View Javadoc
1   /*
2    * #%L
3    * Nuiton Utils
4    * %%
5    * Copyright (C) 2004 - 2010 CodeLutin
6    * %%
7    * This program is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU Lesser General Public License as 
9    * published by the Free Software Foundation, either version 3 of the 
10   * License, or (at your option) any later version.
11   * 
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Lesser Public License for more details.
16   * 
17   * You should have received a copy of the GNU General Lesser Public 
18   * License along with this program.  If not, see
19   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
20   * #L%
21   */
22  
23  package org.nuiton.util;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  
28  import java.lang.reflect.Method;
29  import java.net.URL;
30  import java.net.URLClassLoader;
31  import java.util.ArrayList;
32  import java.util.Arrays;
33  import java.util.List;
34  import java.util.Stack;
35  
36  /**
37   * A usefull class with method for ClassLoader
38   *
39   * @author Tony Chemit - chemit@codelutin.com
40   */
41  public class ClassLoaderUtil {
42  
43  
44      /** Logger. */
45      private static final Log log = LogFactory.getLog(ClassLoaderUtil.class);
46  
47      /**
48       * Returns the all urls to be used in a {@link URLClassLoader}.
49       *
50       * If classloader  has only one url and the url is a jar, try to load in
51       * manifest class-path.
52       *
53       * @param loader the classloader (if null will use system one)
54       * @return all the url found in the classloader
55       */
56      public static URL[] getDeepURLs(URLClassLoader loader) {
57          Stack<URL> urlToTreate = new Stack<URL>();
58          List<URL> urlTreated = new ArrayList<URL>();
59  
60          // first get the urls from classloader
61          URL[] result = getURLs(loader);
62  
63          urlToTreate.addAll(Arrays.asList(result));
64          while (!urlToTreate.isEmpty()) {
65              URL currentUrl = urlToTreate.pop();
66              // save the url
67              urlTreated.add(currentUrl);
68              if (Resource.isJar(currentUrl.toString())) {
69                  // jar invocation
70                  try {
71                      URL[] newArrayURLs =
72                              Resource.getClassPathURLsFromJarManifest(
73                                      currentUrl);
74                      if (newArrayURLs == null) {
75                          continue;
76                      }
77                      List<URL> newURLs = Arrays.asList(newArrayURLs);
78                      for (URL newURL : newURLs) {
79                          if (!urlTreated.contains(newURL) &&
80                              !urlToTreate.contains(newURL)) {
81                              urlToTreate.add(newURL);
82                          }
83                      }
84                  } catch (Exception e) {
85                      if (log.isDebugEnabled()) {
86                          // this is not a such error, but some jar can not be 
87                          log.debug("error with url" + currentUrl +
88                                    " for reason : " + e.getMessage());
89                      }
90                  }
91              }
92          }
93          return urlTreated.toArray(new URL[urlToTreate.size()]);
94      }
95  
96      /**
97       * Recupere la liste des urls d'un {@link URLClassLoader}.
98       *
99       * Note : Un cas particulier est positionné pour JBoss qui utilise
100      * la method getAllURLs.
101      *
102      * @param classLoader le class loader a scanner
103      * @return les urls du classloade.
104      */
105     public static URL[] getURLs(URLClassLoader classLoader) {
106         if (classLoader == null) {
107             classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
108         }
109         Method m;
110         try {
111             // Essai de récupération de la méthode getAllURLs() de
112             // RepositoryClassLoader (JBoss)
113             m = classLoader.getClass().getMethod("getAllURLs");
114         } catch (Exception e) {
115             m = null;
116         }
117         URL[] result;
118         if (m == null) {
119             result = classLoader.getURLs();
120         } else {
121             try {
122                 result = (URL[]) m.invoke(classLoader);
123             } catch (Exception e) {
124                 throw new IllegalStateException(e);
125             }
126         }
127         return result;
128     }
129 
130     public static void printLoader(ClassLoader loader) {
131         log.info(loader);
132         if (loader instanceof URLClassLoader) {
133             URL[] urls = getURLs((URLClassLoader) loader);
134             for (URL url : urls) {
135                 log.info(url);
136             }
137         }
138     }
139 
140 }