1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.plugin;
17
18 import org.apache.log4j.Logger;
19 import org.kuali.rice.core.api.config.property.Config;
20 import org.kuali.rice.core.api.util.ContextClassLoaderBinder;
21 import org.kuali.rice.core.impl.resourceloader.BaseWrappingResourceLoader;
22 import org.kuali.rice.kew.api.WorkflowRuntimeException;
23
24 import javax.xml.namespace.QName;
25 import java.util.ArrayList;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.concurrent.Callable;
29
30
31
32
33
34
35
36
37 public class Plugin extends BaseWrappingResourceLoader {
38
39 private static final Logger LOG = Logger.getLogger(Plugin.class);
40 private Config config;
41 private List<PluginListener> pluginListeners = new ArrayList<PluginListener>();
42
43 private boolean suppressStartupFailure = true;
44 private boolean started = false;
45 private boolean startupFailure = false;
46
47 public Plugin(QName name, Config config, ClassLoader classLoader) {
48 super(name, classLoader);
49 this.config = config;
50 }
51
52
53
54
55 public synchronized void start() {
56 if (started) {
57 LOG.info(getLogPrefix()+" has already been started.");
58 return;
59 }
60 LOG.info(getLogPrefix()+" Starting...");
61 try {
62 ContextClassLoaderBinder.doInContextClassLoader(getClassLoader(), new Callable() {
63 @Override
64 public Object call() throws Exception {
65 startupFailure = false;
66 started = true;
67 Plugin.super.start();
68 LOG.info("Starting plugin listeners");
69 startPluginListeners();
70 return null;
71 }
72 });
73 ClassLoader classLoader = getClassLoader();
74 LOG.info(getLogPrefix()+" ...started." + (classLoader != null ? classLoader.toString() : ""));
75 } catch (Throwable t) {
76 LOG.error(getLogPrefix()+" Failure starting plugin.", t);
77 startupFailure = true;
78 started = true;
79 stop();
80 if (!suppressStartupFailure) {
81 if (t instanceof Error) {
82 throw (Error)t;
83 } else if (t instanceof RuntimeException) {
84 throw (RuntimeException)t;
85 }
86 throw new WorkflowRuntimeException("Failed to startup plugin.", t);
87 }
88 }
89 }
90
91
92
93
94 public synchronized void stop() {
95 if (!started) {
96 LOG.info(getLogPrefix()+" has already been stopped.");
97 return;
98 }
99 LOG.info(getLogPrefix()+" Stopping...");
100 try {
101 ContextClassLoaderBinder.doInContextClassLoader(getClassLoader(), new Callable() {
102 @Override
103 public Object call() throws Exception {
104 started = false;
105 stopPluginListeners();
106
107 Plugin.super.stop();
108 return null;
109 }
110 });
111 } catch (Throwable t) {
112 LOG.error(getLogPrefix()+" Failed when attempting to stop the plugin.", t);
113 }
114 resetPlugin();
115 LOG.info(getLogPrefix()+" ...stopped.");
116 }
117
118 public boolean isStarted() {
119 return started;
120 }
121
122 public void addPluginListener(PluginListener pluginListener) {
123 pluginListeners.add(pluginListener);
124 }
125
126 public void removePluginListener(PluginListener pluginListener) {
127 pluginListeners.remove(pluginListener);
128 }
129
130 protected void startPluginListeners() {
131 for (Iterator iterator = pluginListeners.iterator(); iterator.hasNext();) {
132 PluginListener listener = (PluginListener) iterator.next();
133 listener.pluginInitialized(this);
134 }
135 }
136
137
138
139
140
141
142 protected void stopPluginListeners() {
143 for (Iterator iterator = pluginListeners.iterator(); iterator.hasNext();) {
144 PluginListener listener = (PluginListener) iterator.next();
145 try {
146 listener.pluginDestroyed(this);
147 } catch (Throwable t) {
148 LOG.error(getLogPrefix()+" Failed when invoking pluginDestroyed on Plugin Listener '"+listener.getClass().getName()+"'.", t);
149 }
150 }
151 }
152
153 public boolean isSuppressStartupFailure() {
154 return suppressStartupFailure;
155 }
156
157 public void setSuppressStartupFailure(boolean suppressStartupFailure) {
158 this.suppressStartupFailure = suppressStartupFailure;
159 }
160
161
162
163
164 private void resetPlugin() {
165 if (!startupFailure) {
166 setClassLoader(null);
167 }
168 pluginListeners.clear();
169 }
170
171 private String getLogPrefix() {
172 return toString();
173 }
174
175 public Config getConfig() {
176 return config;
177 }
178
179 public String toString() {
180 return "[Plugin: " + this.getName() + "]";
181 }
182
183 }