View Javadoc

1   /*
2    * Copyright (c) 2005-2007 Creative Sphere Limited.
3    * All rights reserved. This program and the accompanying materials
4    * are made available under the terms of the Eclipse Public License v1.0
5    * which accompanies this distribution, and is available at
6    * http://www.eclipse.org/legal/epl-v10.html
7    *
8    * Contributors:
9    *
10   *   Creative Sphere - initial API and implementation
11   *
12   */
13  package org.abstracthorizon.extend.server.support;
14  
15  import java.io.BufferedReader;
16  import java.io.File;
17  import java.io.IOException;
18  import java.io.InputStream;
19  import java.io.InputStreamReader;
20  import java.lang.reflect.InvocationTargetException;
21  import java.lang.reflect.Method;
22  import java.net.JarURLConnection;
23  import java.net.MalformedURLException;
24  import java.net.URL;
25  import java.net.URLClassLoader;
26  import java.net.URLStreamHandlerFactory;
27  import java.util.ArrayList;
28  import java.util.Collection;
29  import java.util.Enumeration;
30  import java.util.jar.JarEntry;
31  import java.util.jar.JarFile;
32  
33  /**
34   * Utility class that contains class and url tool methods.
35   *
36   * @author Daniel Sendula
37   */
38  public class ClassUtils {
39  
40      /**
41       * Invokes parametherless method with given name. If <code>mustBePresent</code>
42       * is set to <code>true</code> {@link NoSuchMethodException} is propagated wrapped in
43       * {@link RuntimeException}.
44       *
45       * @param object instance on which method is going to be executed
46       * @param methodName method name
47       * @param mustBePresent if set then method must be present or {@link NoSuchMethodError} is thrown
48       * @throws RuntimeException if {@link NoSuchMethodException}, {@link IllegalArgumentException},
49       * {@link IllegalAccessException} or {@link InvocationTargetException} is thrown.
50       */
51      public static void invokeMethod(Object object, String methodName, boolean mustBePresent) {
52          try {
53              Method method = object.getClass().getMethod(methodName, new Class[]{});
54              method.invoke(object, new Object[]{});
55          } catch (NoSuchMethodException e) {
56              if (mustBePresent) {
57                  throw new RuntimeException(e);
58              }
59          } catch (IllegalArgumentException e) {
60              throw new RuntimeException(e);
61          } catch (IllegalAccessException e) {
62              throw new RuntimeException(e);
63          } catch (InvocationTargetException e) {
64              throw new RuntimeException(e);
65          }
66      }
67  
68      /**
69       * Creates class loader for given url. If url is directory then it is scanned
70       * and all jar files from it added to classpath.
71       *
72       * @param parent parent class loader or <code>null</code>
73       * @param lib url class loader to be created for.
74       * @return {@link URLClassLoader} instance
75       */
76      public static URLClassLoader createClassLoader(ClassLoader parent, URL lib) {
77          try {
78              Collection<URL> urls = collectFiles(lib);
79              urls.add(lib);
80              URL[] us = new URL[urls.size()];
81              us = urls.toArray(us);
82              LocalURLClassLoader classLoader = new LocalURLClassLoader(us, parent);
83              return classLoader;
84          } catch (IOException e) {
85              throw new RuntimeException("Cannot create class loader", e);
86          }
87      }
88  
89      /**
90       * Collects files from given url.
91       * @param url url
92       * @return collection of urls
93       * @throws IOException
94       */
95      public static Collection<URL> collectFiles(URL url) throws IOException {
96          String protocol = url.getProtocol();
97          if ("file".equals(protocol)) {
98              return collectFilesFromPath(new File(url.getFile()));
99          } else if ("jar".equals(protocol)) {
100             JarURLConnection jarURLConnection = (JarURLConnection)url.openConnection();
101             return collectFilesFromJar(url, jarURLConnection.getJarFile());
102         } else {
103             return collectFilesFromURL(url);
104         }
105     }
106 
107     /**
108      * Collects files from given path
109      * @param path directory
110      * @return collection of urls
111      * @throws IOException
112      */
113     public static Collection<URL> collectFilesFromPath(File path) throws IOException {
114         ArrayList<URL> urls = new ArrayList<URL>();
115         if (path.exists()) {
116             if (path.isDirectory()) {
117                 File[] files = path.listFiles();
118                 for (File file : files) {
119                     if (/*file.isFile() &&*/ file.getName().endsWith(".jar")) { // TODO is .jar enough?
120                         urls.add(file.toURI().toURL());
121                     }
122                 }
123             }
124         }
125         return urls;
126      }
127 
128     /**
129      * Collects files from jar file (root of)
130      * @param original original url
131      * @param jarFile jar file
132      * @return collection of urls
133      * @throws IOException
134      */
135     public static Collection<URL> collectFilesFromJar(URL original, JarFile jarFile) throws IOException {
136         ArrayList<URL> urls = new ArrayList<URL>();
137 
138         String originalFile = original.getFile();
139         String prefix = originalFile.substring(originalFile.lastIndexOf('!') + 1);
140         if (prefix.endsWith("/")) {
141             if (prefix.startsWith("/")) {
142                 prefix = prefix.substring(1);
143             }
144             Enumeration<JarEntry> en = jarFile.entries();
145             while (en.hasMoreElements()) {
146                 JarEntry entry = en.nextElement();
147                 String path = entry.getName();
148                 if (path.startsWith(prefix)) {
149                     path = path.substring(prefix.length());
150                     if (path.length() > 0) {
151                         int i = path.indexOf('/');
152                         if ((i < 0) /*|| (i == (path.length() - 1))*/) {
153                             URL url = new URL(original.getProtocol(), original.getHost(), original.getPort(), originalFile + path);
154                             urls.add(url);
155                         }
156                     }
157                 }
158             }
159         }
160         return urls;
161      }
162 
163     /**
164      * Collects files from give (generic) url
165      * @param url url
166      * @return collection of files
167      * @throws IOException
168      */
169     public static Collection<URL> collectFilesFromURL(URL url) throws IOException {
170         ArrayList<URL> urls = new ArrayList<URL>();
171         InputStream is = url.openStream();
172         try {
173             BufferedReader input = new BufferedReader(new InputStreamReader(is));
174             String file = input.readLine();
175             while (file != null) {
176                 if (file.length() > 0) {
177                     URL newUrl = new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile() + "/" + file);
178                     urls.add(newUrl);
179                 }
180                 file = input.readLine();
181             }
182         } finally {
183             is.close();
184         }
185         return urls;
186      }
187 
188     /**
189      * Gets home location.
190      * @return home location
191      * @throws MalformedURLException
192      */
193     public static URL getHomeLocation(Class<?> cls) throws MalformedURLException {
194         ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
195         String className = cls.getName().replace('.', '/') + ".class";
196         URL root = contextClassLoader.getResource(className);
197         if ("file".equals(root.getProtocol())) {
198             String file = root.getFile();
199             file = file.substring(0, file.length() - className.length() - 1);
200             if (file.endsWith("bin")) {
201                 file = file.substring(0, file.length() - 3);
202             }
203             return new File(file).toURI().toURL();
204         } else if ("jar".equals(root.getProtocol())) {
205             String file = root.getFile();
206             //if (!file.startsWith("file")) {
207             //    throw new RuntimeException("Cannot handle protocol from where this jar is loaded; " + root);
208             //}
209             int i = file.lastIndexOf('!');
210             file = file.substring(0, i);
211             File f = new File(file);
212             file = f.getParent();
213             if (file.endsWith("bin")) {
214                 file = file.substring(0, file.length() - 3);
215             }
216             return new URL(file);
217             // return new File(file).toURL();
218         } else {
219             throw new RuntimeException("Cannot handle protocol from where this class is loaded; " + root);
220         }
221     }
222 
223 
224     public static class LocalURLClassLoader extends URLClassLoader implements LocalClassLoader {
225 
226         public LocalURLClassLoader(URL[] urls, ClassLoader parent) {
227             super(urls, parent);
228         }
229 
230         public LocalURLClassLoader(URL[] urls) {
231             super(urls);
232         }
233 
234         public LocalURLClassLoader(URL[] urls, ClassLoader parent,
235                 URLStreamHandlerFactory factory) {
236             super(urls, parent, factory);
237         }
238 
239         public Class<?> findClass(String name) throws ClassNotFoundException {
240             return super.findClass(name);
241         }
242 
243         public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
244             Class<?> c = super.loadClass(name, resolve);
245             return c;
246         }
247 
248         public Class<?> loadLocalClass(String name) throws ClassNotFoundException {
249             SecurityManager sm = System.getSecurityManager();
250             if (sm != null) {
251                 int i = name.lastIndexOf('.');
252                 if (i != -1) {
253                     sm.checkPackageAccess(name.substring(0, i));
254                 }
255             }
256 
257             Class<?> c = findLoadedClass(name);
258             if (c == null) {
259                 c = findClass(name);
260             }
261             return c;
262         }
263 
264         public URL getLocalResource(String name) {
265             return findResource(name);
266         }
267 
268         public Enumeration<URL> getLocalResources(String name) throws IOException {
269             return findResources(name);
270         }
271 
272     }
273 }