View Javadoc

1   /*
2    * Copyright 2005-2007 The Kuali Foundation
3    *
4    *
5    * Licensed under the Educational Community License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    * http://www.opensource.org/licenses/ecl2.php
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.kuali.rice.kew.plugin;
18  
19  import java.io.File;
20  import java.io.FileFilter;
21  import java.io.FilenameFilter;
22  import java.util.Iterator;
23  import java.util.List;
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.config.Config;
30  import org.kuali.rice.core.config.ConfigContext;
31  import org.kuali.rice.core.resourceloader.BaseResourceLoader;
32  import org.kuali.rice.core.resourceloader.GlobalResourceLoader;
33  import org.kuali.rice.core.resourceloader.ResourceLoader;
34  import org.kuali.rice.core.resourceloader.ResourceLoaderUtil;
35  import org.kuali.rice.kew.resourceloader.CoreResourceLoader;
36  
37  
38  /**
39   * Various plugin utilities.
40   *
41   * @author Kuali Rice Team (rice.collab@kuali.org)
42   */
43  public final class PluginUtils {
44  
45      private static final Logger LOG = Logger.getLogger(PluginUtils.class);
46      private static final String SHARED_DIR = "shared";
47  
48      // maximum time we should wait for a new plugin directory to stop being
49      // modified before we give up on loading it this time around
50      public static final long INFINITE_MAX_WAIT = -1;
51      // NOTE: must be greater than the SAFE TIME
52      public static final long DEFAULT_MAX_WAIT = 90000;
53  
54      // amount of time since the last time the plugin dir was updated that we
55      // consider "safe" to proceed with registering the plugin
56      // basically, with the current implementation, an amount of time that we
57      // expect any files in process of modification to complete (e.g. copy)
58      // NOTE: MUST be LESS than the MAX WAIT otherwise, we will ALWAYS fail to wait
59      public static final long DEFAULT_SAFE_TIME = 60000;
60  
61      private static final FilenameFilter JAR_FILES_FILTER = new FilenameFilter() {
62          public boolean accept(File dir, String name) {
63              return name.matches(".+\\.jar");
64          }
65      };
66  
67      private static final FileFilter SHARED_DIR_FILTER = new FileFilter() {
68          public boolean accept(File file) {
69              return file.isDirectory() && file.getName().equals(SHARED_DIR);
70          }
71      };
72  
73      public static class PluginDirectoryFilter implements FileFilter {
74          private final File sharedPluginDirectory;
75          public PluginDirectoryFilter(File sharedPluginDirectory) {
76              this.sharedPluginDirectory = sharedPluginDirectory;
77          }
78          public boolean accept(File file) {
79              return file.isDirectory() && !file.getName().equalsIgnoreCase("cvs") &&
80              (sharedPluginDirectory == null ||
81                      !file.getName().equals(sharedPluginDirectory.getName()));
82          }
83      }
84  
85      public static class PluginZipFileFilter implements FileFilter {
86          public boolean accept(File file) {
87              return file.isFile() && file.getName().endsWith(".zip");
88          }
89      }
90  
91      public static String getLogPrefix(Plugin plugin) {
92      	return getLogPrefix(plugin.getName());
93      }
94  
95      public static String getLogPrefix(QName pluginName) {
96      	return "[Plugin: " + pluginName + "]";
97      }
98  
99      static File[] findJars(File libDir) {
100         File[] jarFiles = new File[0];
101         if (libDir.isDirectory()) {
102             jarFiles = libDir.listFiles(JAR_FILES_FILTER);
103         }
104         return jarFiles;
105     }
106 
107     public static File findSharedDirectory(List pluginDirectories) {
108         for (Iterator iterator = pluginDirectories.iterator(); iterator.hasNext();) {
109             File dir = new File((String) iterator.next());
110             if (dir.isDirectory()) {
111                 File[] subDirs = dir.listFiles(SHARED_DIR_FILTER);
112                 if (subDirs.length > 0) {
113                     return subDirs[0];
114                 }
115             }
116         }
117         return null;
118     }
119 
120     public static void validatePluginZipFile(File file) {
121     	if (file == null) {
122 			throw new IllegalArgumentException("Given plugin file was 'null'");
123 		} else if (!file.exists()) {
124 			throw new IllegalArgumentException("Given plugin file does not exist: " + file.getAbsolutePath());
125 		} else if (!file.isFile()) {
126 			throw new IllegalArgumentException("Given plugin file is not a valid file: " + file.getAbsolutePath());
127 		} else if (!file.canRead()) {
128 			throw new IllegalArgumentException("Permission denied to read given plugin file: " + file.getAbsolutePath());
129 		} else if (!file.getName().endsWith(".zip")) {
130 			throw new IllegalArgumentException("Given plugin file does not end in .zip extension: " + file.getAbsolutePath());
131 		}
132     	// now look at the directory the plugin file is in because we need to be able to extract it there
133     	File pluginDirectory = file.getParentFile();
134     	validatePluginDirectory(pluginDirectory);
135     	// also verify that we can write to this directory
136     	if (pluginDirectory == null) {
137     		throw new IllegalArgumentException("Given plugin directory was 'null'");
138     	} else if (!pluginDirectory.canWrite()) {
139     		throw new IllegalArgumentException("Impossible to write to plugin directory so plugin cannot be expanded: " + pluginDirectory.getAbsolutePath());
140     	}
141     }
142 
143     public static void validatePluginDirectory(File directory) {
144     	if (directory == null) {
145 			throw new IllegalArgumentException("Given directory was 'null'");
146 		} else if (!directory.exists()) {
147 			throw new IllegalArgumentException("Given directory does not exist: " + directory.getAbsolutePath());
148 		} else if (!directory.isDirectory()) {
149 			throw new IllegalArgumentException("Given plugin directory is not a valid directory: " + directory.getAbsolutePath());
150 		} else if (!directory.canRead()) {
151 			throw new IllegalArgumentException("Permission denied to read given plugin directory: " + directory.getAbsolutePath());
152 		}
153     }
154 
155     public static PluginRegistry getPluginRegistry() {
156     	return ((CoreResourceLoader)GlobalResourceLoader.getResourceLoader(CoreResourceLoader.NAME)).getRegistry();
157     }
158 
159     public static void installResourceLoader(Plugin plugin) {
160     	if (plugin.getConfig() instanceof PluginConfig) {
161 			PluginConfig pluginConfig = (PluginConfig)plugin.getConfig();
162 			if (!StringUtils.isEmpty(pluginConfig.getResourceLoaderClassname())) {
163                 ResourceLoader resourceLoader = (ResourceLoader) ResourceLoaderUtil.createObject(pluginConfig.getResourceLoaderClassname(), plugin.getClassLoader());
164                 if (resourceLoader == null) {
165                     LOG.warn("Could not create resource loader from plugin resource loader class: " + pluginConfig.getResourceLoaderClassname());
166                     // if null, use a default resource loader
167 					resourceLoader = new BaseResourceLoader(plugin.getName());
168                 }
169 				plugin.addResourceLoader(resourceLoader);
170 			}
171 		}
172     }
173 
174     public static void installPluginListeners(Plugin plugin) {
175     	if (plugin.getConfig() instanceof PluginConfig) {
176 			PluginConfig pluginConfig = (PluginConfig)plugin.getConfig();
177 			for (Iterator iterator = pluginConfig.getListeners().iterator(); iterator.hasNext();) {
178 	            String pluginListenerClassName = (String) iterator.next();
179 	            try {
180 	                Class listenerClass = Class.forName(pluginListenerClassName, true, plugin.getClassLoader());
181 	                plugin.addPluginListener((PluginListener)listenerClass.newInstance());
182 	            } catch (ClassNotFoundException e) {
183 	                throw new PluginException(getLogPrefix(plugin)+" Error finding listener class '"+pluginListenerClassName+"'.", e);
184 	            } catch (InstantiationException e) {
185 	                throw new PluginException(getLogPrefix(plugin)+" Error creating an instance of listener class '"+pluginListenerClassName+"'.", e);
186 	            } catch (IllegalAccessException e) {
187 	                throw new PluginException(getLogPrefix(plugin)+" Error creating an instance of listener class '"+pluginListenerClassName+"'.", e);
188 	            } catch (ClassCastException e) {
189 	                throw new PluginException(getLogPrefix(plugin)+" Listener class '"+pluginListenerClassName+"' does not implement PluginListener.", e);
190 	            }
191 	        }
192 		}
193     }
194 
195     private PluginUtils() { /* prevent construction */}
196 }