costin 01/02/10 00:12:42 Modified: src/share/org/apache/tomcat/startup Main.java src/share/org/apache/tomcat/util/compat Jdk11Compat.java Added: src/share/org/apache/tomcat/util/compat SimpleClassLoader.java Removed: src/share/org/apache/tomcat/util SimpleClassLoader.java Log: Fixed the JDK1.1 build problem. It's very interesting - the code compiles fine on JDK1.2 because getParent() is now part of ClassLoader. It doesn't in JDK1.1, but adding a getParent in SimpleClassLoader will work only in JDK1.1 - in 1.2 it'll fail ( it's final in ClassLoader ). So we have to call the method getParentLoader() in SimpleClassLoader ( so it compiles in both ) and abstract if via JdkCompat. But we are lucky to have it behind JdkCompat and not have to worry about this in future. ( I also followed the XXX and moved SimpleClassLoader in compat - it shouldn't be used standalone - you want to use the real thing if available - URLClassLoader ) Revision Changes Path 1.21 +4 -2 jakarta-tomcat/src/share/org/apache/tomcat/startup/Main.java Index: Main.java =================================================================== RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/startup/Main.java,v retrieving revision 1.20 retrieving revision 1.21 diff -u -r1.20 -r1.21 --- Main.java 2001/02/10 00:55:37 1.20 +++ Main.java 2001/02/10 08:12:41 1.21 @@ -66,7 +66,8 @@ import java.util.*; import java.net.*; -import org.apache.tomcat.util.SimpleClassLoader; +// XXX This should be replaced by JdkCompat +import org.apache.tomcat.util.compat.SimpleClassLoader; import org.apache.tomcat.util.IntrospectionUtils; // Depends: @@ -184,9 +185,10 @@ urlV.addElement( new URL( "file", null , System.getProperty( "java.home" ) +"/../lib/tools.jar")); URL[] serverClassPath=getURLs(urlV); // ClassLoader for webapps it uses a shared dir as repository, distinct from lib + URL[] sharedClassPath=getURLs(getClassPathV(getSharedDir())); URL[] commonClassPath=getURLs(getClassPathV(getCommonDir())); - ClassLoader commonCl= IntrospectionUtils.getURLClassLoader(commonClassPath , parentL ); + // XXX Should be: JdkCompat.newClassLoaderInstance !! ClassLoader commonCl= IntrospectionUtils.getURLClassLoader(commonClassPath , parentL ); ClassLoader sharedCl= IntrospectionUtils.getURLClassLoader(sharedClassPath , commonCl ); ClassLoader serverCl= IntrospectionUtils.getURLClassLoader(serverClassPath , commonCl ); if( commonCl==null ) { 1.4 +1 -3 jakarta-tomcat/src/share/org/apache/tomcat/util/compat/Jdk11Compat.java Index: Jdk11Compat.java =================================================================== RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/compat/Jdk11Compat.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- Jdk11Compat.java 2001/02/10 00:55:37 1.3 +++ Jdk11Compat.java 2001/02/10 08:12:42 1.4 @@ -60,8 +60,6 @@ package org.apache.tomcat.util.compat; import java.net.URL; -// XXX move it here, it's 1.1 specific -import org.apache.tomcat.util.SimpleClassLoader; /** General-purpose utility to provide backward-compatibility and JDK independence. This allow use of JDK1.2 ( or higher ) facilities if @@ -117,7 +115,7 @@ } public URL[] getParentURLs(ClassLoader cl){ SimpleClassLoader scl=(SimpleClassLoader)cl; - return ((SimpleClassLoader)scl.getParent()).getURLs(); + return ((SimpleClassLoader)scl.getParentLoader()).getURLs(); } // Other methods, as needed 1.1 jakarta-tomcat/src/share/org/apache/tomcat/util/compat/SimpleClassLoader.java Index: SimpleClassLoader.java =================================================================== /* * Copyright (c) 1997-1999 The Java Apache Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the Java Apache * Project for use in the Apache JServ servlet engine project * <http://java.apache.org/>." * * 4. The names "Apache JServ", "Apache JServ Servlet Engine" and * "Java Apache Project" must not be used to endorse or promote products * derived from this software without prior written permission. * * 5. Products derived from this software may not be called "Apache JServ" * nor may "Apache" nor "Apache JServ" appear in their names without * prior written permission of the Java Apache Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the Java Apache * Project for use in the Apache JServ servlet engine project * <http://java.apache.org/>." * * THIS SOFTWARE IS PROVIDED BY THE JAVA APACHE PROJECT "AS IS" AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JAVA APACHE PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * This software consists of voluntary contributions made by many * individuals on behalf of the Java Apache Group. For more information * on the Java Apache Project and the Apache JServ Servlet Engine project, * please see <http://java.apache.org/>. * */ package org.apache.tomcat.util.compat; import java.io.*; import java.lang.*; import java.net.*; import java.text.*; import java.util.*; import java.util.zip.*; import java.security.*; /** * This is a JDK1.1 equivalent of URLClassLoader. It have no dependency on * tomcat or any other api - just standard java. * * Based on AdaptiveClassLoader from JServ1, with the dependency check * and reloading features removed ( and moved to an external component) * This is based on the fact that class loading and dependency checking can * be separated and we want to support multiple forms of class loaders. * * The interface also changed to match URLClassLoader. * This class should be used _only_ with JDK1.1, for JDK1.2 you * should use a class loader that is aware of Permissions and the * new rules ( sealing, etc ) * * This class loader respects the standard order defined in the ClassLoader * documentation - for a different order you can plug in a different * class loader ( in the configurations ). * * Since this class loader will be visible to applications we need * to prevent exploits - we'll minimize the public method usage. * * The class path can be set only when the object is constructed. */ public class SimpleClassLoader extends ClassLoader { private static final int debug=0; /** * The classpath which this classloader searches for class definitions. * Each element of the vector should be either a directory, a .zip * file, or a .jar file. * <p> * It may be empty when only system classes are controlled. */ protected URL urls[]; /** * A parent class loader for delegation of finding a class definition. * JDK 1.2 contains parent class loaders as part of java.lang.ClassLoader, * the parent being passed to a constructor, and retreived with * getParent() method. For JDK 1.1 compatibility, we'll duplicate the * 1.2 private member var. */ protected ClassLoader parent; /** Reserved names - this class loader will not allow creation of classes that start with one of those strings. */ protected String reserved[]; SecurityManager sm; //------------------------------------------------------- Constructors public SimpleClassLoader( URL urls[]) { super(); // will check permissions this.urls=urls; sm=System.getSecurityManager(); checkURLs(); } public SimpleClassLoader( URL urls[], ClassLoader parent ) { super(); // will check permissions this.urls=urls; this.parent=parent; sm=System.getSecurityManager(); checkURLs(); } /** This is the prefered constructor to be used with this class loader */ public SimpleClassLoader( URL urls[], ClassLoader parent, String reserved[] ) { super(); // will check permissions this.urls=urls; this.parent=parent; this.reserved=reserved; sm=System.getSecurityManager(); checkURLs(); } /** We can't declare a method "getParent" since it'll not compile in JDK1.2 - the method is final. But we don't have to - this will be used via JdkCompat */ public ClassLoader getParentLoader() { return parent; } private void checkURLs() { int cnt=0; for( int i=0; i<urls.length; i++ ) { URL cp = urls[i]; String fileN = cp.getFile(); File file=new File( fileN ); if( ! file.exists() ) urls[i]=null; if( file.isDirectory() && ! fileN.endsWith("/") ) { try { urls[i]=new URL("file", null, fileN + "/" ); } catch(MalformedURLException e ) { } } } } // debug only void log( String s ) { System.out.println("SimpleClassLoader: " + s ); } //------------------------------------ Implementation of Classloader /* * XXX: The javadoc for java.lang.ClassLoader says that the * ClassLoader should cache classes so that it can handle repeated * requests for the same class. On the other hand, the JLS seems * to imply that each classloader is only asked to load each class * once. Is this a contradiction? * * Perhaps the second call only applies to classes which have been * garbage-collected? */ /** * Resolves the specified name to a Class. The method loadClass() * is called by the virtual machine. As an abstract method, * loadClass() must be defined in a subclass of ClassLoader. * * @param name the name of the desired Class. * @param resolve true if the Class needs to be resolved; * false if the virtual machine just wants to determine * whether the class exists or not * @return the resulting Class. * @exception ClassNotFoundException if the class loader cannot * find a the requested class. */ protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { if( debug>0) log( "loadClass() " + name + " " + resolve); // The class object that will be returned. Class c = null; // check if the class was already loaded c = findLoadedClass( name ); if (c!= null ) { if(resolve) resolveClass(c); return c; } // Attempt to load the class from the parent class loader // (untrusted case) if (parent != null) { try { c = parent.loadClass(name); if (c != null) { if( debug>0) log( "loadClass() from parent " + name); if (resolve) resolveClass(c); return c; } } catch (Exception e) { c = null; } } // Attempt to load the class from the system class loader try { c = findSystemClass(name); if (c != null) { if( debug>0) log( "loadClass() from system " + name); if (resolve) resolveClass(c); return c; } } catch (Exception e) { c = null; } // Make sure we can access this class when using a SecurityManager if (sm != null) { int i = name.lastIndexOf('.'); if (i >= 0) { sm.checkPackageAccess(name.substring(0,i)); sm.checkPackageDefinition(name.substring(0,i)); } } // make sure the class is not in a "reserved" package. if( reserved!=null ) { for( int i=0; i<reserved.length; i++ ) { if( name.startsWith( reserved[i] )) { if( debug>0) log( "reserved: " + name + " " + reserved[i]); throw new ClassNotFoundException(name); } } } if( urls==null ) throw new ClassNotFoundException(name); // Translate class name to file name String classFileName = name.replace('.', '/') + ".class"; // It's '/' not File.Separator - at least that's how URLClassLoader // does it and I suppose there are reasons ( costin ) Resource r=doFindResource( classFileName ); if( r==null ) throw new ClassNotFoundException(name); byte[] classData=null; if( r.file != null ) { InputStream in=null; try { in = new FileInputStream(r.file); classData=loadBytesFromStream(in, (int) r.file.length()); } catch (IOException ioex) { return null; } finally { try { if( in!=null) in.close(); } catch( IOException ex ) {} } } else if( r.zipEntry != null ) { try { classData=loadBytesFromStream(r.zipFile. getInputStream(r.zipEntry), (int)r.zipEntry.getSize()); } catch (IOException ioex) { return null; } finally { try { r.zipFile.close(); } catch ( IOException ignored ) { } } } if (classData != null) { try { c = defineClass(name, classData, 0, classData.length ); if (resolve) resolveClass(c); if( debug>0) log( "loadClass() from local repository " + name); return c; } catch(Throwable t ) { t.printStackTrace(); } } // If not found in any repository throw new ClassNotFoundException(name); } /** * Find a resource with a given name. The return is a URL to the * resource. Doing a getContent() on the URL may return an Image, * an AudioClip,or an InputStream. * * @param name the name of the resource, to be used as is. * @return an URL on the resource, or null if not found. */ public URL getResource(String name) { if( debug > 0 ) log( "getResource() " + name ); URL u = getSystemResource(name); if (u != null) { return u; } Resource r=doFindResource( name ); if( r==null ) return null; // Construct a file://-URL if the repository is a directory if( r.file != null ) { // Build a file:// URL form the file name try { return new URL("file", null, r.file.getAbsolutePath()); } catch(java.net.MalformedURLException badurl) { badurl.printStackTrace(); return null; } } // a jar:-URL *could* change even between minor releases, but // didn't between JVM's 1.1.6 and 1.3beta. Tested on JVM's from // IBM, Blackdown, Microsoft, Sun @ Windows and Sun @ Solaris if( r.zipEntry != null ) { try { return new URL("jar:file:" + r.repository.getPath() + "!/" + name); } catch(java.net.MalformedURLException badurl) { badurl.printStackTrace(); return null; } finally { try { r.zipFile.close(); } catch ( IOException ignored ) { } } } // Not found return null; } /** * Get an InputStream on a given resource. Will return null if no * resource with this name is found. * <p> * The JServClassLoader translate the resource's name to a file * or a zip entry. It looks for the resource in all its repository * entry. * * @see java.lang.Class#getResourceAsStream(String) * @param name the name of the resource, to be used as is. * @return an InputStream on the resource, or null if not found. */ public InputStream getResourceAsStream(String name) { // Try to load it from the system class if( debug > 0 ) log( "getResourceAsStream() " + name ); // InputStream s = getSystemResourceAsStream(name); InputStream s = null; // Get this resource from system class loader s = getSystemResourceAsStream(name); if( debug>0 ) log( "System resource " + s ); if (s != null) { return s; } Resource r=doFindResource( name ); if( r==null ) return null; if( r.file!=null ) { if( debug > 0 ) log( "Found " + r.file); try { InputStream res=new FileInputStream(r.file); return res; } catch (IOException shouldnothappen) { shouldnothappen.printStackTrace(); return null; } } else if( r.zipEntry != null ) { if( debug > 0 ) log( "Found " + r.zipEntry); // workaround - the better solution is to not close the // zipfile !!!! try { byte[] data= loadBytesFromStream(r.zipFile. getInputStream(r.zipEntry), (int) r.zipEntry.getSize()); if(data != null) { InputStream istream = new ByteArrayInputStream(data); return istream; } } catch(IOException e) { } finally { // if we close the zipfile bad things will happen - // we can't read the stream on some VMs if ( r.zipFile != null ) { try { r.zipFile.close(); } catch ( IOException ignored ) { } } } } return s; } // -------------------- Private methods -------------------- /** Private class used to store the result of the search */ private class Resource { /* Repository used to find the resource */ File repository; /* File - if the resource is a file */ File file; /* Zip file and entry if it's in a jar */ ZipEntry zipEntry; ZipFile zipFile; } // common code to find the resource private Resource doFindResource( String name ) { Resource r=new Resource(); for( int i=0; i<urls.length; i++ ) { URL cp = urls[i]; if( cp==null ) continue; String fileN = cp.getFile(); File file=new File( fileN ); if (fileN.endsWith("/")) { String fileName = name.replace('/', File.separatorChar); File resFile = new File(file, fileName); if (resFile.exists()) { r.file=resFile; r.repository=file; return r; } } else { try { ZipFile zf = new ZipFile(file.getAbsolutePath()); ZipEntry ze = zf.getEntry(name); //if( debug > 0 ) log( "Searching " + file + " " + name ); if (ze != null) { r.zipEntry=ze; r.zipFile=zf; r.repository=file; return r; } } catch (IOException ioe) { ioe.printStackTrace(); System.out.println("Name= " + name + " " + file ); return null; } } } return null; } /** * Loads all the bytes of an InputStream. */ private byte[] loadBytesFromStream(InputStream in, int length) throws IOException { byte[] buf = new byte[length]; int nRead, count = 0; while ((length > 0) && ((nRead = in.read(buf,count,length)) != -1)) { count += nRead; length -= nRead; } return buf; } public URL[] getURLs() { //TODO: Add custom implementation. return urls; } } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]