001/** 002 * Copyright 2005-2016 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.kew.plugin; 017 018/** 019 * A PluginEnvironment represents a Plugin and the PluginLoader from which it was loaded. 020 * Grouping these together allows us to execute a reload of the Plugin since the Plugin 021 * itself is not responsible for handling how it's own loading or reloading. 022 * 023 * <p>The PluginEnvironment also keeps a reference to the PluginRegistry because this 024 * allows it to add and remove Plugins as child resource loaders of the registry. 025 * 026 * @author Kuali Rice Team (rice.collab@kuali.org) 027 */ 028public class PluginEnvironment implements Reloadable { 029 030 private boolean loaded = false; 031 private Plugin plugin; 032 private final PluginLoader loader; 033 private final PluginRegistry registry; 034 private boolean suppressStartupFailure = true; 035 036 /** 037 * Constructs an unloaded PluginEnvironment from the given PluginLoader and PluginRegistry. 038 * The environment will not be loaded until the first time that load() is executed. 039 */ 040 public PluginEnvironment(PluginLoader loader, PluginRegistry registry) { 041 this.loader = loader; 042 this.registry = registry; 043 } 044 045 /** 046 * Constructs a PluginEnvironment representing the given loaded Plugin. Environments created 047 * in this manner will indicate that they are loaded from the moment they are constructed. 048 */ 049 public PluginEnvironment(Plugin plugin, PluginLoader loader, PluginRegistry registry) { 050 this(loader, registry); 051 this.plugin = plugin; 052 this.loaded = true; 053 } 054 055 /** 056 * Returns true if this environment has been loaded, false otherwise. If this method returns 057 * false then getPlugin() may return null if the environment was never loaded after construction. 058 */ 059 public boolean isLoaded() { 060 return loaded; 061 } 062 063 /** 064 * Returns a boolean indicating whether or not this PluginEnvironment is truly reloadable. 065 * 066 * This will return false if the Plugin represents a plugin which can not be reloaded. 067 */ 068 public boolean isReloadable() { 069 return true; 070 } 071 072 /** 073 * Indicates whether or not a reload of this environment is needed. If this method 074 * returns true, it should continue to return true until a reload() is executed. 075 */ 076 public synchronized boolean isReloadNeeded() { 077 return loader.isModified(); 078 } 079 080 /** 081 * Reloads the environment by effectively executing an unload() followed by a load(). 082 */ 083 public synchronized void reload() throws Exception { 084 unload(); 085 load(); 086 } 087 088 /** 089 * Loads the plugin from the PluginLoader. This will also start the Plugin and add it 090 * to the PluginRegistry's resoure loaders. 091 */ 092 public synchronized void load() throws Exception { 093 plugin = loader.load(); 094 plugin.setSuppressStartupFailure(suppressStartupFailure); 095 // it's important that the plugin is added to the resource loading system prior to startup because 096 // startup may need to grab services 097 registry.addResourceLoader(plugin); 098 plugin.start(); 099 loaded = true; 100 } 101 102 /** 103 * Unloads the plugin. The effectively shuts the plugin down and removes it from the 104 * PluginRegistry's resource loaders. 105 * @throws Exception 106 */ 107 public synchronized void unload() throws Exception { 108 if (plugin != null) { 109 plugin.stop(); 110 // it's important that the plugin be removed from the resource loading system after shutdown in 111 // case the plugin needs to access the resource loader during shutdown 112 registry.removeResourceLoader(plugin.getName()); 113 } 114 loaded = false; 115 } 116 117 public String getPluginName() { 118 if (getPlugin() != null) { 119 return getPlugin().getName().getLocalPart(); 120 } 121 return loader.getPluginName(); 122 } 123 124 /** 125 * Gets the Plugin represented by this environment. May be null if this environment has not 126 * yet been loaded. 127 */ 128 public Plugin getPlugin() { 129 return plugin; 130 } 131 132 /** 133 * Gets the PluginLoader which loaded the Plugin in this environment. 134 */ 135 public PluginLoader getLoader() { 136 return loader; 137 } 138 139 /** 140 * By default, startup failure is suppressed. If it is indicated that startup failure 141 * suppression is not desired, then startup errors will be thrown directly from calls to 142 * load(). 143 */ 144 public void setSuppressStartupFailure(boolean suppressStartupFailure) { 145 this.suppressStartupFailure = suppressStartupFailure; 146 } 147 148}