Java tutorial
/* * Copyright (C) 2005 by Quentin Anciaux * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License * for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * @author Quentin Anciaux */ package org.allcolor.yahp.converter; import java.beans.Introspector; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.net.URLConnection; import java.net.URLStreamHandlerFactory; import java.security.AccessControlContext; import java.security.ProtectionDomain; import java.sql.Driver; import java.sql.DriverManager; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.Hashtable; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.StringTokenizer; import java.util.Vector; import java.util.Map.Entry; import java.util.jar.JarEntry; import java.util.jar.JarInputStream; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.LookAndFeel; import javax.swing.UIManager; /** * This is a custom tree classloader * * @author Quentin Anciaux * @version 1.0 */ public final class CClassLoader extends URLClassLoader { /** classloader namespace */ public static final String CCLASSLOADER_NAMESPACE = "org.allcolor::CClassLoader.loadClass::"; private static ThreadLocal contextLoader = new ThreadLocal(); /** DEBUG log level */ private static final int DEBUG = 1; /** FATAL log level */ private static final int FATAL = 2; /** INFO log level */ private static final int INFO = 0; /** use for logging */ private static final Logger log = Logger.getLogger(CClassLoader.class.getName()); /** contains all mandatory loaders */ private static final Map mandatoryLoadersMap = new HashMap(); /** name of the rootloader */ public static final String ROOT_LOADER = "rootLoader"; /** handle to the root loader */ private static CClassLoader rootLoader = CClassLoader .createLoader((CClassLoader.class.getClassLoader() != null) ? CClassLoader.class.getClassLoader() : ClassLoader.getSystemClassLoader(), CClassLoader.ROOT_LOADER); /** * Ser the URLClassLoader that will return to calls to getURLs() */ private static volatile URLClassLoader urlLoader = null; protected void finalize() throws Throwable { System.out.println("Finalizing classloader : " + this.finalizepath); this.finalizepath = null; } /** * Create a new loader * * @param parent * a reference to the parent loader * @param name * loader name * * @return a new loader */ private static final CClassLoader createLoader(final ClassLoader parent, final String name) { try { return new CClassLoader(parent, name); } catch (final Exception ignore) { return null; } } // end createLoader() /** * Creates and allocates a memory URL * * @param entryName * name of the entry * @param entry * byte array of the entry * @return the created URL or null if an error occurs. */ public static URL createMemoryURL(final String entryName, final byte[] entry) { try { final Class c = ClassLoader.getSystemClassLoader() .loadClass("org.allcolor.yahp.converter.CMemoryURLHandler"); final Method m = c.getDeclaredMethod("createMemoryURL", new Class[] { String.class, byte[].class }); m.setAccessible(true); return (URL) m.invoke(null, new Object[] { entryName, entry }); } catch (final Exception ignore) { ignore.printStackTrace(); return null; } } private static final void clearMap(Map map) { for (Iterator it = map.entrySet().iterator(); it.hasNext();) { Map.Entry e = (Map.Entry) it.next(); Object value = e.getKey(); if ((value != null) && (value.getClass().getClassLoader() != null) && (value.getClass().getClassLoader().getClass() == CClassLoader.class)) { System.out.println("Resseting thread local " + value); it.remove(); continue; } if (value instanceof Map) { clearMap((Map) value); } else if (value instanceof List) { clearList((List) value); } else if (value instanceof Set) { clearSet((Set) value); } value = e.getValue(); if ((value != null) && (value.getClass().getClassLoader() != null) && (value.getClass().getClassLoader().getClass() == CClassLoader.class)) { System.out.println("Resseting thread local " + value); it.remove(); continue; } if (value instanceof Map) { clearMap((Map) value); } else if (value instanceof List) { clearList((List) value); } else if (value instanceof Set) { clearSet((Set) value); } else if (value instanceof Object[]) { clearArray((Object[]) value); } } } private static final void clearArray(Object[] array) { for (int i = 0; i < array.length; i++) { Object value = array[i]; if ((value != null) && (value.getClass().getClassLoader() != null) && (value.getClass().getClassLoader().getClass() == CClassLoader.class)) { System.out.println("Resseting thread local " + value); array[i] = null; continue; } if (value instanceof Map) { clearMap((Map) value); } else if (value instanceof List) { clearList((List) value); } else if (value instanceof Set) { clearSet((Set) value); } else if (value instanceof Object[]) { clearArray((Object[]) value); } } } private static final void clearList(List list) { for (Iterator it = list.iterator(); it.hasNext();) { Object value = it.next(); if ((value != null) && (value.getClass().getClassLoader() != null) && (value.getClass().getClassLoader().getClass() == CClassLoader.class)) { System.out.println("Resseting thread local " + value); it.remove(); continue; } if (value instanceof Map) { clearMap((Map) value); } else if (value instanceof List) { clearList((List) value); } else if (value instanceof Set) { clearSet((Set) value); } else if (value instanceof Object[]) { clearArray((Object[]) value); } } } private static final void clearSet(Set list) { for (Iterator it = list.iterator(); it.hasNext();) { Object value = it.next(); if ((value != null) && (value.getClass().getClassLoader() != null) && (value.getClass().getClassLoader().getClass() == CClassLoader.class)) { System.out.println("Resseting thread local " + value); it.remove(); continue; } if (value instanceof Map) { clearMap((Map) value); } else if (value instanceof List) { clearList((List) value); } else if (value instanceof Set) { clearSet((Set) value); } else if (value instanceof Object[]) { clearArray((Object[]) value); } } } /** * destroy the loader tree */ public static final void destroy() { if (CClassLoader.rootLoader == null) { return; } System.out.println("Destroying YAHP ClassLoader Tree"); CClassLoader.urlLoader = null; try { Field f = Class.forName("java.lang.Shutdown").getDeclaredField("hooks"); f.setAccessible(true); ArrayList l = (ArrayList) f.get(null); for (Iterator it = l.iterator(); it.hasNext();) { Object o = it.next(); if ((o != null) && (o.getClass().getClassLoader() != null) && (o.getClass().getClassLoader().getClass() == CClassLoader.class)) { it.remove(); } } } catch (Throwable ignore) { } try { Field f = Class.forName("java.lang.ApplicationShutdownHooks").getDeclaredField("hooks"); f.setAccessible(true); IdentityHashMap l = (IdentityHashMap) f.get(null); for (Iterator it = l.entrySet().iterator(); it.hasNext();) { Entry e = (Entry) it.next(); Thread o = (Thread) e.getKey(); if ((o != null) && (o.getClass().getClassLoader() != null) && (o.getClass().getClassLoader().getClass() == CClassLoader.class)) { it.remove(); continue; } o = (Thread) e.getValue(); if ((o != null) && (o.getClass().getClassLoader() != null) && (o.getClass().getClassLoader().getClass() == CClassLoader.class)) { it.remove(); } } } catch (Throwable ignore) { } try { if ((UIManager.getLookAndFeel() != null) && (UIManager.getLookAndFeel().getClass().getClassLoader() != null) && (UIManager.getLookAndFeel().getClass().getClassLoader().getClass() == CClassLoader.class)) { UIManager.setLookAndFeel((LookAndFeel) null); } Field f = UIManager.class.getDeclaredField("currentLAFState"); f.setAccessible(true); Object lafstate = f.get(null); if (lafstate != null) { Field fmultiUIDefaults = lafstate.getClass().getDeclaredField("multiUIDefaults"); fmultiUIDefaults.setAccessible(true); Object multiUIDefaults = fmultiUIDefaults.get(lafstate); Method clear = multiUIDefaults.getClass().getDeclaredMethod("clear", (Class[]) null); clear.setAccessible(true); clear.invoke(multiUIDefaults, (Object[]) null); Field tbl = lafstate.getClass().getDeclaredField("tables"); tbl.setAccessible(true); Hashtable[] tables = (Hashtable[]) tbl.get(lafstate); if (tables != null) { for (int i = 0; i < tables.length; i++) { Hashtable element = tables[i]; if (element != null) { element.clear(); } } } } } catch (Throwable ignore) { } try { Hashtable tb = UIManager.getDefaults(); Object cl = tb.get("ClassLoader"); if (cl.getClass() == CClassLoader.class) { tb.put("ClassLoader", CClassLoader.rootLoader.getParent()); } } catch (Throwable ignore) { } Method logFactoryRelease = null; try { logFactoryRelease = CClassLoader.rootLoader.loadClass("org.apache.commons.logging.LogFactory") .getMethod("release", new Class[] { ClassLoader.class }); } catch (final Throwable ignore) { } CClassLoader.rootLoader._destroy(logFactoryRelease); CClassLoader.mandatoryLoadersMap.clear(); CClassLoader.rootLoader = null; // deregister any sql driver loaded try { final List deregisterList = new ArrayList(); for (final Enumeration it = DriverManager.getDrivers(); it.hasMoreElements();) { final Driver d = (Driver) it.nextElement(); if ((d != null) && (d.getClass().getClassLoader() != null) && (d.getClass().getClassLoader().getClass() == CClassLoader.class)) { deregisterList.add(d); } } for (int i = 0; i < deregisterList.size(); i++) { final Driver driver = (Driver) deregisterList.get(i); DriverManager.deregisterDriver(driver); } } catch (final Throwable ignore) { } // stop dandling thread created with this classloader // tested only on sun jdk ThreadGroup tg = Thread.currentThread().getThreadGroup(); while ((tg != null) && (tg.getParent() != null)) { tg = tg.getParent(); } List ltg = new ArrayList(); ltg.add(tg); CClassLoader.getThreadGroups(tg, ltg); for (int ii = 0; ii < ltg.size(); ii++) { try { final ThreadGroup g = (ThreadGroup) ltg.get(ii); final Field fthreads = ThreadGroup.class.getDeclaredField("threads"); fthreads.setAccessible(true); final List toStop = new ArrayList(); Object threads[] = null; if (fthreads.getType() == Vector.class) { // in gnu classpath threads = ((Vector) fthreads.get(g)).toArray(); } else { // sun threads = (Object[]) fthreads.get(g); } for (int i = 0; i < threads.length; i++) { if (threads[i] == null) { continue; } if ((threads[i] != null) && (((Thread) threads[i]).getContextClassLoader() != null) && (((Thread) threads[i]).getContextClassLoader().getClass() == CClassLoader.class)) { ((Thread) threads[i]).setContextClassLoader(null); } if ((threads[i] != null) && (threads[i].getClass().getClassLoader() != null) && (threads[i].getClass().getClassLoader().getClass() == CClassLoader.class)) { toStop.add((Thread) threads[i]); } // remove any object in threadLocal referring an object // loaded // by this classloader tree try { final Field fthreadLocals = Thread.class.getDeclaredField("threadLocals"); fthreadLocals.setAccessible(true); final Object threadLocals = fthreadLocals.get(threads[i]); if (threadLocals != null) { final Field ftable = threadLocals.getClass().getDeclaredField("table"); ftable.setAccessible(true); final Object table[] = (Object[]) ftable.get(threadLocals); for (int kk = 0; kk < table.length; kk++) { final Object element = table[kk]; if (element != null) { final Field fvalue = element.getClass().getDeclaredField("value"); fvalue.setAccessible(true); final Object value = fvalue.get(element); if ((value != null) && (value.getClass().getClassLoader() != null) && (value .getClass().getClassLoader().getClass() == CClassLoader.class)) { fvalue.set(element, null); } if (value instanceof Map) { clearMap((Map) value); } else if (value instanceof List) { clearList((List) value); } else if (value instanceof Set) { clearSet((Set) value); } else if (value instanceof Object[]) { clearArray((Object[]) value); } fvalue.setAccessible(false); } } ftable.setAccessible(false); } fthreadLocals.setAccessible(false); } catch (final Throwable ignore) { ignore.printStackTrace(); } // remove any object in threadLocal referring an object // loaded // by this classloader tree try { final Field fthreadLocals = Thread.class.getDeclaredField("inheritableThreadLocals"); fthreadLocals.setAccessible(true); final Object threadLocals = fthreadLocals.get(threads[i]); if (threadLocals != null) { final Field ftable = threadLocals.getClass().getDeclaredField("table"); ftable.setAccessible(true); final Object table[] = (Object[]) ftable.get(threadLocals); for (int kk = 0; kk < table.length; kk++) { final Object element = table[kk]; if (element != null) { final Field fvalue = element.getClass().getDeclaredField("value"); fvalue.setAccessible(true); final Object value = fvalue.get(element); if ((value != null) && (value.getClass().getClassLoader() != null) && (value .getClass().getClassLoader().getClass() == CClassLoader.class)) { fvalue.set(element, null); } if (value instanceof Map) { clearMap((Map) value); } else if (value instanceof List) { clearList((List) value); } else if (value instanceof Set) { clearSet((Set) value); } else if (value instanceof Object[]) { clearArray((Object[]) value); } fvalue.setAccessible(false); } } ftable.setAccessible(false); } fthreadLocals.setAccessible(false); } catch (final Throwable ignore) { ignore.printStackTrace(); } // remove any protection domain referring this loader tree try { final Field finheritedAccessControlContext = Thread.class .getDeclaredField("inheritedAccessControlContext"); finheritedAccessControlContext.setAccessible(true); final Object inheritedAccessControlContext = finheritedAccessControlContext.get(threads[i]); if (inheritedAccessControlContext != null) { final Field fcontext = AccessControlContext.class.getDeclaredField("context"); fcontext.setAccessible(true); final Object context[] = (Object[]) fcontext.get(inheritedAccessControlContext); if (context != null) { for (int k = 0; k < context.length; k++) { if (context[k] == null) continue; final Field fclassloader = ProtectionDomain.class .getDeclaredField("classloader"); fclassloader.setAccessible(true); final Object classloader = fclassloader.get(context[k]); if ((classloader != null) && (classloader.getClass() == CClassLoader.class)) { context[k] = null; } fclassloader.setAccessible(false); } } fcontext.setAccessible(false); } finheritedAccessControlContext.setAccessible(false); } catch (final Throwable ignore) { ignore.printStackTrace(); } } fthreads.setAccessible(false); for (int i = 0; i < toStop.size(); i++) { try { final Thread t = (Thread) toStop.get(i); final Method stop = t.getClass().getMethod("stop", (Class[]) null); stop.invoke(t, (Object[]) null); } catch (final Throwable ignore) { } } } catch (final Throwable ignore) { } } try { CThreadContext.destroy(); } catch (Throwable ignore) { } System.runFinalization(); System.gc(); Introspector.flushCaches(); System.out.println("Destroying YAHP ClassLoader Tree : done"); } // end destroy() /** * Return a list of classes and jar files * * @param current * currently inspected file * @param list * list of url to classes and jar files * @return list of url to classes and jar files */ private static List getClasses(final File current, final List list) { if (current.isDirectory()) { try { list.add(current.toURI().toURL()); } catch (final Exception ignore) { } final File children[] = current.listFiles(); for (int i = 0; i < children.length; i++) { final File element = children[i]; CClassLoader.getClasses(element, list); } } else if (current.isFile()) { final String name = current.getName(); if (name.endsWith(".class")) { try { list.add(current.toURI().toURL()); } catch (final Exception ignore) { } } else if (name.endsWith(".jar")) { try { list.add(current.toURI().toURL()); } catch (final Exception ignore) { } } } return list; } // end getClasses() public static final ClassLoader getContextLoader() { return CClassLoader.contextLoader.get() != null ? (CClassLoader) ((WeakReference) CClassLoader.contextLoader.get()).get() : null; } /** * return the loader with the given path * * @param fpath * the path to lookup * * @return the loader with the given path */ public static final CClassLoader getLoader(final String fpath) { String path = fpath; CClassLoader currentLoader = CClassLoader.rootLoader; if (path == null) { return CClassLoader.getRootLoader(); } if (path.startsWith(CClassLoader.ROOT_LOADER)) { path = path.substring(10); } final StringTokenizer tokenizer = new StringTokenizer(path, "/", false); while (tokenizer.hasMoreTokens()) { final String name = tokenizer.nextToken(); currentLoader = currentLoader.getLoaderByName(name); } return currentLoader; } // end getLoader() /** * return the rootloader * * @return the rootloader */ public static final CClassLoader getRootLoader() { if (CClassLoader.rootLoader == null) { CClassLoader.rootLoader = CClassLoader.createLoader(CClassLoader.class.getClassLoader(), CClassLoader.ROOT_LOADER); } return CClassLoader.rootLoader; } // end getRootLoader() private static void getThreadGroups(ThreadGroup tg, List ltg) { try { final Field fgroups = ThreadGroup.class.getDeclaredField("groups"); fgroups.setAccessible(true); ThreadGroup[] array = (ThreadGroup[]) fgroups.get(tg); if (array != null) { for (int i = 0; i < array.length; i++) { ThreadGroup element = array[i]; if (!ltg.contains(element)) { CClassLoader.getThreadGroups(element, ltg); ltg.add(element); } } } } catch (Throwable ignore) { } } /** * Return a list of jar and classes located in path * * @param path * the path in which to search * @return a list of jar and classes located in path */ public static URL[] getURLs(final String path) { final File topDir = new File(path); final List list = new ArrayList(); CClassLoader.getClasses(topDir, list); final URL ret[] = new URL[list.size() + 1]; for (int i = 0; i < list.size(); i++) { ret[i] = (URL) list.get(i); } try { ret[list.size()] = topDir.toURI().toURL(); } catch (final Exception ignore) { } return ret; } // end getURLs() /** * initialize the loaders hierarchy * * @param config * the loaders config object */ public static final void init(final CClassLoaderConfig config) { CClassLoader.installURLStreamHandlerFactory(); if (CClassLoader.getRootLoader().isInit()) { return; } // initialize the loaders default parameters. for (final Iterator it = config.getLoadersInfoMap().entrySet().iterator(); it.hasNext();) { final Map.Entry entry = (Map.Entry) it.next(); final String loaderPath = (String) entry.getKey(); final CClassLoaderConfig.CLoaderInfo info = (CClassLoaderConfig.CLoaderInfo) entry.getValue(); final CClassLoader loader = CClassLoader.getLoader(loaderPath); loader.config = config; loader.booAlone = info.isAlone(); loader.booDoNotForwardToParent = info.isDoNotForwardToParent(); loader.booMandatory = info.isMandatory(); if (loader.isMandatory()) { CClassLoader.mandatoryLoadersMap.put(loader.getPath(), loader); } loader.booResourceOnly = info.isResourceOnly(); } // lookup classes/resources in filesystem for (final Iterator it = config.getFilesMap().entrySet().iterator(); it.hasNext();) { final Map.Entry entry = (Map.Entry) it.next(); final String loaderPath = (String) entry.getKey(); final List list = (List) entry.getValue(); final CClassLoader loader = CClassLoader.getLoader(loaderPath); for (final Iterator f = list.iterator(); f.hasNext();) { final Object obj = f.next(); if (obj instanceof URL) { final URL file = (URL) obj; String name = file.toString(); final int index = name.indexOf(loaderPath); if (index != -1) { name = name.substring(index + loaderPath.length()); } if (name.endsWith(".jar")) { loader.addResource(name, file); loader.readDirectories(file); } else { loader.addResource(name, file); if (!loader.booResourceOnly && name.endsWith(".class")) { name = name.substring(0, name.lastIndexOf('.')); name = name.replace('\\', '/'); name = name.replace('/', '.'); loader.addClass(name, file); } else if (name.startsWith("native/")) { String system = name.substring(7); system = system.substring(0, system.indexOf('/')); if (!loader.dllMap.containsKey(system)) { loader.dllMap.put(system, file); } if (!loader.resourcesMap.containsKey(name)) { loader.resourcesMap.put(name, file); } else { final Object to = loader.resourcesMap.get(name); if (to instanceof URL) { final URL uo = (URL) to; final List l = new ArrayList(); l.add(uo); l.add(file); loader.resourcesMap.put(name, l); } else if (to instanceof List) { final List uo = (List) to; uo.add(file); loader.resourcesMap.put(name, uo); } } } } } } } // set init state CClassLoader.setInit(CClassLoader.getRootLoader()); } // end init() /** * Install a custom URLStreamHandlerFactory which handle nested jar loading, * and memory url. The installation is done only if necessary. * */ private static void installURLStreamHandlerFactory() { synchronized (URL.class) { try { try { new URL("yahpjarloader://test/test"); return; } catch (MalformedURLException e) { } if (CClassLoader.class.getClassLoader() != ClassLoader.getSystemClassLoader()) { try { Class c = ClassLoader.getSystemClassLoader() .loadClass("org.allcolor.yahp.converter.CYaHPURLStreamHandlerFactory"); if (c != null) { return; } } catch (Throwable ignore) { } } final Field factory = URL.class.getDeclaredField("factory"); factory.setAccessible(true); final URLStreamHandlerFactory oldFactory = (URLStreamHandlerFactory) factory.get(null); if ((oldFactory == null) || (oldFactory.getClass().getName().indexOf("CYaHPURLStreamHandlerFactory") == -1)) { synchronized (factory) { System.out.println("Installing new URLStreamHandlerFactory..."); final Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", new Class[] { String.class, byte[].class, int.class, int.class }); defineClass.setAccessible(true); final byte[] bauc = CClassLoader.loadByteArray(CClassLoader.class.getClassLoader() .getResource("org/allcolor/yahp/converter/CByteArrayUrlConnection.class")); final byte[] crypt = CClassLoader.loadByteArray(CClassLoader.class.getClassLoader() .getResource("org/allcolor/yahp/converter/CCryptoUtils.class")); final byte[] b64c = CClassLoader.loadByteArray(CClassLoader.class.getClassLoader() .getResource("org/allcolor/yahp/converter/CBASE64Codec.class")); final byte[] muh = CClassLoader.loadByteArray(CClassLoader.class.getClassLoader() .getResource("org/allcolor/yahp/converter/CMemoryURLHandler.class")); final byte[] juhgc = CClassLoader .loadByteArray(CClassLoader.class.getClassLoader().getResource( "org/allcolor/yahp/converter/CJarLoaderURLStreamHandler$CGCCleaner.class")); final byte[] juh = CClassLoader.loadByteArray(CClassLoader.class.getClassLoader() .getResource("org/allcolor/yahp/converter/CJarLoaderURLStreamHandler.class")); final byte[] hf = CClassLoader.loadByteArray(CClassLoader.class.getClassLoader() .getResource("org/allcolor/yahp/converter/CYaHPURLStreamHandlerFactory.class")); defineClass.invoke(ClassLoader.getSystemClassLoader(), new Object[] { "org.allcolor.yahp.converter.CByteArrayUrlConnection", bauc, new Integer(0), new Integer(bauc.length) }); defineClass.invoke(ClassLoader.getSystemClassLoader(), new Object[] { "org.allcolor.yahp.converter.CCryptoUtils", crypt, new Integer(0), new Integer(crypt.length) }); defineClass.invoke(ClassLoader.getSystemClassLoader(), new Object[] { "org.allcolor.yahp.converter.CBASE64Codec", b64c, new Integer(0), new Integer(b64c.length) }); defineClass.invoke(ClassLoader.getSystemClassLoader(), new Object[] { "org.allcolor.yahp.converter.CMemoryURLHandler", muh, new Integer(0), new Integer(muh.length) }); defineClass.invoke(ClassLoader.getSystemClassLoader(), new Object[] { "org.allcolor.yahp.converter.CJarLoaderURLStreamHandler$CGCCleaner", juhgc, new Integer(0), new Integer(juhgc.length) }); defineClass.invoke(ClassLoader.getSystemClassLoader(), new Object[] { "org.allcolor.yahp.converter.CJarLoaderURLStreamHandler", juh, new Integer(0), new Integer(juh.length) }); final Class c = (Class) defineClass.invoke(ClassLoader.getSystemClassLoader(), new Object[] { "org.allcolor.yahp.converter.CYaHPURLStreamHandlerFactory", hf, new Integer(0), new Integer(hf.length) }); final Constructor cons = c.getConstructor(new Class[] { URLStreamHandlerFactory.class }); final URLStreamHandlerFactory fact = (URLStreamHandlerFactory) cons .newInstance(new Object[] { oldFactory }); factory.set(null, fact); System.out.println("Installing new URLStreamHandlerFactory DONE."); } } } catch (final Throwable ignore) { ignore.printStackTrace(); } } } /** * load the given inputstream in a byte array * * @param in * the stream to load * * @return a byte array */ public static final byte[] loadByteArray(final InputStream in) { try { final ByteArrayOutputStream bOut = new ByteArrayOutputStream(); final byte buffer[] = new byte[2048]; int iNbByteRead = -1; while ((iNbByteRead = in.read(buffer)) != -1) { bOut.write(buffer, 0, iNbByteRead); } return bOut.toByteArray(); } catch (final IOException ioe) { return null; } } // end loadByteArray() /** * load the given url in a byte array * * @param urlToResource * url to load * * @return a byte array */ public static final byte[] loadByteArray(final URL urlToResource) { InputStream in = null; try { final URLConnection uc = urlToResource.openConnection(); uc.setUseCaches(false); in = uc.getInputStream(); return CClassLoader.loadByteArray(in); } catch (final IOException ioe) { return null; } finally { try { in.close(); } catch (final Exception ignore) { } } } // end loadByteArray() /** * load multiple resources of same name * * @param loader * current lookup loader * @param URLList * list of found resources * @param resourceName * name to match */ private static final void loadResources(final CClassLoader loader, final List URLList, final String resourceName) { final List l = loader.getPrivateResource(resourceName); if (l != null) { URLList.addAll(l); } final List loaderList = new ArrayList(); for (final Iterator it = loader.childrenMap.entrySet().iterator(); it.hasNext();) { final Entry entry = (Entry) it.next(); loaderList.add(entry.getValue()); } for (int i = 0; i < loaderList.size(); i++) { final Object element = loaderList.get(i); final CClassLoader child = (CClassLoader) element; CClassLoader.loadResources(child, URLList, resourceName); } } // end loadResources() /** * log the message * * @param Message * message to log * @param level * log level (INFO,DEBUG,FATAL) */ private static final void log(final String Message, final int level) { if ((level == CClassLoader.INFO) && CClassLoader.log.isLoggable(Level.INFO)) { CClassLoader.log.info(Message); } else if ((level == CClassLoader.DEBUG) && CClassLoader.log.isLoggable(Level.FINE)) { CClassLoader.log.fine(Message); } else if ((level == CClassLoader.FATAL) && CClassLoader.log.isLoggable(Level.SEVERE)) { CClassLoader.log.severe(Message); } } // end log() /** * Release a previously allocated memory URL * * @param u * the URL to release memory */ public static void releaseMemoryURL(final URL u) { try { final Class c = ClassLoader.getSystemClassLoader() .loadClass("org.allcolor.yahp.converter.CMemoryURLHandler"); final Method m = c.getDeclaredMethod("releaseMemoryURL", new Class[] { URL.class }); m.setAccessible(true); m.invoke(null, new Object[] { u }); } catch (final Exception ignore) { ignore.printStackTrace(); } } public static final void setContextLoader(ClassLoader contextLoader) { CClassLoader.contextLoader.set(new WeakReference(contextLoader)); } /** * set the init flag of all loaders * * @param loader * the current loader */ private static final void setInit(final CClassLoader loader) { loader.booInit = true; for (final Iterator it = loader.getChildLoader(); it.hasNext();) { final Map.Entry entry = (Map.Entry) it.next(); CClassLoader.setInit((CClassLoader) entry.getValue()); } } // end setInit() /** * Set the urlloader used to resolved getURLs * * @param urlLoader * the urlloader used to resolved getURLs */ public static void setURLClassLoader(final URLClassLoader urlLoader) { CClassLoader.urlLoader = urlLoader; } /** * test if the logging level is enabled * * @param level * the logging level to test * * @return true if enabled */ private static final boolean sl(final int level) { if ((level == CClassLoader.INFO) && CClassLoader.log.isLoggable(Level.INFO)) { return true; } else if ((level == CClassLoader.DEBUG) && CClassLoader.log.isLoggable(Level.FINE)) { return true; } else if ((level == CClassLoader.FATAL) && CClassLoader.log.isLoggable(Level.SEVERE)) { return true; } return false; } // end sl() /** is alone ? */ private boolean booAlone = false; /** is not forwarding to parent ? */ private boolean booDoNotForwardToParent = false; /** is initializing ? */ private boolean booInit = false; /** is mandatory ? */ private boolean booMandatory = false; /** is resource only ? */ private boolean booResourceOnly = false; private final Map cacheMap = new HashMap(); /** contains reference to children loaders */ private final Map childrenMap = new HashMap(); /** known classes by this loader */ private final Map classesMap = new HashMap(); /** reference to the loader config object */ private CClassLoaderConfig config; /** * Contains a name-URL of dll/.so mapping for this loader */ private final Map dllMap = new HashMap(); /** loader name */ private String name = null; /** loader path */ private String path = null; private String finalizepath = null; /** known resources by this loader */ private final Map resourcesMap = new HashMap(); /** * Create a new loader * * @param parent * a reference to the parent loader * @param name * loader name * * @throws Exception * should not happen */ private CClassLoader(final ClassLoader parent, final String name) throws Exception { super(new URL[0], parent); this.name = name; this.path = this.nGetLoaderPath(); } // end CClassLoader() /** * Destroy instance variables. * * @param logFactoryRelease * method to release commons logging */ private final void _destroy(final Method logFactoryRelease) { for (final Iterator it = this.childrenMap.entrySet().iterator(); it.hasNext();) { final Map.Entry entry = (Map.Entry) it.next(); final CClassLoader loader = (CClassLoader) entry.getValue(); loader._destroy(logFactoryRelease); it.remove(); } try { // remove ref from commons logging logFactoryRelease.invoke(null, new Object[] { this }); } catch (final Exception e) { } try { // reset parent to system class loader final Field parent = ClassLoader.class.getDeclaredField("parent"); parent.setAccessible(true); parent.set(this, ClassLoader.getSystemClassLoader()); parent.setAccessible(false); } catch (final Throwable ignore) { } this.classesMap.clear(); for (final Iterator it = this.dllMap.entrySet().iterator(); it.hasNext();) { final Object element = it.next(); final Map.Entry entry = (Map.Entry) element; if (entry.getValue() instanceof File) { ((File) entry.getValue()).delete(); } } this.cacheMap.clear(); this.dllMap.clear(); this.resourcesMap.clear(); this.config = null; this.name = null; this.finalizepath = this.path; this.path = null; //classes System.runFinalization(); System.gc(); } // end _destroy() /** * add a class to known class * * @param className * class name * @param urlToClass * url to class file */ public final void addClass(final String className, final URL urlToClass) { if ((className == null) || (urlToClass == null)) { return; } if (!this.classesMap.containsKey(className)) { this.classesMap.put(className, urlToClass); } } // end addClass() /** * add a resource * * @param resouceName * name of the resource to add * @param urlToResource * url to the resource */ public final void addResource(final String resouceName, final URL urlToResource) { if ((urlToResource == null) || (resouceName == null)) { return; } if (this.resourcesMap.containsKey(resouceName.replace('\\', '/'))) { final Object to = this.resourcesMap.get(resouceName.replace('\\', '/')); if (to instanceof URL) { final URL uo = (URL) to; final List l = new ArrayList(); l.add(uo); this.resourcesMap.put(resouceName.replace('\\', '/'), l); } else if (to instanceof List) { final List uo = (List) to; uo.add(urlToResource); this.resourcesMap.put(resouceName.replace('\\', '/'), uo); } } else { this.resourcesMap.put(resouceName.replace('\\', '/'), urlToResource); } } // end addResource() /* * (non-Javadoc) * * @see java.lang.ClassLoader#findClass(java.lang.String) */ protected final Class findClass(final String name) throws ClassNotFoundException { try { if (name == null) { return null; } if (name.startsWith("java.") || name.startsWith("sun.reflect")) { return ClassLoader.getSystemClassLoader().loadClass(name); } final String searchClass = name.replace('.', '/') + ".class"; final CThreadContext context = CThreadContext.getInstance(); final String cpName = CClassLoader.CCLASSLOADER_NAMESPACE + name; List lPriorLoader = (List) context.get(cpName); if (lPriorLoader == null) { lPriorLoader = new Vector(); context.set(cpName, lPriorLoader); } if (lPriorLoader.contains(this.toString())) { return null; } lPriorLoader.add(this.toString()); if (CClassLoader.sl(CClassLoader.DEBUG)) { CClassLoader.log("Searching " + name + " in " + this.getPath(), CClassLoader.DEBUG); } final WeakReference cache = (WeakReference) this.cacheMap.get(name); if (cache != null) { final Class c = (Class) cache.get(); if (c != null) { return c; } } // first check if this class as a mandatory loader if (!this.booAlone) { CClassLoader loader = null; for (final Iterator it = CClassLoader.mandatoryLoadersMap.entrySet().iterator(); it.hasNext();) { final Entry entry = (Entry) it.next(); loader = (CClassLoader) entry.getValue(); if (loader.classesMap.containsKey(searchClass)) { if (loader != this) { break; } loader = null; break; } loader = null; } if (loader != null) { final Class c = loader.findClass(name); if (c != null) { return c; } } } // second search in this repository byte buffer[] = null; final URL urlToResource = (URL) this.classesMap.get(searchClass); if (urlToResource != null) { buffer = CClassLoader.loadByteArray(urlToResource); } if (buffer != null) { if (CClassLoader.sl(CClassLoader.DEBUG)) { CClassLoader.log("Loaded " + name + " in " + this.getPath(), CClassLoader.DEBUG); } Class c = null; c = this.findLoadedClass(name); if (c == null) { try { c = this.defineClass(name, buffer, 0, buffer.length); } catch (final LinkageError e) { c = this.findLoadedClass(name); if (c == null) { throw new ClassNotFoundException(name + " was not found !"); } } } if (c != null) { return c; } } // then search in each children final List tmpLoader = new ArrayList(); for (final Iterator it = this.childrenMap.entrySet().iterator(); it.hasNext();) { final Entry entry = (Entry) it.next(); final CClassLoader child = (CClassLoader) entry.getValue(); if (lPriorLoader.contains(child.toString())) { continue; } tmpLoader.add(child); } for (final Iterator it = tmpLoader.iterator(); it.hasNext();) { final Object element = it.next(); final CClassLoader child = (CClassLoader) element; final Class c = child.findClass(name); if (c != null) { return c; } } // then follow to parents if ((this != CClassLoader.getRootLoader()) && !this.booDoNotForwardToParent) { if (lPriorLoader.contains(this.getParent().toString())) { return null; } else { if (this.getParent() instanceof CClassLoader) { return ((CClassLoader) this.getParent()).findClass(name); } else { return this.getParent().loadClass(name); } } } else { try { ClassLoader contextLoader = CClassLoader.getContextLoader(); if (contextLoader == null) { contextLoader = CClassLoader.getRootLoader().getParent(); } final Class c = contextLoader.loadClass(name); if (c != null) { return c; } } catch (Throwable e) { final Class c = CClassLoader.getRootLoader().getParent().loadClass(name); if (c != null) { return c; } } throw new ClassNotFoundException(name); } } catch (ClassNotFoundException e) { throw e; } catch (NoClassDefFoundError e) { throw e; } catch (Throwable e) { throw new ClassNotFoundException(name, e); } } // end findClass() /* * (non-Javadoc) * * @see java.lang.ClassLoader#findLibrary(java.lang.String) */ protected String findLibrary(final String libname) { if (!this.isInit()) { if (CClassLoader.sl(CClassLoader.DEBUG)) { CClassLoader.log("Not initialized, forward to old loader " + libname + " in " + this.getPath(), CClassLoader.DEBUG); } return super.findLibrary(libname); } final String system = CSystem.getName() + "/" + libname; final CThreadContext context = CThreadContext.getInstance(); final String cpName = CClassLoader.CCLASSLOADER_NAMESPACE + system; try { List lPriorLoader = (List) context.get(cpName); if (lPriorLoader == null) { lPriorLoader = new Vector(); context.set(cpName, lPriorLoader); } if (lPriorLoader.contains(this.toString())) { return null; } lPriorLoader.add(this.toString()); if (!this.booAlone) { CClassLoader loader = null; for (final Iterator it = CClassLoader.mandatoryLoadersMap.entrySet().iterator(); it.hasNext();) { final Entry entry = (Entry) it.next(); loader = (CClassLoader) entry.getValue(); if (loader.dllMap.containsKey(system)) { if (loader != this) { break; } loader = null; break; } loader = null; } if (loader != null) { final String c = loader.findLibrary(libname); context.set(cpName, null); return c; } } String path = null; final Object obj = this.dllMap.get(system); if (obj instanceof URL) { final URL urlToResource = (URL) obj; final byte[] buffer = CClassLoader.loadByteArray(urlToResource); final File nfile = File.createTempFile(libname + this.hashCode(), ".so"); final FileOutputStream fout = new FileOutputStream(nfile); fout.write(buffer); fout.close(); this.dllMap.put(system, nfile); path = nfile.getAbsolutePath(); } else if (obj instanceof File) { final File nfile = (File) obj; path = nfile.getAbsolutePath(); } if (path != null) { context.set(cpName, null); return path; } // then search in each children final List tmpLoader = new ArrayList(); for (final Iterator it = this.childrenMap.entrySet().iterator(); it.hasNext();) { final Entry entry = (Entry) it.next(); final CClassLoader child = (CClassLoader) entry.getValue(); if (lPriorLoader.contains(child.toString())) { continue; } tmpLoader.add(child); } for (final Iterator it = tmpLoader.iterator(); it.hasNext();) { final Object element = it.next(); final CClassLoader child = (CClassLoader) element; final String c = child.findLibrary(libname); if (c != null) { return c; } } // then follow to parents if ((this != CClassLoader.getRootLoader()) && !this.booDoNotForwardToParent) { if (lPriorLoader.contains(this.getParent().toString())) { return null; } else { if (this.getParent() instanceof CClassLoader) { final CClassLoader parent = (CClassLoader) this.getParent(); return parent.findLibrary(libname); } else { return super.findLibrary(libname); } } } else { final String c = super.findLibrary(libname); context.set(cpName, null); return c; } } catch (final IOException e) { return super.findLibrary(libname); } } /* * (non-Javadoc) * * @see java.lang.ClassLoader#findResource(java.lang.String) */ public final URL findResource(final String fname) { if (!this.isInit()) { if (CClassLoader.sl(CClassLoader.DEBUG)) { CClassLoader.log("Not initialized, forward to old loader " + fname + " in " + this.getPath(), CClassLoader.DEBUG); } if ((Thread.currentThread().getContextClassLoader() != null) && (Thread.currentThread().getContextClassLoader() != this)) { return Thread.currentThread().getContextClassLoader().getResource(fname); } return CClassLoader.getRootLoader().getParent().getResource(fname); } String name = fname; if (name.startsWith("/")) { name = name.substring(1); } final CThreadContext context = CThreadContext.getInstance(); final String cpName = CClassLoader.CCLASSLOADER_NAMESPACE + name; List lPriorLoader = (List) context.get(cpName); if (lPriorLoader == null) { lPriorLoader = new Vector(); context.set(cpName, lPriorLoader); } if (lPriorLoader.contains(this.toString())) { return null; } lPriorLoader.add(this.toString()); if (CClassLoader.sl(CClassLoader.DEBUG)) { CClassLoader.log("Searching " + name + " in " + this.getPath(), CClassLoader.DEBUG); } // first check if this resource as a mandatory loader URL urlToResource = null; if (!this.booAlone) { CClassLoader loader = null; for (final Iterator it = CClassLoader.mandatoryLoadersMap.entrySet().iterator(); it.hasNext();) { final Entry entry = (Entry) it.next(); loader = (CClassLoader) entry.getValue(); if (loader.resourcesMap.containsKey(name)) { if (loader != this) { break; } loader = null; break; } loader = null; } if (loader != null) { urlToResource = loader.getResource(name); } if (urlToResource != null) { context.set(cpName, null); return urlToResource; } } final Object to = this.resourcesMap.get(name); if (to instanceof URL) { // second search in this repository urlToResource = (URL) to; } else if (to instanceof List) { final List l = (List) to; urlToResource = (URL) l.get(0); } if (urlToResource != null) { if (CClassLoader.sl(CClassLoader.DEBUG)) { CClassLoader.log("Loaded " + name + " in " + this.getPath(), CClassLoader.DEBUG); } context.set(cpName, null); return urlToResource; } // then search in each children final List tmpLoader = new ArrayList(); for (final Iterator it = this.childrenMap.entrySet().iterator(); it.hasNext();) { final Entry entry = (Entry) it.next(); final CClassLoader child = (CClassLoader) entry.getValue(); if (lPriorLoader.contains(child.toString())) { continue; } tmpLoader.add(child); } for (final Iterator it = tmpLoader.iterator(); it.hasNext();) { final Object element = it.next(); final CClassLoader child = (CClassLoader) element; urlToResource = child.getResource(name); if (urlToResource != null) { return urlToResource; } } // then follow to parents if ((this != CClassLoader.getRootLoader()) && !this.booDoNotForwardToParent) { if (lPriorLoader.contains(this.getParent().toString())) { return null; } else { if (this.getParent() == null) { return null; } return this.getParent().getResource(name); } } else { urlToResource = CClassLoader.getRootLoader().getParent().getResource(name); context.set(cpName, null); return urlToResource; } } // end findResource() /* * (non-Javadoc) * * @see java.lang.ClassLoader#findResources(java.lang.String) */ public final Enumeration findResources(final String name) throws IOException { final CClassLoader loader = CClassLoader.getRootLoader(); final List URLList = new ArrayList(); try { CClassLoader.loadResources(loader, URLList, name); } finally { try { } catch (final Exception ignore) { } } try { final Enumeration eu = CClassLoader.getRootLoader().getParent().getResources(name); while (eu.hasMoreElements()) { URLList.add(eu.nextElement()); } } catch (final Throwable ignore) { } final Iterator it = URLList.iterator(); return new Enumeration() { Iterator internalIt = it; public boolean hasMoreElements() { return this.internalIt.hasNext(); } // end hasMoreElements() public Object nextElement() { return this.internalIt.next(); } // end nextElement() } // end new ; } // end findResources() /** * return an iterator on children loaders * * @return an iterator on children loaders */ public final Iterator getChildLoader() { return this.childrenMap.entrySet().iterator(); } // end getChildLoader() /** * return a copy of the known classes * * @return a copy of the known classes */ public final Map getClassesMap() { return Collections.unmodifiableMap(this.classesMap); } // end getClassesMap() /** * Return the child loader with the given name * * @param name * name of the child to get * * @return the child loader with the given name */ private final CClassLoader getLoaderByName(final String name) { try { CClassLoader loader = (CClassLoader) this.childrenMap.get(name); if (loader == null) { loader = CClassLoader.createLoader(this, name); this.childrenMap.put(name, loader); } return loader; } finally { try { } catch (final Exception ignore) { } } } // end getLoaderByName() /** * Returns the name. * * @return Returns the name. */ public final String getName() { return this.name; } // end getName() /** * Returns the path. * * @return Returns the path. */ public final String getPath() { return this.path; } // end getPath() /** * get the resource with the given name * * @param name * name of the resource to get * * @return the resource with the given name */ private final List getPrivateResource(final String name) { try { final Object to = this.resourcesMap.get(name); final List list = new ArrayList(); if (to instanceof URL) { list.add((URL) to); return list; } else if (to instanceof List) { final List l = (List) to; for (int i = 0; i < l.size(); i++) { list.add((URL) l.get(i)); } return list; } else { return null; } } finally { try { } catch (final Exception ignore) { } } } // end getPrivateResource() /* * (non-Javadoc) * * @see java.lang.ClassLoader#getResource(java.lang.String) */ public final URL getResource(final String name) { return this.findResource(name); } // end getResource() public final InputStream getResourceAsStream(final String name) { try { return this.getResource(name).openStream(); } catch (final Exception ioe) { return null; } } // end getResourceAsStream() /* * * !!!!!!!!!!!!!!!!!!!!!!!!!!!!! This method is only possible in 1.5 vm upward. * SHAME ON SUN * public Enumeration getResources(String name) throws IOException { if (this != CClassLoader.getRootLoader()) { return CClassLoader.getRootLoader().getResources(name); } final CThreadContext context = CThreadContext.getInstance(); Object obj = context.get(CClassLoader.CCLASSLOADER_NAMESPACE + name + this.getPath()); if (obj != null) { return new Vector().elements(); } context .set(CClassLoader.CCLASSLOADER_NAMESPACE + name + this.getPath(), ""); try { return this.findResources(name); } finally { context.set(CClassLoader.CCLASSLOADER_NAMESPACE + name + this.getPath(), null); } } */ /** * return a copy of the known resources * * @return a copy of the known resources */ public final Map getResourcesMap() { return Collections.unmodifiableMap(this.resourcesMap); } // end getResourcesMap() /* * (non-Javadoc) * * @see java.net.URLClassLoader#getURLs() */ public URL[] getURLs() { return CClassLoader.urlLoader != null ? CClassLoader.urlLoader.getURLs() : new URL[0]; } // end getURLs() /** * Returns the booAlone. * * @return Returns the booAlone. */ public final boolean isAlone() { return this.booAlone; } // end isAlone() /** * return booDoNotForwardToParent * * @return booDoNotForwardToParent */ public final boolean isForwardingToParent() { return !this.booDoNotForwardToParent; } // end isForwardingToParent() /** * Returns the booInit. * * @return Returns the booInit. */ public final boolean isInit() { return this.booInit; } // end isInit() /** * Returns the booMandatory. * * @return Returns the booMandatory. */ public final boolean isMandatory() { return this.booMandatory; } // end isMandatory() /** * Returns the booResourceOnly. * * @return Returns the booResourceOnly. */ public final boolean isResourceOnly() { return this.booResourceOnly; } // end isResourceOnly() /* * (non-Javadoc) * * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean) */ protected final Class loadClass(final String name, final boolean resolve) throws ClassNotFoundException { final CThreadContext context = CThreadContext.getInstance(); try { Class c = null; final WeakReference cache = (WeakReference) this.cacheMap.get(name); if (cache != null) { c = (Class) cache.get(); } if (c == null) { // First, check if the class has already been loaded c = this.findLoadedClass(name); if (c == null) { c = this.findClass(name); this.cacheMap.put(name, new WeakReference(c)); } } if (resolve) { this.resolveClass(c); } return c; } finally { context.set(CClassLoader.CCLASSLOADER_NAMESPACE + name, null); try { } catch (final Exception ignore) { } } } // end loadClass() /** * calculate the loader path * * @return the calculated path */ private final String nGetLoaderPath() { ClassLoader currentLoader = this; final StringBuffer buffer = new StringBuffer(); buffer.append(this.name); while ((currentLoader = currentLoader.getParent()) != null) { if (currentLoader.getClass() == CClassLoader.class) { buffer.insert(0, "/"); buffer.insert(0, ((CClassLoader) currentLoader).name); } else { break; } } return buffer.toString(); } // end nGetLoaderPath() /** * analyse the content of the given jar file * * @param jarFile * the jar to analise */ private final void readDirectories(final URL jarFile) { JarInputStream jarIn = null; try { if (!jarFile.getPath().endsWith(".jar")) { return; } if (CClassLoader.sl(CClassLoader.DEBUG)) { CClassLoader.log("opening jar : " + jarFile.toExternalForm(), CClassLoader.DEBUG); } jarIn = new JarInputStream(jarFile.openStream()); JarEntry jarEntry = null; while ((jarEntry = jarIn.getNextJarEntry()) != null) { if (jarEntry.isDirectory()) { continue; } final URL url = new URL("yahpjarloader://" + CBASE64Codec.encode(jarFile.toExternalForm().getBytes("utf-8")).replaceAll("\n", "") + "/" + jarEntry.getName()); if (CClassLoader.sl(CClassLoader.DEBUG)) { CClassLoader.log("found entry : " + url.toString(), CClassLoader.DEBUG); } if (jarEntry.getName().endsWith(".class")) { if (!this.classesMap.containsKey(jarEntry.getName())) { if (!this.booResourceOnly) { this.classesMap.put(jarEntry.getName(), url); } } if (this.resourcesMap.containsKey(jarEntry.getName())) { final Object to = this.resourcesMap.get(jarEntry.getName()); if (to instanceof URL) { final URL uo = (URL) to; final List l = new ArrayList(); l.add(uo); l.add(url); this.resourcesMap.put(jarEntry.getName(), l); } else if (to instanceof List) { final List uo = (List) to; uo.add(url); this.resourcesMap.put(jarEntry.getName(), uo); } } else { this.resourcesMap.put(jarEntry.getName(), url); } } else if (jarEntry.getName().startsWith("native/")) { String system = jarEntry.getName().substring(7); system = system.substring(0, system.indexOf('/')); if (!this.dllMap.containsKey(system)) { this.dllMap.put(system, url); } if (this.resourcesMap.containsKey(jarEntry.getName())) { final Object to = this.resourcesMap.get(jarEntry.getName()); if (to instanceof URL) { final URL uo = (URL) to; final List l = new ArrayList(); l.add(uo); l.add(url); this.resourcesMap.put(jarEntry.getName(), l); } else if (to instanceof List) { final List uo = (List) to; uo.add(url); this.resourcesMap.put(jarEntry.getName(), uo); } } else { this.resourcesMap.put(jarEntry.getName(), url); } } else { if (this.resourcesMap.containsKey(jarEntry.getName())) { final Object to = this.resourcesMap.get(jarEntry.getName()); if (to instanceof URL) { final URL uo = (URL) to; final List l = new ArrayList(); l.add(uo); l.add(url); this.resourcesMap.put(jarEntry.getName(), l); } else if (to instanceof List) { final List uo = (List) to; uo.add(url); this.resourcesMap.put(jarEntry.getName(), uo); } } else { this.resourcesMap.put(jarEntry.getName(), url); } } } if (CClassLoader.sl(CClassLoader.DEBUG)) { CClassLoader.log("opening jar : " + jarFile.getFile().toString() + " done.", CClassLoader.DEBUG); } } catch (final MalformedURLException mue) { mue.printStackTrace(); if (CClassLoader.sl(CClassLoader.FATAL)) { CClassLoader.log(mue.getMessage(), CClassLoader.FATAL); } } catch (final IOException ioe) { ioe.printStackTrace(); if (CClassLoader.sl(CClassLoader.FATAL)) { CClassLoader.log(ioe.getMessage(), CClassLoader.FATAL); } } catch (final Exception e) { e.printStackTrace(); if (CClassLoader.sl(CClassLoader.FATAL)) { CClassLoader.log(e.getMessage(), CClassLoader.FATAL); } } finally { try { jarIn.close(); jarIn = null; } catch (final Exception e) { } } } // end readDirectories() /** * reload this loader */ public final void reload() { this.reload(this.config); } // end reload() /** * reload this loader * * @param config * a loader config object */ public final void reload(final CClassLoaderConfig config) { if (this == CClassLoader.getRootLoader()) { return; } if (config == null) { return; } final CClassLoader parent = ((CClassLoader) this.getParent()); parent.removeLoader(this.name); if (this.isMandatory()) { CClassLoader.mandatoryLoadersMap.remove(this.getPath()); } final CClassLoader newLoader = CClassLoader.getLoader(parent.getPath() + "/" + this.name); newLoader.config = this.config; newLoader.booAlone = this.booAlone; newLoader.booMandatory = this.booMandatory; newLoader.booResourceOnly = this.booResourceOnly; newLoader.booDoNotForwardToParent = this.booDoNotForwardToParent; final List list = (List) config.getFilesMap().get(this.path); for (final Iterator f = list.iterator(); f.hasNext();) { final URL file = (URL) f.next(); newLoader.readDirectories(file); } final Iterator it = this.childrenMap.keySet().iterator(); while (it.hasNext()) { final CClassLoader child = (CClassLoader) this.childrenMap.get(it.next()); child.reload(); } this._destroy(null); if (newLoader.isMandatory()) { CClassLoader.mandatoryLoadersMap.put(newLoader.getPath(), newLoader); } newLoader.booInit = true; } // end reload() /** * remove the given loader from this loader * * @param loaderToRemove * name of the loader to remove. NOT NULL. * * @return the removed loader or null. * * @throws NullPointerException * if loaderToRemove is null or a zero length/blank string */ public final CClassLoader removeLoader(final String loaderToRemove) { if (loaderToRemove.trim().length() == 0) { throw new NullPointerException(); } return (CClassLoader) this.childrenMap.remove(loaderToRemove); } // end removeLoader() /** * remove the given resource name from known resource * * @param resourceName * name of the resource to remove */ public final void removeResource(final String resourceName) { if (resourceName == null) { return; } this.resourcesMap.remove(resourceName.replace('\\', '/')); } // end removeResource() public String toString() { return this.getPath(); } } // end CClassLoader