001: /*
002: * Copyright 2005-2006 The Kuali Foundation.
003: *
004: *
005: * Licensed under the Educational Community License, Version 1.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.opensource.org/licenses/ecl1.php
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package edu.iu.uis.eden.plugin;
018:
019: import java.io.File;
020: import java.io.FileFilter;
021: import java.io.FilenameFilter;
022: import java.util.Iterator;
023: import java.util.List;
024:
025: import javax.xml.namespace.QName;
026:
027: import org.apache.commons.lang.StringUtils;
028: import org.apache.log4j.Logger;
029: import org.kuali.rice.config.Config;
030: import org.kuali.rice.core.Core;
031: import org.kuali.rice.resourceloader.BaseResourceLoader;
032: import org.kuali.rice.resourceloader.GlobalResourceLoader;
033: import org.kuali.rice.resourceloader.ResourceLoader;
034: import org.kuali.rice.resourceloader.ResourceLoaderUtil;
035:
036: import edu.iu.uis.eden.core.CoreResourceLoader;
037: import edu.iu.uis.eden.plugin.client.PluginListener;
038: import edu.iu.uis.eden.plugin.manifest.PluginManifest;
039:
040: /**
041: * Various plugin utilities.
042: *
043: * @author Aaron Hamid (arh14 at cornell dot edu)
044: */
045: public final class PluginUtils {
046:
047: private static final Logger LOG = Logger
048: .getLogger(PluginUtils.class);
049: private static final String SHARED_DIR = "shared";
050:
051: // maximum time we should wait for a new plugin directory to stop being
052: // modified before we give up on loading it this time around
053: public static final long INFINITE_MAX_WAIT = -1;
054: // NOTE: must be greater than the SAFE TIME
055: public static final long DEFAULT_MAX_WAIT = 90000;
056:
057: // amount of time since the last time the plugin dir was updated that we
058: // consider "safe" to proceed with registering the plugin
059: // basically, with the current implementation, an amount of time that we
060: // expect any files in process of modification to complete (e.g. copy)
061: // NOTE: MUST be LESS than the MAX WAIT otherwise, we will ALWAYS fail to wait
062: public static final long DEFAULT_SAFE_TIME = 60000;
063:
064: public static final String DEFAULT_INSTITUTIONAL_PLUGIN_NAME = "en";
065:
066: private static final FilenameFilter JAR_FILES_FILTER = new FilenameFilter() {
067: public boolean accept(File dir, String name) {
068: return name.matches(".+\\.jar");
069: }
070: };
071:
072: private static final FileFilter SHARED_DIR_FILTER = new FileFilter() {
073: public boolean accept(File file) {
074: return file.isDirectory()
075: && file.getName().equals(SHARED_DIR);
076: }
077: };
078:
079: public static class PluginDirectoryFilter implements FileFilter {
080: private final File sharedPluginDirectory;
081:
082: public PluginDirectoryFilter(File sharedPluginDirectory) {
083: this .sharedPluginDirectory = sharedPluginDirectory;
084: }
085:
086: public boolean accept(File file) {
087: return file.isDirectory()
088: && !file.getName().equalsIgnoreCase("cvs")
089: && (sharedPluginDirectory == null || !file
090: .getName().equals(
091: sharedPluginDirectory.getName()));
092: }
093: }
094:
095: public static class PluginZipFileFilter implements FileFilter {
096: public boolean accept(File file) {
097: return file.isFile() && file.getName().endsWith(".zip");
098: }
099: }
100:
101: public static String getLogPrefix(Plugin plugin) {
102: return getLogPrefix(plugin.getName(),
103: isInstitutionalPlugin(plugin));
104: }
105:
106: public static String getLogPrefix(QName pluginName,
107: boolean institutionalPlugin) {
108: return "[" + (institutionalPlugin ? "Institutional " : "")
109: + "Plugin: " + pluginName + "]";
110: }
111:
112: static File[] findJars(File libDir) {
113: File[] jarFiles = new File[0];
114: if (libDir.isDirectory()) {
115: jarFiles = libDir.listFiles(JAR_FILES_FILTER);
116: }
117: return jarFiles;
118: }
119:
120: public static File findSharedDirectory(List pluginDirectories) {
121: for (Iterator iterator = pluginDirectories.iterator(); iterator
122: .hasNext();) {
123: File dir = new File((String) iterator.next());
124: if (dir.isDirectory()) {
125: File[] subDirs = dir.listFiles(SHARED_DIR_FILTER);
126: if (subDirs.length > 0) {
127: return subDirs[0];
128: }
129: }
130: }
131: return null;
132: }
133:
134: public static String getInstitutionalPluginName() {
135: String pluginName = Core.getCurrentContextConfig().getProperty(
136: Config.INSTITUTIONAL_PLUGIN_NAME);
137: if (StringUtils.isEmpty(pluginName)) {
138: pluginName = DEFAULT_INSTITUTIONAL_PLUGIN_NAME;
139: }
140: return pluginName;
141: }
142:
143: public static boolean isInstitutionalPlugin(String pluginName) {
144: return pluginName.equals(getInstitutionalPluginName());
145: }
146:
147: public static boolean isInstitutionalPlugin(QName pluginName) {
148: return isInstitutionalPlugin(pluginName.getLocalPart());
149: }
150:
151: public static boolean isInstitutionalPlugin(Plugin plugin) {
152: return isInstitutionalPlugin(plugin.getName());
153: }
154:
155: public static void validatePluginZipFile(File file) {
156: if (file == null) {
157: throw new IllegalArgumentException(
158: "Given plugin file was 'null'");
159: } else if (!file.exists()) {
160: throw new IllegalArgumentException(
161: "Given plugin file does not exist: "
162: + file.getAbsolutePath());
163: } else if (!file.isFile()) {
164: throw new IllegalArgumentException(
165: "Given plugin file is not a valid file: "
166: + file.getAbsolutePath());
167: } else if (!file.canRead()) {
168: throw new IllegalArgumentException(
169: "Permission denied to read given plugin file: "
170: + file.getAbsolutePath());
171: } else if (!file.getName().endsWith(".zip")) {
172: throw new IllegalArgumentException(
173: "Given plugin file does not end in .zip extension: "
174: + file.getAbsolutePath());
175: }
176: // now look at the directory the plugin file is in because we need to be able to extract it there
177: File pluginDirectory = file.getParentFile();
178: validatePluginDirectory(pluginDirectory);
179: // also verify that we can write to this directory
180: if (pluginDirectory == null) {
181: throw new IllegalArgumentException(
182: "Given plugin directory was 'null'");
183: } else if (!pluginDirectory.canWrite()) {
184: throw new IllegalArgumentException(
185: "Impossible to write to plugin directory so plugin cannot be expanded: "
186: + pluginDirectory.getAbsolutePath());
187: }
188: }
189:
190: public static void validatePluginDirectory(File directory) {
191: if (directory == null) {
192: throw new IllegalArgumentException(
193: "Given directory was 'null'");
194: } else if (!directory.exists()) {
195: throw new IllegalArgumentException(
196: "Given directory does not exist: "
197: + directory.getAbsolutePath());
198: } else if (!directory.isDirectory()) {
199: throw new IllegalArgumentException(
200: "Given plugin directory is not a valid directory: "
201: + directory.getAbsolutePath());
202: } else if (!directory.canRead()) {
203: throw new IllegalArgumentException(
204: "Permission denied to read given plugin directory: "
205: + directory.getAbsolutePath());
206: }
207: }
208:
209: public static PluginRegistry getPluginRegistry() {
210: return ((CoreResourceLoader) GlobalResourceLoader
211: .getResourceLoader(CoreResourceLoader.NAME))
212: .getRegistry();
213: }
214:
215: public static void installResourceLoader(Plugin plugin) {
216: if (plugin.getConfig() instanceof PluginManifest) {
217: PluginManifest pluginManifest = (PluginManifest) plugin
218: .getConfig();
219: if (!StringUtils.isEmpty(pluginManifest
220: .getResourceLoaderClassname())) {
221: ResourceLoader resourceLoader = (ResourceLoader) ResourceLoaderUtil
222: .createObject(pluginManifest
223: .getResourceLoaderClassname(), plugin
224: .getClassLoader());
225: if (resourceLoader == null) {
226: LOG
227: .warn("Could not create resource loader from plugin resource loader class: "
228: + pluginManifest
229: .getResourceLoaderClassname());
230: // if null, use a default resource loader
231: resourceLoader = new BaseResourceLoader(plugin
232: .getName());
233: }
234: plugin.addResourceLoader(resourceLoader);
235: }
236: }
237: }
238:
239: public static void installPluginListeners(Plugin plugin) {
240: if (plugin.getConfig() instanceof PluginManifest) {
241: PluginManifest pluginManifest = (PluginManifest) plugin
242: .getConfig();
243: for (Iterator iterator = pluginManifest.getListeners()
244: .iterator(); iterator.hasNext();) {
245: String pluginListenerClassName = (String) iterator
246: .next();
247: try {
248: Class listenerClass = Class.forName(
249: pluginListenerClassName, true, plugin
250: .getClassLoader());
251: plugin
252: .addPluginListener((PluginListener) listenerClass
253: .newInstance());
254: } catch (ClassNotFoundException e) {
255: throw new PluginException(getLogPrefix(plugin)
256: + " Error finding listener class '"
257: + pluginListenerClassName + "'.", e);
258: } catch (InstantiationException e) {
259: throw new PluginException(
260: getLogPrefix(plugin)
261: + " Error creating an instance of listener class '"
262: + pluginListenerClassName + "'.", e);
263: } catch (IllegalAccessException e) {
264: throw new PluginException(
265: getLogPrefix(plugin)
266: + " Error creating an instance of listener class '"
267: + pluginListenerClassName + "'.", e);
268: } catch (ClassCastException e) {
269: throw new PluginException(getLogPrefix(plugin)
270: + " Listener class '"
271: + pluginListenerClassName
272: + "' does not implement PluginListener.", e);
273: }
274: }
275: }
276: }
277:
278: private PluginUtils() { /* prevent construction */
279: }
280: }
|