001 /**
002 * Copyright 2005-2013 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 */
016 package 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 */
028 public 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 supressStartupFailure = 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.setSupressStartupFailure(supressStartupFailure);
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 supressed. If it is indicated that startup failure
141 * supression is not desired, then startup errors will be thrown directly from calls to
142 * load().
143 */
144 public void setSupressStartupFailure(boolean supressStartupFailure) {
145 this.supressStartupFailure = supressStartupFailure;
146 }
147
148 }