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]