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