source: trunk/src/org/expeditee/reflection/PackageLoader.java@ 919

Last change on this file since 919 was 919, checked in by jts21, 10 years ago

Added license headers to all files, added full GPL3 license file, moved license header generator script to dev/bin/scripts

File size: 9.6 KB
Line 
1/**
2 * PackageLoader.java
3 * Copyright (C) 2010 New Zealand Digital Library, http://expeditee.org
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package org.expeditee.reflection;
20
21import java.io.File;
22import java.io.IOException;
23import java.net.JarURLConnection;
24import java.net.URI;
25import java.net.URL;
26import java.net.URLConnection;
27import java.util.ArrayList;
28import java.util.Enumeration;
29import java.util.LinkedList;
30import java.util.List;
31import java.util.jar.JarEntry;
32import java.util.jar.JarFile;
33import java.util.zip.ZipEntry;
34
35
36public class PackageLoader {
37
38 // The following is adapted from:
39 // http://stackoverflow.com/questions/1456930/how-do-i-read-all-classes-from-a-java-package-in-the-classpath
40
41 public static List<Class<?>> getClassesNew(String packageName)
42 throws ClassNotFoundException {
43
44 ClassLoader classLoader = Thread.currentThread()
45 .getContextClassLoader();
46
47 ArrayList<String> names = new ArrayList<String>();
48 ;
49 final ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
50
51 String realPackageName = packageName;
52 packageName = packageName.replace(".", "/");
53 URL packageURL = classLoader.getResource(packageName);
54
55 if (packageURL.getProtocol().equals("jar")) {
56
57 // build jar file name, then loop through zipped entries
58
59 String jarFileNameUndecoded = packageURL.getFile();
60
61 try {
62 JarURLConnection ju_connection = (JarURLConnection) packageURL
63 .openConnection();
64 JarFile jf = ju_connection.getJarFile();
65
66 Enumeration<JarEntry> jarEntries = jf.entries();
67 while (jarEntries.hasMoreElements()) {
68 String entryName = jarEntries.nextElement().getName();
69
70 if (entryName.startsWith(packageName)) {
71
72 if (entryName.endsWith(".class")
73 && !entryName.contains("$")) {
74
75 // Deal with situation where the class found might
76 // be a further sub-package
77 // e.g. for "org.expeditee.action"
78 // there is:
79 // org/expeditee/action/widgets/Chart.class
80 // which would produce a value of 'entryName' as
81 // widgets/Chart.class
82
83 entryName = entryName.substring(0,
84 entryName.length() - 6); // 6 = '.class'
85 entryName = entryName.replace('/', '.');
86
87 names.add(entryName);
88 classes.add(Class.forName(entryName));
89 }
90 }
91 }
92 } catch (Exception e) {
93 System.err.println("Failed to decode jar file: "
94 + jarFileNameUndecoded);
95 e.printStackTrace();
96 }
97 } else if (packageURL.getProtocol().equals("bundleresource")) {
98 try {
99 final URLConnection urlConnection = packageURL.openConnection();
100 final Class<?> c = urlConnection.getClass();
101 final java.lang.reflect.Method toInvoke = c.getMethod("getFileURL");
102 final URL fileURL = (URL)toInvoke.invoke(urlConnection);
103 final File folder = new File(fileURL.getFile());
104 final List<String> files = findFiles(folder);
105 for (final String s : files) {
106 String entryName = realPackageName + s;
107 if (entryName.endsWith(".class") && !entryName.contains("$")) {
108 entryName = entryName.substring(0, entryName.lastIndexOf('.'));
109 entryName = entryName.replace('/', '.');
110 names.add(entryName);
111 try {
112 final Class<?> tmpc = Class.forName(entryName);
113 classes.add(tmpc);
114 } catch (NoClassDefFoundError e) {
115 System.err.println("Unable to instantiate class " + entryName);
116 System.err.println(e.getMessage());
117 }
118 }
119 }
120 } catch (final Exception e) {
121 System.err.println("Failed to process file: " + packageName);
122 e.printStackTrace();
123 }
124 } else {
125 // loop through files in classpath
126
127 String packageURLString = packageURL.toString();
128 try {
129 URI uri = new URI(packageURLString);
130 File folder = new File(uri.getPath());
131
132 List<String> files = findFiles(folder);
133 for (String s : files) {
134 String entryName = realPackageName + s;
135
136 if (entryName.endsWith(".class")
137 && !entryName.contains("$")) {
138 entryName = entryName.substring(0,
139 entryName.lastIndexOf('.'));
140 entryName = entryName.replace('/', '.');
141
142 names.add(entryName);
143 classes.add(Class.forName(entryName));
144 }
145 }
146 } catch (Exception e) {
147 System.err.println("Failed to process file: "
148 + packageURLString);
149 e.printStackTrace();
150 }
151 }
152
153 return classes;
154 }
155
156 /**
157 * Finds all files in a directory and it's subdirectories
158 *
159 * @param directory
160 * The folder to start in
161 *
162 * @return A list of Strings containing file paths relative to the starting
163 * directory
164 */
165 private static List<String> findFiles(File directory) {
166 List<String> files = new LinkedList<String>();
167 for (File f : directory.listFiles()) {
168 if (f.isDirectory()) {
169 for (String s : findFiles(f)) {
170 files.add(f.getName() + "/" + s);
171 }
172 } else {
173 files.add(f.getName());
174 }
175 }
176 return files;
177 }
178
179 public static List<Class<?>> getClasses(final String pckgname)
180 throws ClassNotFoundException {
181
182 final ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
183
184 // Must be a forward slash for loading resources
185 final String packagePath = pckgname.replace('.', '/');
186
187 if (System.getProperty("eclipse.expeditee.home") == null) {
188 final ClassLoader cld = Thread.currentThread()
189 .getContextClassLoader();
190 if (cld == null) {
191 throw new ClassNotFoundException("Can't get class loader.");
192 }
193 URL resource = null;
194 try {
195 final Enumeration<URL> resources = cld
196 .getResources(packagePath);
197 while (resources.hasMoreElements()) {
198 URL url = resources.nextElement();
199 resource = url;
200 }
201 } catch (IOException e) {
202 System.err
203 .println("A IO Error has occured when trying to use the ContextClassLoader"
204 + System.getProperty("line.separator")
205 + "Are you running from within Eclipse? (or just not with Jar) Then make sure your"
206 + " 'eclipse.expeditee.home' property is set correctly. It is currently: '"
207 + System.getProperty("eclipse.expeditee.home")
208 + "'"
209 + System.getProperty("line.separator")
210 + "You can set it by adding a VM argument. "
211 + "Example: -Declipse.expeditee.home=D:\\Desktop\\Research\\expeditee-svn");
212 e.printStackTrace();
213 }
214 if (resource == null) {
215 throw new ClassNotFoundException("No resource for "
216 + packagePath);
217 }
218 final File directory = new File(resource.getFile());
219
220 final int splitPoint = directory.getPath().indexOf('!');
221 if (splitPoint > 0) {
222 String jarName = directory.getPath().substring(
223 "file:".length(), splitPoint);
224 // Windows HACK
225 if (jarName.indexOf(":") >= 0)
226 jarName = jarName.substring(1);
227
228 if (jarName.indexOf("%20") > 0) {
229 jarName = jarName.replace("%20", " ");
230 }
231 // System.out.println("JarName:" + jarName);
232 try {
233 final JarFile jarFile = new JarFile(jarName);
234 final Enumeration<?> entries = jarFile.entries();
235 while (entries.hasMoreElements()) {
236 final ZipEntry entry = (ZipEntry) entries.nextElement();
237 final String className = entry.getName();
238 if (className.startsWith(packagePath)) {
239 if (className.endsWith(".class")
240 && !className.contains("$")) {
241 // The forward slash below is a forwards slash
242 // for
243 // both windows and linux
244
245 String class_forname = className.substring(0,
246 className.length() - 6);
247 class_forname = class_forname.replace('/', '.');
248
249 classes.add(Class.forName(class_forname));
250 }
251 }
252 }
253 try {
254 jarFile.close();
255 } catch (IOException e) {
256 System.err
257 .println("Error attempting to close Jar file");
258 e.printStackTrace();
259 }
260 } catch (IOException e) {
261 System.err.println("Error Instantiating Jar File Object");
262 e.printStackTrace();
263 }
264 } else {
265
266 System.err
267 .println("A Error has occured when trying to use a Jar file to find actions or agents."
268 + System.getProperty("line.separator")
269 + "Are you running from within Eclipse? (or just not with Jar) Then make sure your"
270 + " 'eclipse.expeditee.home' property is set correctly. It is currently: '"
271 + System.getProperty("eclipse.expeditee.home")
272 + "'"
273 + System.getProperty("line.separator")
274 + "You can set it by adding a VM argument. "
275 + "Example: -Declipse.expeditee.home=D:\\Desktop\\Research\\expeditee-svn");
276 }
277 } else {
278 String eclipse_expeditee_home = System.getProperty(
279 "eclipse.expeditee.home", "");
280 String full_package_path = eclipse_expeditee_home + File.separator
281 + "bin" + File.separator + packagePath;
282
283 final File directory = new File(full_package_path);
284
285 if (directory.exists()) {
286 // Get the list of the files contained in the package
287 String[] files = directory.list();
288 for (int i = 0; i < files.length; i++) {
289 // we are only interested in .class files
290 if (files[i].endsWith(".class") && !files[i].contains("$")
291 && !files[i].equals("Actions.class")) {
292 // removes the .class extension
293 classes.add(Class.forName(pckgname
294 + files[i].substring(0, files[i].length() - 6)));
295 }
296 }
297 } else {
298 throw new ClassNotFoundException("The package '" + pckgname
299 + "' in the directory '" + directory
300 + "' does not appear to be a valid package");
301 }
302 }
303 return classes;
304 }
305
306}
Note: See TracBrowser for help on using the repository browser.