DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG·
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://issues.apache.org/bugzilla/show_bug.cgi?id=23344>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND·
INSERTED IN THE BUG DATABASE.

http://issues.apache.org/bugzilla/show_bug.cgi?id=23344


[EMAIL PROTECTED] changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|FIXED                       |




------- Additional Comments From [EMAIL PROTECTED]  2005-06-15 02:48 -------
While working on building tomcat-5.0.28 and testing web apps I came across the
same problem. I dived into the source code and fixed the actual problem (rather
than using url, eg, file:///<path>/<file>.jar). Please refer to the explanation
below.

When adding a jar file (eg, "foo/bar.jar") to the class loader's repository it
treats as a directory and therefore it cannot load any classes from this jar.
The following explains why it happens.
        
--org.apache.catalina.startup.ClassLoaderFactory-- is responsible for creating
class loader instances. Each instance is of
org.apache.catalina.loader.StandardClassLoader type, which in its turn extends
java.net.URLClassLoader:

java.net.URLClassLoader
       / | \
         |
         |
org.apache.catalina.loader.StandardClassLoader
                
        
--ClassLoaderFactory#createClassLoader(File unpacked[], File packed[], URL
urls[], ClassLoader parent)-- is the actual method that creates class loaders.
First argument (ie unpacked) contains jar files or directories ( that is where
the name "unpacked" comes from ). 
Second argument (ie packed) is a directory packed with jar files
        
ClassLoaderFactory#createClassLoader method adds File.separator to the end of
the jar file path ( file.getCanonicalPath() + File.separator ) when constructing
a URL instance to represent a jar file and then adds a string representation of
a newly created URL to its list of repositories ( list.add(url.toString()) ) :
                        
-----------------------------------------------------------------------------
if (unpacked != null) {
  for (int i = 0; i < unpacked.length; i++)  {
        File file = unpacked[i];
        if (!file.exists() || !file.canRead())
            continue;
            if (debug >= 1)
                 log("  Including directory or JAR " 
                                + file.getAbsolutePath());
            URL url = new URL("file", null, 
                               file.getCanonicalPath() + File.separator);
            list.add(url.toString());
  }
}
               
-----------------------------------------------------------------------------
                
For instance, if "unpacked" argument contains '/home/aa/lib/velocity.jar' then a
URL object is 'file:/home/aa/lib/velocity.jar/' - a forward slash / (which is a
Unix file separator) has been added to the url.
        
After ClassLoaderFactory#createClassLoader adds all repositories to its
repository list it converts this list to array and constructs
StandardClassLoader with it:
        
                
-----------------------------------------------------------------------------
String array[] = (String[]) list.toArray(new String[list.size()]);
StandardClassLoader classLoader = null;
if (parent == null)
  classLoader = new StandardClassLoader(array);
            
-----------------------------------------------------------------------------
            
StandardClassLoader( String[] ) constructor converts each repository found in
the given array argument to a URL object:
                
-----------------------------------------------------------------------------
protected static URL[] convert(String input[], URLStreamHandlerFactory factory) 
{
  .....
  url[i] = new URL(null, input[i], streamHandler);
  .....
}
                
-----------------------------------------------------------------------------
                                   
For instance, if the repositories array of String type contains
'file:/home/aa/lib/velocity.jar/' then a URL object is
'file:/home/aa/lib/velocity.jar/'. If the repository holds a path on Windows
machine then the URL object would have all backslashes  replaced all  with
forward slashes ( URL object crated with new URL(null,
"file:I:\lib\velocity.jar\", streamHandler) would have
"file:I:/lib/velocity.jar/" string representation ).
    
Once StandardClassLoader( String[] ) converts repository array of a String type
into a URL type it calls its super constructor, which in fact is a
URLClassLoader( URL[] ).
    
However, the contract for URLClassLoader( URL[] ) constructor indicates that
"Any URL that ends with a '/' is assumed to refer to a directory. " and
therefore a jar file gets ignored by the loader.
    
For instance, if the repositories array contains
'file:/home/aa/lib/velocity.jar/' url object the URLClassLoader( URL[] )
constructor treats this url as a directory and therefore a jar file is never
properly loaded.
    
Therefore, a File.separator that got added to a jar file in
ClassLoaderFactory#createClassLoader method made it invalid because the actual
class loader assumes that this jar file is a directory.

-- 
Configure bugmail: http://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to