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.commons.lang.StringUtils;
19 import org.apache.log4j.Logger;
20 import org.kuali.rice.core.api.CoreConstants;
21 import org.kuali.rice.core.api.config.CoreConfigHelper;
22 import org.kuali.rice.core.api.config.property.Config;
23 import org.kuali.rice.core.api.config.property.ConfigContext;
24 import org.kuali.rice.core.api.util.ClassLoaderUtils;
25 import org.kuali.rice.core.api.util.ContextClassLoaderBinder;
26 import org.kuali.rice.core.api.util.xml.XmlException;
27
28 import javax.xml.namespace.QName;
29 import java.io.File;
30 import java.io.FileNotFoundException;
31 import java.io.IOException;
32 import java.net.MalformedURLException;
33 import java.net.URL;
34
35
36
37
38
39
40
41
42
43 public abstract class BasePluginLoader implements PluginLoader {
44 private static final Logger LOG = Logger.getLogger(BasePluginLoader.class);
45
46 private static final String META_INF_PATH = "META-INF";
47 private static final String PLUGIN_CONFIG_PATH = META_INF_PATH + "/workflow.xml";
48
49 protected final String simplePluginName;
50 protected String logPrefix;
51
52 protected final ClassLoader parentClassLoader;
53 protected final Config parentConfig;
54 protected final File sharedPluginDirectory;
55 protected String pluginConfigPath = PLUGIN_CONFIG_PATH;
56
57 public BasePluginLoader(String simplePluginName, File sharedPluginDirectory, ClassLoader parentClassLoader, Config parentConfig) {
58 this.sharedPluginDirectory = sharedPluginDirectory;
59 if (parentClassLoader == null) {
60 parentClassLoader = ClassLoaderUtils.getDefaultClassLoader();
61 }
62 this.parentClassLoader = parentClassLoader;
63 this.parentConfig = parentConfig;
64 this.simplePluginName = simplePluginName;
65 this.logPrefix = simplePluginName;
66 }
67
68 protected String getLogPrefix() {
69 return logPrefix;
70 }
71
72 public String getPluginName() {
73 return simplePluginName;
74 }
75
76 public void setPluginConfigPath(String pluginConfigPath) {
77 this.pluginConfigPath = pluginConfigPath;
78 }
79
80 protected String getSimplePluginName() {
81 return simplePluginName;
82 }
83
84
85
86
87
88
89
90 protected abstract PluginClassLoader createPluginClassLoader() throws IOException;
91
92
93
94
95
96
97 protected abstract URL getPluginConfigURL() throws PluginException, IOException;
98
99
100
101
102 public Plugin load() throws Exception {
103 PluginClassLoader classLoader = createPluginClassLoader();
104 LOG.info("Created plugin ClassLoader: " + classLoader);
105 ContextClassLoaderBinder.bind(classLoader);
106 try {
107 return loadWithinContextClassLoader(classLoader);
108 } finally {
109 ContextClassLoaderBinder.unbind();
110 }
111 }
112
113 public boolean isRemoved() {
114 return false;
115 }
116
117
118
119
120 protected Plugin loadWithinContextClassLoader(PluginClassLoader classLoader) throws PluginException, IOException {
121 URL url = getPluginConfigURL();
122 PluginConfig pluginConfig = loadPluginConfig(url);
123 QName qPluginName = getPluginName(pluginConfig);
124 classLoader.setConfig(pluginConfig);
125 ConfigContext.init(classLoader, pluginConfig);
126 configureExtraClasspath(classLoader, pluginConfig);
127 this.logPrefix = PluginUtils.getLogPrefix(qPluginName).toString();
128 LOG.info("Constructing plugin '" + simplePluginName + "' with classloader: " + classLoader);
129 Plugin plugin = new Plugin(qPluginName, pluginConfig, classLoader);
130 installResourceLoader(plugin);
131 installPluginListeners(plugin);
132 return plugin;
133 }
134
135 protected void installResourceLoader(Plugin plugin) {
136 PluginUtils.installResourceLoader(plugin);
137 }
138
139 protected void installPluginListeners(Plugin plugin) {
140 PluginUtils.installPluginListeners(plugin);
141 }
142
143 protected void configureExtraClasspath(PluginClassLoader classLoader, PluginConfig config) throws MalformedURLException {
144 String extraClassesDirs = config.getProperty(Config.EXTRA_CLASSES_DIR);
145 if (!org.apache.commons.lang.StringUtils.isEmpty(extraClassesDirs)) {
146 String[] extraClasses = extraClassesDirs.split(",");
147 for (int index = 0; index < extraClasses.length; index++) {
148 File extraClassesDir = new File(extraClasses[index]);
149 if (extraClassesDir.exists()) {
150 classLoader.addClassesDirectory(extraClassesDir);
151 }
152 }
153 }
154 String extraLibDirs = config.getProperty(Config.EXTRA_LIB_DIR);
155 if (!org.apache.commons.lang.StringUtils.isEmpty(extraLibDirs)) {
156 String[] extraLibs = extraLibDirs.split(",");
157 for (int index = 0; index < extraLibs.length; index++) {
158 File extraLibDir = new File(extraLibs[index]);
159 if (extraLibDir.exists()) {
160 classLoader.addLibDirectory(extraLibDir);
161 }
162 }
163 }
164 }
165
166
167 protected QName getPluginName(PluginConfig pluginConfig) {
168 String applicationId = pluginConfig.getProperty(CoreConstants.Config.APPLICATION_ID);
169 QName qPluginName = null;
170 if (StringUtils.isBlank(applicationId)) {
171 qPluginName = new QName(CoreConfigHelper.getApplicationId(), simplePluginName);
172 } else {
173 qPluginName = new QName(applicationId, simplePluginName);
174 }
175 return qPluginName;
176 }
177
178 protected PluginConfig loadPluginConfig(URL url) {
179 PluginConfigParser parser = new PluginConfigParser();
180 try {
181 PluginConfig pluginConfig = parser.parse(url, parentConfig);
182 pluginConfig.parseConfig();
183 return pluginConfig;
184 } catch (FileNotFoundException e) {
185 throw new PluginException(getLogPrefix() + " Could not locate the plugin config file at path " + url, e);
186 } catch (IOException ioe) {
187 throw new PluginException(getLogPrefix() + " Could not read the plugin config file", ioe);
188 } catch (XmlException ixe) {
189 throw new PluginException(getLogPrefix() + " Could not parse the plugin config file", ixe);
190 }
191 }
192 }