79201576049a80014e30b3ebcc31649bb5a7fd29
[guacamole.git] / src / main / java / net / sourceforge / guacamole / net / basic / GuacamoleClassLoader.java
1
2 package net.sourceforge.guacamole.net.basic;
3
4 /* ***** BEGIN LICENSE BLOCK *****
5  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is guacamole-common.
18  *
19  * The Initial Developer of the Original Code is
20  * Michael Jumper.
21  * Portions created by the Initial Developer are Copyright (C) 2010
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Alternatively, the contents of this file may be used under the terms of
27  * either the GNU General Public License Version 2 or later (the "GPL"), or
28  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29  * in which case the provisions of the GPL or the LGPL are applicable instead
30  * of those above. If you wish to allow use of your version of this file only
31  * under the terms of either the GPL or the LGPL, and not to allow others to
32  * use your version of this file under the terms of the MPL, indicate your
33  * decision by deleting the provisions above and replace them with the notice
34  * and other provisions required by the GPL or the LGPL. If you do not delete
35  * the provisions above, a recipient may use your version of this file under
36  * the terms of any one of the MPL, the GPL or the LGPL.
37  *
38  * ***** END LICENSE BLOCK ***** */
39
40 import java.io.File;
41 import java.io.FilenameFilter;
42 import java.net.MalformedURLException;
43 import java.net.URL;
44 import java.net.URLClassLoader;
45 import java.util.ArrayList;
46 import java.util.Collection;
47 import net.sourceforge.guacamole.GuacamoleException;
48 import net.sourceforge.guacamole.net.basic.properties.BasicGuacamoleProperties;
49 import net.sourceforge.guacamole.properties.GuacamoleProperties;
50
51 /**
52  * A ClassLoader implementation which finds classes within a configurable
53  * directory. This directory is set within guacamole.properties.
54  * 
55  * @author Michael Jumper
56  */
57 public class GuacamoleClassLoader extends ClassLoader {
58     
59     private URLClassLoader classLoader = null;
60
61     private static GuacamoleException exception = null;
62     private static GuacamoleClassLoader instance = null;
63     
64     static {
65         
66         try {
67             // Attempt to create singleton classloader which loads classes from
68             // all .jar's in the lib directory defined in guacamole.properties
69             instance = new GuacamoleClassLoader(
70                 GuacamoleProperties.getProperty(BasicGuacamoleProperties.LIB_DIRECTORY)
71             );
72         }
73         
74         catch (GuacamoleException e) {
75             // On error, record exception
76             exception = e;
77         }
78         
79     }
80
81     private GuacamoleClassLoader(File libDirectory) throws GuacamoleException {
82
83         // If no directory provided, just direct requests to parent classloader
84         if (libDirectory == null)
85             return;
86         
87         // Validate directory is indeed a directory
88         if (!libDirectory.isDirectory())
89             throw new GuacamoleException(libDirectory + " is not a directory.");
90         
91         // Get list of URLs for all .jar's in the lib directory
92         Collection<URL> jarURLs = new ArrayList<URL>();
93         for (File file : libDirectory.listFiles(new FilenameFilter() {
94
95             @Override
96             public boolean accept(File dir, String name) {
97                 
98                 // If it ends with .jar, accept the file
99                 return name.endsWith(".jar");
100                 
101             }
102
103         })) {
104
105             try {
106                 
107                 // Add URL for the .jar to the jar URL list
108                 jarURLs.add(file.toURI().toURL());
109                 
110             }
111             catch (MalformedURLException e) {
112                 throw new GuacamoleException(e);
113             }
114                 
115         }
116         
117         // Set delegate classloader to new URLClassLoader which loads from the
118         // .jars found above.
119
120         URL[] urls = new URL[jarURLs.size()];
121         classLoader = new URLClassLoader(
122             jarURLs.toArray(urls),
123             getClass().getClassLoader()
124         );
125         
126     }
127
128     /**
129      * Returns an instance of a GuacamoleClassLoader which finds classes
130      * within the directory configured in guacamole.properties.
131      * 
132      * @return An instance of a GuacamoleClassLoader.
133      * @throws GuacamoleException If no instance could be returned due to an
134      *                            error.
135      */
136     public static GuacamoleClassLoader getInstance() throws GuacamoleException {
137         
138         // If instance could not be created, rethrow original exception
139         if (exception != null) throw exception;
140         
141         return instance;
142
143     }
144
145     @Override
146     protected Class<?> findClass(String name) throws ClassNotFoundException {
147
148         // If no classloader, use default loader
149         if (classLoader == null)
150             return Class.forName(name);
151         
152         // Otherwise, delegate
153         return classLoader.loadClass(name);
154
155     }
156
157 }