View Javadoc

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