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.IOException;
21  import java.net.MalformedURLException;
22  import java.net.URL;
23  import java.net.URLClassLoader;
24  import java.util.Enumeration;
25  
26  import org.kuali.rice.core.lifecycle.Lifecycle;
27  import org.kuali.rice.kew.util.SimpleEnumeration;
28  
29  
30  /**
31   * A simple class loader implementation which looks at itself before delegating to its parent.
32   *
33   * @author Kuali Rice Team (rice.collab@kuali.org)
34   */
35  public class PluginClassLoader extends URLClassLoader implements Lifecycle {//implements Modifiable {
36      static final String CLASSES_DIR = "classes";
37      static final String LIB_DIR = "lib";
38      private static final String[] SYSTEM_CLASSES = new String[] { "java.", "javax.servlet.", "javax.xml.", "javax.management.", "org.xml.", "org.w3c." };
39  
40      //private ModificationTracker modTracker = new ModificationTracker();
41      //this is purposely typed.
42      private PluginConfig config;
43      private boolean started = false;
44  
45      public PluginClassLoader() {
46          super(new URL[0]);
47      }
48  
49      public PluginClassLoader(ClassLoader parent) {
50          super(new URL[0], parent);
51      }
52  
53      public PluginClassLoader(ClassLoader parent, File sharedDirectory, File pluginDirectory) throws MalformedURLException {
54          super(new URL[0], parent);
55          if (sharedDirectory != null) {
56              addClassesDirectory(new File(sharedDirectory, CLASSES_DIR));
57              addLibDirectory(new File(sharedDirectory, LIB_DIR));
58          }
59          addClassesDirectory(new File(pluginDirectory, CLASSES_DIR));
60          addLibDirectory(new File(pluginDirectory, LIB_DIR));
61      }
62  
63      public void addClassesDirectory(File classesDir) throws MalformedURLException {
64          if (classesDir != null && classesDir.isDirectory()) {
65              addURL(classesDir.toURL());
66          }
67      }
68  
69      public void addLibDirectory(File libDir) throws MalformedURLException {
70          File[] jars = PluginUtils.findJars(libDir);
71          for (int index = 0; index < jars.length; index++) {
72              addURL(jars[index].toURL());
73          }
74      }
75  
76      public Class loadClass(String className) throws ClassNotFoundException {
77          return loadClass(className, false);
78      }
79  
80      public void addURL(URL url) {
81          super.addURL(url);
82          //modTracker.addURL(url);
83      }
84  
85      //public boolean isModified() {
86      //    return modTracker.isModified();
87      //}
88  
89      public synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
90          Class loadedClass = loadExistingClass(name, resolve);
91          if (loadedClass != null) {
92              return loadedClass;
93          }
94          loadedClass = loadSystemClass(name, resolve);
95          if (loadedClass != null) {
96              return loadedClass;
97          }
98          loadedClass = loadLocalClass(name, resolve);
99          if (loadedClass != null) {
100             return loadedClass;
101         }
102         loadedClass = loadParentClass(name, resolve);
103         if (loadedClass != null) {
104             return loadedClass;
105         }
106         throw new ClassNotFoundException(name);
107     }
108 
109     public URL getResource(String name) {
110         URL resource = findResource(name);
111         if (resource == null) {
112             resource = getParent().getResource(name);
113         }
114         return resource;
115     }
116 
117     public Enumeration<URL> getResources(String name) throws IOException {
118     	Enumeration<URL> localResources = findResources(name);
119     	Enumeration<URL> parentResources = getParent().getResources(name);
120     	return new SimpleEnumeration<URL>(localResources, parentResources);
121     }
122 
123 
124 
125     private Class loadExistingClass(String name, boolean resolve) {
126         Class loadedClass = findLoadedClass(name);
127         if (loadedClass != null && resolve) {
128             resolveClass(loadedClass);
129         }
130         return loadedClass;
131     }
132 
133     private Class loadSystemClass(String name, boolean resolve) {
134     	Class loadedClass = null;
135     	if (isSystemClass(name)) {
136     		try {
137     			loadedClass = getSystemClassLoader().loadClass(name);
138     			if (loadedClass != null && resolve) {
139     				resolveClass(loadedClass);
140     			}
141     		} catch (ClassNotFoundException e) {
142     			// not found in system class loader
143     		}
144     	}
145 		return loadedClass;
146     }
147 
148     private Class loadLocalClass(String name, boolean resolve) {
149         Class loadedClass = null;
150         try {
151             loadedClass = findClass(name);
152             if (loadedClass != null && resolve) {
153                 resolveClass(loadedClass);
154             }
155         } catch (ClassNotFoundException e) {
156             // not found locally
157         }
158         return loadedClass;
159     }
160 
161     private Class loadParentClass(String name, boolean resolve) {
162         Class loadedClass = null;
163         try {
164             loadedClass = getParent().loadClass(name);
165             if (loadedClass != null && resolve) {
166                 resolveClass(loadedClass);
167             }
168         } catch (ClassNotFoundException e) {
169             // not found in parent
170         }
171         return loadedClass;
172     }
173 
174     /**
175      * This method modeled on the isSystemPath method in Jetty's ContextLoader.
176      *
177      * When loading classes from the system classloader, we really only want to load certain classes
178      * from there so this will tell us whether or not the class name given is one we want to load
179      * from the system classloader.
180      */
181     private boolean isSystemClass(String name) {
182     	name = name.replace('/','.');
183         while(name.startsWith(".")) {
184         	name=name.substring(1);
185         }
186         for (int index = 0; index < SYSTEM_CLASSES.length; index++) {
187         	String systemClass = SYSTEM_CLASSES[index];
188         	if (systemClass.endsWith(".")) {
189         		if (name.startsWith(systemClass)) {
190         			return true;
191         		}
192         	}
193         	else if (name.equals(systemClass)) {
194         		return true;
195         	}
196         }
197         return false;
198     }
199 
200     public String toString() {
201         StringBuffer sb = new StringBuffer("[PluginClassLoader: urls=");
202         URL[] urls = getURLs();
203         if (urls == null) {
204             sb.append("null");
205         } else {
206             for (int i = 0; i < urls.length; i++) {
207                 sb.append(urls[i]);
208                 sb.append(",");
209             }
210             // remove trailing comma
211             if (urls.length > 1) {
212                 sb.setLength(sb.length() - 1);
213             }
214         }
215         sb.append("]");
216         return sb.toString();
217     }
218 
219 	public PluginConfig getConfig() {
220 		return config;
221 	}
222 
223 	public void setConfig(PluginConfig config) {
224 		this.config = config;
225 	}
226 
227 	public void start() {
228 		started = true;
229 	}
230 
231 	public void stop() {
232 		config = null;
233 		started = false;
234 	}
235 
236 	public boolean isStarted() {
237 		return started;
238 	}
239 }