InputStream getResourceAsStream(String name) { InputStream is = (myLoader == null) ? ClassLoader.getSystemResourceAsStream(name) : myLoader.getResourceAsStream(name); if (is != null) return is; // match behaviour of standard class loaders. if (name.endsWith(".class")) return null; boolean unlockLoader = false; try { unlockLoader = lockClassLoader(ShExQual.SH); synchronized (this) { if (needReload) { reload(); } if (!initDone) initLoaders(); for (int i = 0; i < jarList.length; i++) { JarLoader jl = jarList[i]; is = jl.getStream(name); if (is != null) { return is; } } } return null; } catch (StandardException se) { return null; } finally { if (unlockLoader) { lf.unlock(compat, this, classLoaderLock, ShExQual.SH); } } }
/** * Load the class from the class path. Called by JarLoader when it has a request to load a class * to fulfill the sematics of db.database.classpath. * * <p>Enforces two restrictions: * * <UL> * <LI>Do not allow classes in certain name spaces to be loaded from installed jars, see * RESTRICTED_PACKAGES for the list. * <LI>Referencing Derby's internal classes (those outside the public api) from installed is * disallowed. This is to stop user defined routines bypassing security or taking advantage * of security holes in Derby. E.g. allowing a routine to call a public method in db would * allow such routines to call public static methods for system procedures without having * been granted permission on them, such as setting database properties. * </UL> * * @exception ClassNotFoundException Class can not be found or the installed jar is restricted * from loading it. */ Class loadClass(String className, boolean resolve) throws ClassNotFoundException { JarLoader jl = null; boolean unlockLoader = false; try { unlockLoader = lockClassLoader(ShExQual.SH); synchronized (this) { if (needReload) { reload(); } Class clazz = checkLoaded(className, resolve); if (clazz != null) return clazz; // Refuse to load classes from restricted name spaces // That is classes in those name spaces can be not // loaded from installed jar files. for (int i = 0; i < RESTRICTED_PACKAGES.length; i++) { if (className.startsWith(RESTRICTED_PACKAGES[i])) throw new ClassNotFoundException(className); } String jvmClassName = className.replace('.', '/').concat(".class"); if (!initDone) initLoaders(); for (int i = 0; i < jarList.length; i++) { jl = jarList[i]; Class c = jl.loadClassData(className, jvmClassName, resolve); if (c != null) { if (vs != null) vs.println( MessageService.getTextMessage( MessageId.CM_CLASS_LOAD, className, jl.getJarName())); return c; } } // Ok we are missing the class, we will try to reload once and Find it... reload(); initDone = false; initLoaders(); for (int i = 0; i < jarList.length; i++) { jl = jarList[i]; Class c = jl.loadClassData(className, jvmClassName, resolve); if (c != null) { if (vs != null) vs.println( MessageService.getTextMessage( MessageId.CM_CLASS_LOAD, className, jl.getJarName())); return c; } } } return null; } catch (StandardException se) { throw new ClassNotFoundException( MessageService.getTextMessage( MessageId.CM_CLASS_LOAD_EXCEPTION, className, jl == null ? null : jl.getJarName(), se)); } finally { if (unlockLoader) { lf.unlock(compat, this, classLoaderLock, ShExQual.SH); } } }
/* * Version of getResource() that tracks the jar files that have been * visited by linking through the index files. This helper method uses * a HashSet to store the URLs of jar files that have been searched and * uses it to avoid going into an infinite loop, looking for a * non-existent resource */ Resource getResource(final String name, boolean check, Set visited) { Resource res; Object[] jarFiles; int count = 0; LinkedList jarFilesList = null; /* If there no jar files in the index that can potential contain * this resource then return immediately. */ if ((jarFilesList = index.get(name)) == null) return null; do { jarFiles = jarFilesList.toArray(); int size = jarFilesList.size(); /* loop through the mapped jar file list */ while (count < size) { String jarName = (String) jarFiles[count++]; JarLoader newLoader; final URL url; try { url = new URL(csu, jarName); if ((newLoader = (JarLoader) lmap.get(url)) == null) { /* no loader has been set up for this jar file * before */ newLoader = (JarLoader) AccessController.doPrivileged( new PrivilegedExceptionAction() { public Object run() throws IOException { return new JarLoader(url, handler, lmap); } }); /* this newly opened jar file has its own index, * merge it into the parent's index, taking into * account the relative path. */ JarIndex newIndex = ((JarLoader) newLoader).getIndex(); if (newIndex != null) { int pos = jarName.lastIndexOf("/"); newIndex.merge(this.index, (pos == -1 ? null : jarName.substring(0, pos + 1))); } /* put it in the global hashtable */ lmap.put(url, newLoader); } } catch (java.security.PrivilegedActionException pae) { continue; } catch (MalformedURLException e) { continue; } /* Note that the addition of the url to the list of visited * jars incorporates a check for presence in the hashmap */ boolean visitedURL = !visited.add(url); if (!visitedURL) { final JarEntry entry = newLoader.jar.getJarEntry(name); if (entry != null) { return newLoader.checkResource(name, check, entry); } /* Verify that at least one other resource with the * same package name as the lookedup resource is * present in the new jar */ if (!newLoader.validIndex(name)) { /* the mapping is wrong */ throw new InvalidJarIndexException("Invalid index"); } } /* If newLoader is the current loader or if it is a * loader that has already been searched or if the new * loader does not have an index then skip it * and move on to the next loader. */ if (visitedURL || newLoader == this || newLoader.getIndex() == null) { continue; } /* Process the index of the new loader */ if ((res = newLoader.getResource(name, check, visited)) != null) { return res; } } // Get the list of jar files again as the list could have grown // due to merging of index files. jarFilesList = index.get(name); // If the count is unchanged, we are done. } while (count < jarFilesList.size()); return null; }