Revision 42559
trunk/org.gvsig.desktop/org.gvsig.desktop.framework/org.gvsig.andami/src/main/java/org/gvsig/andami/plugins/PluginClassLoader.java | ||
---|---|---|
36 | 36 |
import java.util.ArrayList; |
37 | 37 |
import java.util.Arrays; |
38 | 38 |
import java.util.Enumeration; |
39 |
import java.util.HashMap; |
|
39 | 40 |
import java.util.HashSet; |
40 | 41 |
import java.util.Hashtable; |
41 | 42 |
import java.util.Iterator; |
... | ... | |
74 | 75 |
*/ |
75 | 76 |
private static Logger logger = LoggerFactory.getLogger(PluginClassLoader.class.getName()); |
76 | 77 |
|
77 |
/** |
|
78 |
* DOCUMENT ME! |
|
79 |
*/ |
|
80 |
private Hashtable<String, ZipFile> clasesJar = new Hashtable<String, ZipFile>(); |
|
81 | 78 |
|
82 |
/**
|
|
83 |
* DOCUMENT ME! |
|
84 |
*/ |
|
79 |
private Map<String, ZipFile> clasesJar = new HashMap<>();
|
|
80 |
|
|
81 |
|
|
85 | 82 |
private File baseDir; |
86 | 83 |
private List<PluginClassLoader> pluginLoaders; |
87 |
private static List<ClassLoader> otherLoaders = new ArrayList<ClassLoader>();
|
|
84 |
private static List<ClassLoader> otherLoaders = new ArrayList<>(); |
|
88 | 85 |
private boolean isOtherLoader = false; |
89 | 86 |
|
90 | 87 |
/** |
... | ... | |
107 | 104 |
public PluginClassLoader(URL[] jars, String baseDir, ClassLoader cl, |
108 | 105 |
List<PluginClassLoader> pluginLoaders) throws IOException { |
109 | 106 |
super(jars, cl); |
110 |
logger.debug("Creating PluginClassLoader for {}.", baseDir); |
|
111 | 107 |
this.baseDir = new File(new File(baseDir).getAbsolutePath()); |
112 |
this.pluginLoaders = new ArrayList(); |
|
113 |
this.pluginLoaders.addAll(pluginLoaders); |
|
108 |
try { |
|
109 |
logger.debug("Creating PluginClassLoader for {}.", this.getPluginName()); |
|
110 |
this.pluginLoaders = new ArrayList(); |
|
111 |
this.pluginLoaders.addAll(pluginLoaders); |
|
114 | 112 |
|
115 |
if (jars == null || jars.length < 1) { |
|
116 |
debugDump(); |
|
117 |
return; |
|
118 |
} |
|
119 |
ZipFile[] jarFiles = new ZipFile[jars.length]; |
|
113 |
if (jars == null || jars.length < 1) {
|
|
114 |
debugDump();
|
|
115 |
return;
|
|
116 |
}
|
|
117 |
ZipFile[] jarFiles = new ZipFile[jars.length];
|
|
120 | 118 |
|
121 |
for (int i = 0; i < jars.length; i++) { |
|
122 |
try { |
|
123 |
jarFiles[i] = new ZipFile(jars[i].getPath()); |
|
119 |
for (int i = 0; i < jars.length; i++) { |
|
120 |
try { |
|
121 |
logger.debug("Classloader {}, loading jar {}", this.getPluginName(), jars[i].getPath()); |
|
122 |
jarFiles[i] = new ZipFile(jars[i].getPath()); |
|
124 | 123 |
|
125 |
Enumeration<? extends ZipEntry> entradas = jarFiles[i].entries(); |
|
124 |
Enumeration<? extends ZipEntry> entradas = jarFiles[i].entries();
|
|
126 | 125 |
|
127 |
while (entradas.hasMoreElements()) { |
|
128 |
ZipEntry file = (ZipEntry) entradas.nextElement(); |
|
129 |
String fileName = file.getName(); |
|
126 |
while (entradas.hasMoreElements()) {
|
|
127 |
ZipEntry file = (ZipEntry) entradas.nextElement();
|
|
128 |
String fileName = file.getName();
|
|
130 | 129 |
|
131 |
if (!fileName.toLowerCase().endsWith(".class")) { //$NON-NLS-1$ |
|
130 |
if (!fileName.toLowerCase().endsWith(".class")) { //$NON-NLS-1$
|
|
132 | 131 |
|
133 |
continue; |
|
134 |
} |
|
132 |
continue;
|
|
133 |
}
|
|
135 | 134 |
|
136 |
fileName = fileName.substring(0, fileName.length() - 6) |
|
137 |
.replace('/', '.'); |
|
135 |
fileName = fileName.substring(0, fileName.length() - 6)
|
|
136 |
.replace('/', '.');
|
|
138 | 137 |
|
139 |
if (clasesJar.get(fileName) != null) { |
|
140 |
logger.warn("Duplicated class {} in {} and {}", |
|
141 |
new Object[]{ |
|
142 |
fileName, |
|
143 |
jarFiles[i].getName(), |
|
144 |
clasesJar.get(fileName).getName() |
|
145 |
} |
|
146 |
); |
|
147 |
} else { |
|
148 |
clasesJar.put(fileName, jarFiles[i]); |
|
138 |
if (clasesJar.get(fileName) != null) { |
|
139 |
logger.warn("Classloader {}, duplicated class {} in {} and {}", |
|
140 |
new Object[]{ |
|
141 |
this.getPluginName(), |
|
142 |
fileName, |
|
143 |
jarFiles[i].getName(), |
|
144 |
clasesJar.get(fileName).getName() |
|
145 |
} |
|
146 |
); |
|
147 |
} else { |
|
148 |
clasesJar.put(fileName, jarFiles[i]); |
|
149 |
} |
|
149 | 150 |
} |
151 |
} catch (ZipException e) { |
|
152 |
throw new IOException(e.getMessage() + " Jar: " |
|
153 |
+ jars[i].getPath() + ": " + jarFiles[i]); |
|
154 |
} catch (IOException e) { |
|
155 |
throw e; |
|
150 | 156 |
} |
151 |
} catch (ZipException e) { |
|
152 |
throw new IOException(e.getMessage() + " Jar: " |
|
153 |
+ jars[i].getPath() + ": " + jarFiles[i]); |
|
154 |
} catch (IOException e) { |
|
155 |
throw e; |
|
156 |
} finally { |
|
157 |
debugDump(); |
|
158 | 157 |
} |
158 |
} finally { |
|
159 |
debugDump(); |
|
159 | 160 |
} |
160 | 161 |
} |
161 | 162 |
|
... | ... | |
167 | 168 |
logger.debug(" baseDir: " + this.baseDir); |
168 | 169 |
logger.debug(" parent: " + this.getParent()); |
169 | 170 |
logger.debug(" depends:"); |
170 |
for (int n = 0; n < this.pluginLoaders.size(); n++) {
|
|
171 |
logger.debug(" {}", this.pluginLoaders.get(n).toString());
|
|
171 |
for (PluginClassLoader pluginLoader : this.pluginLoaders) {
|
|
172 |
logger.debug(" {}", pluginLoader.toString());
|
|
172 | 173 |
} |
173 | 174 |
logger.debug(" urls:"); |
174 | 175 |
URL[] urls = this.getURLs(); |
175 |
for (int n = 0; n < urls.length; n++) {
|
|
176 |
logger.debug(" " + urls[n].toString());
|
|
176 |
for (URL url : urls) {
|
|
177 |
logger.debug(" " + url.toString()); |
|
177 | 178 |
} |
178 |
logger.debug(" classes:"); |
|
179 |
Iterator<Map.Entry<String, ZipFile>> it = this.clasesJar.entrySet().iterator(); |
|
180 |
while (it.hasNext()) { |
|
181 |
Entry<String, ZipFile> entry = it.next(); |
|
182 |
logger.debug(" " + entry.getKey() + "(" + entry.getValue().getName() + ")"); |
|
183 |
} |
|
179 |
// logger.debug(" classes:");
|
|
180 |
// Iterator<Map.Entry<String, ZipFile>> it = this.clasesJar.entrySet().iterator();
|
|
181 |
// while (it.hasNext()) {
|
|
182 |
// Entry<String, ZipFile> entry = it.next();
|
|
183 |
// logger.debug(" " + entry.getKey() + "(" + entry.getValue().getName() + ")");
|
|
184 |
// }
|
|
184 | 185 |
} |
185 | 186 |
|
186 | 187 |
protected Class singleLoadClass(String name) throws ClassNotFoundException { |
187 | 188 |
Class<?> c; |
188 |
Set<String> pluginsVisiteds = new HashSet<String>();
|
|
189 |
Set<String> pluginsVisiteds = new HashSet<>(); |
|
189 | 190 |
c = this.singleLoadClass(pluginsVisiteds, name); |
190 | 191 |
return c; |
191 | 192 |
} |
... | ... | |
200 | 201 |
* |
201 | 202 |
* @throws ClassNotFoundException Si no se pudo encontrar la clase |
202 | 203 |
*/ |
204 |
@Override |
|
203 | 205 |
protected Class loadClass(String name, boolean resolve) |
204 | 206 |
throws ClassNotFoundException { |
205 | 207 |
Class<?> c = null; |
206 | 208 |
|
207 |
// Intentamos cargar con el system classloader
|
|
209 |
// Intentamos cargar con el URLClassLoader
|
|
208 | 210 |
try { |
209 | 211 |
if (!isOtherLoader) { |
210 | 212 |
c = super.loadClass(name, resolve); |
211 |
logger.debug("Found class {} in system-classloader", name);
|
|
213 |
logger.debug("Classloader {}, found class {}.", this.getPluginName(), name);
|
|
212 | 214 |
} |
213 | 215 |
} catch (ClassNotFoundException e1) { |
214 | 216 |
try { |
... | ... | |
237 | 239 |
|
238 | 240 |
private Class<?> loadOtherClass(String name) |
239 | 241 |
throws ClassNotFoundException { |
240 |
ClassLoader[] ocl = (ClassLoader[]) otherLoaders.toArray(new ClassLoader[0]); |
|
241 |
Class<?> c = null;
|
|
242 |
for (int i = 0; i < ocl.length; i++) {
|
|
243 |
c = ocl[i].loadClass(name);
|
|
242 |
ClassLoader[] ocls = (ClassLoader[]) otherLoaders.toArray(new ClassLoader[0]);
|
|
243 |
Class<?> c; |
|
244 |
for (ClassLoader ocl : ocls) {
|
|
245 |
c = ocl.loadClass(name); |
|
244 | 246 |
if (c != null) { |
245 |
logger.debug("Found class {} by the alternative classloaders of plugin {}",
|
|
246 |
name, baseDir);
|
|
247 |
|
|
247 |
logger.debug("Classloader {}, found class {} in classloader {}",
|
|
248 |
new Object[]{this, getPluginName(), name, ocl.toString()}
|
|
249 |
); |
|
248 | 250 |
return c; |
249 | 251 |
} |
250 | 252 |
} |
... | ... | |
341 | 343 |
* |
342 | 344 |
* @return Resource's URL if it was found, nul otherwise. |
343 | 345 |
*/ |
346 |
@Override |
|
344 | 347 |
public URL getResource(String res) { |
345 |
URL ret = null;
|
|
348 |
URL ret ; |
|
346 | 349 |
|
347 |
Set<String> pluginsVisiteds = new HashSet<String>();
|
|
350 |
Set<String> pluginsVisiteds = new HashSet<>(); |
|
348 | 351 |
ret = this.getResource(pluginsVisiteds, res); |
349 | 352 |
return ret; |
350 | 353 |
} |
... | ... | |
364 | 367 |
|
365 | 368 |
String parte = res.get(0); |
366 | 369 |
|
367 |
for (int i = 0; i < files.length; i++) {
|
|
368 |
if (files[i].getName().compareTo(parte) == 0) {
|
|
370 |
for (File file : files) {
|
|
371 |
if (file.getName().compareTo(parte) == 0) { |
|
369 | 372 |
if (res.size() == 1) { |
370 | 373 |
try { |
371 |
return new URL("file:" + files[i].toString());
|
|
372 |
} catch (MalformedURLException e) {
|
|
374 |
return new URL("file:" + file.toString()); |
|
375 |
}catch (MalformedURLException e) { |
|
373 | 376 |
return null; |
374 | 377 |
} |
375 | 378 |
} else { |
376 |
return getResource(files[i], res.subList(1, res.size()));
|
|
379 |
return getResource(file, res.subList(1, res.size())); |
|
377 | 380 |
} |
378 | 381 |
} |
379 | 382 |
} |
... | ... | |
394 | 397 |
/* |
395 | 398 |
* @see java.security.SecureClassLoader#getPermissions(java.security.CodeSource) |
396 | 399 |
*/ |
400 |
@Override |
|
397 | 401 |
protected PermissionCollection getPermissions(CodeSource codesource) { |
398 | 402 |
PermissionCollection perms = super.getPermissions(codesource); |
399 | 403 |
perms.add(new AllPermission()); |
... | ... | |
446 | 450 |
return c; |
447 | 451 |
} |
448 | 452 |
|
449 |
logger.debug("Searching class '{}' in {}", new Object[]{name, this.toString()}); |
|
453 |
logger.debug("Classloader {}, searching class '{}'", |
|
454 |
new Object[]{this.getPluginName(), name} |
|
455 |
); |
|
450 | 456 |
try { |
451 | 457 |
ZipFile jar = (ZipFile) clasesJar.get(name); |
452 | 458 |
|
... | ... | |
459 | 465 |
if (f.exists()) { |
460 | 466 |
byte[] data = loadClassData(f); |
461 | 467 |
c = defineClass(name, data, 0, data.length); |
462 |
logger.debug("Found class {} in classes-folder of plugin {}", |
|
463 |
new Object[]{name, baseDir}); |
|
468 |
logger.debug("Classloader {}/classes-folder, found class {}", |
|
469 |
new Object[]{this.getPluginName(), name} |
|
470 |
); |
|
464 | 471 |
|
465 | 472 |
} else { |
466 |
//Buscamos en los otros plugins |
|
467 |
for (int i = 0; i < pluginLoaders.size(); i++) { |
|
473 |
for (PluginClassLoader pluginLoader1 : pluginLoaders) { |
|
468 | 474 |
c = null; |
469 |
if (pluginLoaders.get(i) != null) { |
|
475 |
PluginClassLoader pluginLoader = pluginLoader1; |
|
476 |
if (pluginLoader != null) { |
|
470 | 477 |
try { |
471 |
c = pluginLoaders.get(i).singleLoadClass(pluginsVisiteds, name);
|
|
478 |
c = pluginLoader.singleLoadClass(pluginsVisiteds, name); |
|
472 | 479 |
} catch (ClassNotFoundException e) { |
473 | 480 |
// Si no la encontramos en el primer plugin, capturamos la exceptcion |
474 | 481 |
// porque es probable que la encontremos en el resto de plugins. |
475 | 482 |
} |
483 |
if (c != null) { |
|
484 |
logger.debug("Classloader {}, found class {} in plugin {}", |
|
485 |
new Object[]{ |
|
486 |
this.getPluginName(), |
|
487 |
name, |
|
488 |
pluginLoader.getPluginName() |
|
489 |
} |
|
490 |
); |
|
491 |
return c; |
|
492 |
} |
|
476 | 493 |
} |
477 |
if (c != null) { |
|
478 |
return c; |
|
479 |
} |
|
480 | 494 |
} |
495 |
|
|
496 |
|
|
481 | 497 |
} |
482 | 498 |
} else { |
499 |
logger.debug("Classloader {}, found class {} in jar {}", |
|
500 |
new Object[]{ |
|
501 |
this.getPluginName(), |
|
502 |
name, |
|
503 |
jar.getName() |
|
504 |
} |
|
505 |
); |
|
483 | 506 |
String fileName = name.replace('.', '/') + ".class"; |
484 | 507 |
ZipEntry classFile = jar.getEntry(fileName); |
485 | 508 |
byte[] data = loadClassData(classFile, |
486 | 509 |
jar.getInputStream(classFile)); |
487 | 510 |
|
488 | 511 |
c = defineClass(name, data, 0, data.length); |
512 |
if (c == null) { |
|
513 |
logger.debug("Classloader {}, can't load class {} from jar {}", |
|
514 |
new Object[]{ |
|
515 |
this.getPluginName(), |
|
516 |
name, |
|
517 |
jar.getName() |
|
518 |
} |
|
519 |
); |
|
520 |
} |
|
489 | 521 |
|
490 |
logger.debug("Found class {} in jar {} of plugin {}", |
|
491 |
new Object[]{name, jar.getName(), baseDir}); |
|
492 | 522 |
} |
493 | 523 |
|
494 | 524 |
if (c == null) { |
525 |
logger.debug("Classloader {}, class not found {}", |
|
526 |
new Object[]{ |
|
527 |
this.getPluginName(), |
|
528 |
name |
|
529 |
} |
|
530 |
); |
|
531 |
debugDump(); |
|
495 | 532 |
throw new ClassNotFoundException(name); |
496 | 533 |
} |
497 | 534 |
|
498 | 535 |
return c; |
499 | 536 |
} catch (IOException e) { |
537 |
logger.debug("Classloader {}, error loading class {}", |
|
538 |
new Object[]{ |
|
539 |
this.getPluginName(), |
|
540 |
name |
|
541 |
}, |
|
542 |
e |
|
543 |
); |
|
500 | 544 |
throw new ClassNotFoundException(Messages.getString( |
501 | 545 |
"PluginClassLoader.Error_reading_file") + name); |
502 | 546 |
} |
... | ... | |
524 | 568 |
// |
525 | 569 |
// Primero buscamos en el directorio del plugin. |
526 | 570 |
try { |
527 |
logger.debug("Plugin {}. Searching resource '{}'", res, this.getPluginName());
|
|
528 |
List<String> resource = new ArrayList<String>();
|
|
571 |
logger.debug("Classloader {}, searching resource '{}'", this.getPluginName(), res);
|
|
572 |
List<String> resource = new ArrayList<>(); |
|
529 | 573 |
StringTokenizer st = new StringTokenizer(res, "\\/"); |
530 | 574 |
while (st.hasMoreTokens()) { |
531 | 575 |
String token = st.nextToken(); |
... | ... | |
536 | 580 |
return ret; |
537 | 581 |
} |
538 | 582 |
} catch (Exception e) { |
539 |
logger.warn("Plugin {}. Error getting resource '{}'.", new Object[]{this.getPluginName(), res}, e); |
|
583 |
logger.warn("Classloader {}, Error getting resource '{}'.", |
|
584 |
new Object[]{ |
|
585 |
this.getPluginName(), res |
|
586 |
}, |
|
587 |
e |
|
588 |
); |
|
540 | 589 |
} |
541 | 590 |
|
542 |
logger.debug("Plugin {}. Searching in depends pluginLoaders", this.getPluginName()); |
|
543 |
for (int i = 0; i < this.pluginLoaders.size(); i++) { |
|
544 |
PluginClassLoader pluginClassLoader = pluginLoaders.get(i); |
|
591 |
logger.debug("Classloader {}, searching in depends pluginLoaders", this.getPluginName()); |
|
592 |
for (PluginClassLoader pluginClassLoader : this.pluginLoaders) { |
|
545 | 593 |
if (pluginClassLoader != null) { |
546 | 594 |
try { |
547 | 595 |
pluginsVisiteds.add(pluginClassLoader.getPluginName()); |
548 | 596 |
ret = pluginClassLoader.getResource(pluginsVisiteds, res); |
549 | 597 |
if (ret != null) { |
550 |
logger.trace("Plugin {}. Found resource '{}' in plugin '{}'.",
|
|
598 |
logger.debug("Classloader {}, Found resource '{}' in plugin '{}'.",
|
|
551 | 599 |
new Object[]{ |
552 |
this.getPluginName(), pluginClassLoader.getPluginName(), res |
|
553 |
}); |
|
600 |
this.getPluginName(), res, pluginClassLoader.getPluginName(),}); |
|
554 | 601 |
return ret; |
555 | 602 |
} |
556 | 603 |
} catch (Exception e) { |
... | ... | |
565 | 612 |
try { |
566 | 613 |
ret = super.getResource(res); |
567 | 614 |
} catch (Exception e) { |
568 |
logger.warn("Plugin {}. Error getting resource '{}' in parent classloader'", new Object[]{this.getPluginName(), res}, e); |
|
615 |
logger.warn("Classloader {}, error getting resource '{}' in parent classloader'", |
|
616 |
new Object[]{this.getPluginName(), res}, |
|
617 |
e |
|
618 |
); |
|
569 | 619 |
} |
570 | 620 |
if (ret == null) { |
571 |
logger.debug("Plugin {}. Resource '{}' not found.", new Object[]{this.getPluginName(), res}); |
|
621 |
logger.debug("Classloader {}, Resource '{}' not found.", |
|
622 |
new Object[]{this.getPluginName(), res} |
|
623 |
); |
|
572 | 624 |
} |
573 | 625 |
} |
574 | 626 |
return ret; |
Also available in: Unified diff