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 }