You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by James THOMAS <Ja...@enovia.com> on 2001/09/06 22:09:04 UTC

Tomcat 3.3 (JDK 1.1 compatibility fixes)

Hello, I've provided below JDK 1.1 compatibility fixes for Tomcat 3.3.  Can
someone please add these fixes to the code?  I believe you'll find that the
fixes are trivial except for the last one.  The last problem I described
below concerns the way the class loaders are implemented.  I have a
solution that works but I think it needs to be verified.   Thank you for
your time.  James.



======================================================================
File:  jakarta-tomcat-3.3-dev-src\src\build.xml
======================================================================
Line:  301
Add the following line:
     <exclude name="**/util/depend/DependClassLoader12.java" unless
="jdk12.present"/>
Reason:
     We don't want to compile the class "DependClassLoader12" when JDK 1.1
is used to compile Tomcat 3.3

======================================================================
File:
jakarta-tomcat-3.3-dev-src\src\admin\WEB-INF\classes\tadm\AntTag.java
======================================================================
Line: 24
    targets.clear();
Change to:
    targets.removeAllElements();
Reason:
     The method "clear" does not exist on Vector class in JDK 1.1

======================================================================
File:
jakarta-tomcat-3.3-dev-src\src\share\org\apache\tomcat\startup\EmbededTomcat.java
======================================================================
Line:  198
     attributes.put( name, v );
Change To:
     if( v == null )
          attributes.remove( name );
     else
          attributes.put( name, v );
Reason:
     When running with JDK 1.1, the value of the "parentClassLoader" is
null, which will cause an exception because null values cannot be placed
into a hashtable.  As a generic solution, I recommend changing the
implementation to treat a "setAttribute" with a null value as a request to
remove the current attribute value.

======================================================================
File:
jakarta-tomcat-3.3-dev-src\src\share\org\apache\tomcat\startup\Main.java
======================================================================
Line: 215-216
     System.setProperty( "tomcat.home", installDir );
     System.setProperty("java.security.policy",  policyFile);
Change To:
     System.getProperties().put( "tomcat.home", installDir );
     System.getProperties().put("java.security.policy",  policyFile);
Reason:
     The method "setProperty" does not exist in JDK 1.1

======================================================================
File:
jakarta-tomcat-3.3-dev-src\src\share\org\apache\tomcat\util\compat\Jdk11Compat.java
======================================================================
Line: 142
     }while((cl!=null) && ( depth < c ));
Change To:
     }while((cl!=null) && ( depth >= c ));
Reason:
     The loop condition is incorrect.  This bug cause JSP compilation
errors because the classpath does not contain the common classpath (which
includes the servlet.jar).

======================================================================
File:
jakarta-tomcat-3.3-dev-src\src\share\org\apache\tomcat\util\depend\DependClassLoader.java
======================================================================
The method "loadClassInternal" appears to be incorrect.  When loading a
class, the code first retrieves the class as a resource from the "parent"
class loader.  But, the return value from the "getResource" is not used
because the code then delegates the class loading to the "parent2" class
loader ("parent2.loadClass(name)").  When running with JDK 1.1, the
"getResource" returns null because the "jar" protocol is not valid (the
exception message "unknown protocol: jar" is thrown from SimpleClassLoader
where a java.net.URL is constructed).  This causes the "loadClassInternal"
method to throw a "ClassNotFoundException" prematurely because the class
can successfully be loaded by one of the the parent class loaders.  Below I
offer a solution but I think it would be best if someone with a more
in-depth understanding of the code can validate this solution.

Side note: with the solution below, we can eliminate the need for the
"parent2" attribute held by the "DependClassLoader" class.

protected Class loadClassInternal( String name, boolean resolve )
      throws ClassNotFoundException
   {
      if( debug>0) log( "loadClass() " + name + " " + resolve);
      Class c = null;

      // check if  we already loaded this class
        c = findLoadedClass( name );
        if( c != null ) {
         //System.out.println( "class already loaded" );
           if( resolve )
            resolveClass( c );
         return c;
      }

      // check parent class
      if( parent != null ) {
         try {
            c = parent.loadClass( name );
            //System.out.println( "class loaded by parent" );
            return c;
         }
         catch( ClassNotFoundException e ) {
         }
      }

      throw new ClassNotFoundException(name);
   }


James Thomas
ENOVIA Corp.
704 - 944 - 8933
james_THOMAS@enovia.com


Re: Tomcat 3.3 (JDK 1.1 compatibility fixes)

Posted by cm...@yahoo.com.
Thanks James, I'm very happy to see your contributions. ( and my
appologies for not testing with 1.1 often enough ).

> jakarta-tomcat-3.3-dev-src\src\share\org\apache\tomcat\util\depend\DependClassLoader.java
> ======================================================================
> The method "loadClassInternal" appears to be incorrect.  When loading a
> class, the code first retrieves the class as a resource from the "parent"
> class loader.  But, the return value from the "getResource" is not used
> because the code then delegates the class loading to the "parent2" class
> loader ("parent2.loadClass(name)").  When running with JDK 1.1, the
> "getResource" returns null because the "jar" protocol is not valid (the
> exception message "unknown protocol: jar" is thrown from SimpleClassLoader
> where a java.net.URL is constructed).  This causes the "loadClassInternal"
> method to throw a "ClassNotFoundException" prematurely because the class
> can successfully be loaded by one of the the parent class loaders.  Below I
> offer a solution but I think it would be best if someone with a more
> in-depth understanding of the code can validate this solution.

The code is a bit tricky. 3.3 uses normal URLClassLoaders for loading, but
in order to support reloading we use an additional wrapper (
DependClassLoader ) that will collect dependencies ( since a servlet/jsp
can depend on multiple jars/classes ).

For DCL, "parent" is the webapp class loader. "parent2" is the
applications class loader, parent of all webapp loaders.

The code tries to make DependClassLoader as non-intrusive as possible (
i.e. the behavior of using DCL should be as close as possible to 'normal'
).

If a class can be loaded by parent2 ( the common app loader ), then we
just delegate to it ( that's the normal delegation that would be used if
no DCL was present ). We don't delegate to parent because then all classes
loaded as result of resolving the current class would not be registered as
depends ( parent will do all the loading without any notification ).

If not, we'll use parent to get the bytes - then load them. The reason we
have DependClassLoader12 is to support the security context - I couldn't
find any other way ( like via jdkcompat ) since we need to call a
protected method in super.


>       // check parent class
>       if( parent != null ) {
>          try {
>             c = parent.loadClass( name );

^^^ That will not brake part of reloading - parent will load all classes
that are requested by the current class, and we'll not be able to record
that...

I'll try to find another fix ( nice try ! :-).

Costin