JDK-4258001 : UNC support in Classpath
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 1.2.0,1.2.2,1.3.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic,windows_nt
  • CPU: generic,x86
  • Submitted: 1999-07-28
  • Updated: 2001-02-05
  • Resolved: 2001-02-05
Related Reports
Duplicate :  
Duplicate :  
Description

Name: vi73552			Date: 07/28/99


I am loading class files and the JVM across a network
using the standard UNC in a .bat file for the path and classpath.
Such as \\servername\directoryname.

I am using a clean machine(s) Windows 9x with no JVM on it.

When I launch the bat file, the JVM loads and scores of
classes load from the rt.jar (I know this because I use the
-verbose switch).

However, the application fails because I get the error message: 
Execption in thread "main" java.lang.Error: can't load javax.swing.
plaf.metal.MetalLookAndFeel
(Review ID: 93163) 
======================================================================

Name: krT82822			Date: 09/27/99


Set up CLASSPATH using UNC pathnames, e.g.,
CLASSPATH:
  .
  \\gaa\c\TnG\packages\class
  \\gaa\c\ASG\Java\packages\class
  \\gaa\c\Apps\Sun\jdk1.2.2\lib\tools.jar
  \\gaa\c\c\Apps\Sun\jre1.2\lib\rt.jar
  \\gaa\c\Apps\Sun\jre1.2\lib\comm.jar
  \\gaa\c\Apps\Symantec\VisualCafe\bin\components\sfc.jar

Now invoke the javac compiler. The compiler claims to be unable
to find a resource bundle:

Exception in thread "main" java.lang.Error: Fatal: Resource for javac is missing
        at sun.tools.javac.Main.initResource(Main.java:126)
        at sun.tools.javac.Main.getText(Main.java:152)
        at sun.tools.javac.Main.getText(Main.java:146)
        at sun.tools.javac.Main.getText(Main.java:142)
        at sun.tools.javac.Main.error(Main.java:99)
        at sun.tools.javac.Main.usage_error(Main.java:113)
        at sun.tools.javac.Main.compile(Main.java:455)
        at sun.tools.javac.Main.main(Main.java:733)

Redefine the CLASSPATH using drive letters, e.g.,

  CLASSPATH:
  .
  c:\TnG\packages\class
  c:\ASG\Java\packages\class
  c:\Apps\Sun\jdk1.2.2\lib\tools.jar
  c:\Apps\Sun\jre1.2\lib\rt.jar
  c:\Apps\Sun\jre1.2\lib\comm.jar
  c:\Apps\Symantec\VisualCafe\bin\components\sfc.jar

and the problem vanishes.

Using UNC names does not appear to affect anything else.
(Review ID: 95770)
======================================================================

Name: skT88420			Date: 02/29/2000


java version "1.2.2"
Classic VM (build JDK-1.2.2-001, native threads, symcjit)

I have modified the JVM system class loader so that URLs may be added to the
CLASSPATH.  This would allow an organization to place an item such
as "http://intranet.domain.com/Java/" into the CLASSPATH of all client
computers, and centrally manage all of the Java classes for the entire network
on that web server.
(Review ID: 101846)
======================================================================

Name: skT88420			Date: 03/17/2000


java version "1.2.2"
Classic VM (build JDK-1.2.2-001, native threads, symcjit)


The original diff I submitted caused the original file CLASSPATHs to not work.
This fixes the bug I introduced, and is intended as a replacement for the
original diff I submitted.

My enhancement was also attached to bug #4258001.  I have tested this bug
against my code, and it appears to no longer be a problem.

RELATED BUGS:
4258001
(Review ID: 102557)
======================================================================

Comments
EVALUATION The code that's failing is (from SwingUtilities.loadSystemClass): Class.forName(className,true,ClassLoader.getSystemClassLoader()); where className is "javax.swing.plaf.metal.MetalLookAndFeel" (see UIManager.java). I don't believe that Swing is the source of the problem so I'm reassigning it to classes_io per bug 4032066. hans.muller@Eng 1999-09-21 4258001 is a different bug than 4032066. The latter is about handling UNC pathnames in the various java.io classes; it was fixed in both 1.1.6 and 1.2beta3. The former is about UNC pathnames in the class-loading machinery, which makes use of the I/O classes but also includes a lot of other complicated URL stuff. I could believe that 4258001 is a real bug, but it might also be an artifact of the submitter's environment. Reassigning to runtime for further evaluation. -- mr@eng 1999/9/22 This happens in swing code when rt.jar is in the bootstrap class path. ###@###.### 1999-09-23 fred.oliver@East 2001-02-05 This bug contains two completely separate situations ... (1) Something (resources) does not work when UNC pathnames are used (which is definitely a win32-only thing). This appears to be a duplicate of 4180841, which is fixed in 1.3. I am able to reproduce this problem with 1.2.2, but not with 1.3. (2) Why can't I put a URL in my class path (in addition to jar files or class directories)? This is a new feature request, not a bug. Since this has nothing to do with the original bug, I have created a new rfe, just for this (4411894).
11-06-2004

WORK AROUND Name: vi73552 Date: 07/28/99 Everything works OK if you map a drive. ====================================================================== Name: krT82822 Date: 09/27/99 Don't use UNC names in the CLASSPATH if you use the Sun javac. (Review ID: 95770) ======================================================================
11-06-2004

SUGGESTED FIX tors first while ((pos = cp.indexOf(File.pathSeparator, lastPos)) != -1) { maxCount++; lastPos = pos + 1; } ! path = new File[maxCount]; lastPos = pos = 0; // Now scan for each path component while ((pos = cp.indexOf(File.pathSeparator, lastPos)) != -1) { if (pos - lastPos > 0) { ! path[count++] = new File(cp.substring(lastPos, pos)); } else { // empty path component translates to "." ! path[count++] = new File("."); } lastPos = pos + 1; } // Make sure we include the last path component if (lastPos < cp.length()) { ! path[count++] = new File(cp.substring(lastPos)); } else { ! path[count++] = new File("."); } // Trim array to correct size if (count != maxCount) { ! File[] tmp = new File[count]; System.arraycopy(path, 0, tmp, 0, count); path = tmp; } } else { ! path = new File[0]; } // DEBUG //for (int i = 0; i < path.length; i++) { --- 334,401 ---- return new URLClassPath(urls, factory); } ! // No longer needed - getClassPath() now returns URLs ! // private static URL[] pathToURLs(String[] path) { ! // URL[] urls = new URL[path.length]; ! // for (int i = 0; i < path.length; i++) { ! // urls[i] = getFileURL(path[i]); ! // } ! // // DEBUG ! // //for (int i = 0; i < urls.length; i++) { ! // // System.out.println("urls[" + i + "] = " + '"' + urls[i] + '"'); ! // //} ! // return urls; ! // } ! private static URL[] getClassPath(String cp) { ! URL[] path; if (cp != null) { int count = 0, maxCount = 1; int pos = 0, lastPos = 0; + String pathItem; // Count the number of separators first while ((pos = cp.indexOf(File.pathSeparator, lastPos)) != -1) { maxCount++; lastPos = pos + 1; } ! path = new URL[maxCount]; lastPos = pos = 0; // Now scan for each path component while ((pos = cp.indexOf(File.pathSeparator, lastPos)) != -1) { if (pos - lastPos > 0) { ! pathItem = cp.substring(lastPos, pos); } else { // empty path component translates to "." ! pathItem = "."; } + try { + path[count] = new URL(pathItem); + } catch (MalformedURLException e) { + path[count] = getFileURL(new File(pathItem)); + } lastPos = pos + 1; + count++; } // Make sure we include the last path component if (lastPos < cp.length()) { ! pathItem = cp.substring(lastPos); } else { ! pathItem = "."; ! } ! try { ! path[count] = new URL(pathItem); ! } catch (MalformedURLException e) { ! path[count] = getFileURL(new File(pathItem)); } + count++; // Trim array to correct size if (count != maxCount) { ! URL[] tmp = new URL[count]; System.arraycopy(path, 0, tmp, 0, count); path = tmp; } } else { ! path = new URL[0]; } // DEBUG //for (int i = 0; i < path.length; i++) { *************** *** 443,454 **** class PathPermissions extends PermissionCollection { ! private File path[]; private Permissions perms; URL codeBase; ! PathPermissions(File path[]) { this.path = path; this.perms = null; --- 458,469 ---- class PathPermissions extends PermissionCollection { ! private URL path[]; private Permissions perms; URL codeBase; ! PathPermissions(URL path[]) { this.path = path; this.perms = null; *************** *** 480,510 **** AccessController.doPrivileged(new PrivilegedAction() { public Object run() { for (int i=0; i < path.length; i++) { - File f = path[i]; - String path; - try { - path = f.getCanonicalPath(); - } catch (IOException ioe) { - path = f.getAbsolutePath(); - } if (i == 0) { ! codeBase = Launcher.getFileURL(new File(path)); } ! if (f.isDirectory()) { ! if (path.endsWith(File.separator)) { ! perms.add(new FilePermission(path+"-", "read")); ! } else { ! perms.add(new FilePermission(path + ! File.separator+"-", "read")); ! } } else { ! int endIndex = path.lastIndexOf(File.separatorChar); ! if (endIndex != -1) { ! path = path.substring(0, endIndex+1) + "-"; ! perms.add(new FilePermission(path, "read")); ! } else { ! // XXX? ! } } } return null; --- 495,530 ---- AccessController.doPrivileged(new PrivilegedAction() { public Object run() { for (int i=0; i < path.length; i++) { if (i == 0) { ! codeBase = path[i]; } ! if (path[i].getProtocol().equals("file")) { ! File f = new File(path[i].getFile().replace('/', File.separatorChar)); ! String pathItem = f.getAbsolutePath(); ! int endIndex; ! ! if (f.isDirectory() && !pathItem.endsWith (File.separator)) { ! pathItem = pathItem + File.separator; ! } ! endIndex = pathItem.lastIndexOf(File.separatorChar); ! if (endIndex != -1) { ! pathItem = pathItem.substring(0, endIndex+1) + "- "; ! perms.add(new FilePermission(pathItem, "read")); ! } else { ! // XXX? ! } } else { ! try { ! Permission perm = path[i].openConnection ().getPermission(); ! ! // Don't add AllPermission if subclass didn't override ! // getPermission() ! if (!(perm instanceof java.security.AllPermission)) { ! perms.add(perm); ! } ! } catch (IOException e) { ! // Ignore error - Assume there's no permission to add ! } } } return null; FILES CHANGED: share/classes/sun/misc/Launcher.java (Review ID: 102557) ======================================================================
11-06-2004

SUGGESTED FIX Name: skT88420 Date: 02/29/2000 *** share\classes\sun\misc\Launcher.java Tue Jun 29 03:18:22 1999 --- share\classes\sun\misc\Launcher.java.new Mon Feb 28 20:36:10 2000 *************** *** 177,183 **** if (files != null) { for (int j = 0; j < files.length; j++) { File f = new File(dirs[i], files[j]); ! urls.add(getFileURL(f)); } } } --- 177,183 ---- if (files != null) { for (int j = 0; j < files.length; j++) { File f = new File(dirs[i], files[j]); ! urls.add(getFileURL(f.getAbsolutePath())); } } } *************** *** 213,233 **** return null; } ! private static AccessControlContext getContext(File[] dirs) ! throws IOException ! { ! PathPermissions perms = ! new PathPermissions(dirs); ! ! ProtectionDomain domain = ! new ProtectionDomain(new CodeSource(perms.getCodeBase(), null), ! perms); ! ! AccessControlContext acc = ! new AccessControlContext(new ProtectionDomain[] { domain }); ! ! return acc; ! } } /** --- 213,234 ---- return null; } ! // This method isn't used, and is no longer similar to the one below. ! // private static AccessControlContext getContext(File[] dirs) ! // throws IOException ! // { ! // PathPermissions perms = ! // new PathPermissions(dirs); ! // ! // ProtectionDomain domain = ! // new ProtectionDomain(new CodeSource(perms.getCodeBase(), null), ! // perms); ! // ! // AccessControlContext acc = ! // new AccessControlContext(new ProtectionDomain[] { domain }); ! // ! // return acc; ! // } } /** *************** *** 240,253 **** throws IOException { final String s = System.getProperty("java.class.path"); ! final File[] path = (s == null) ? new File[0] : getClassPath(s); return (AppClassLoader) AccessController.doPrivileged(new PrivilegedAction() { public Object run() { ! URL[] urls = ! (s == null) ? new URL[0] : pathToURLs(path); ! return new AppClassLoader(urls, extcl); } }, getContext(path)); } --- 241,252 ---- throws IOException { final String s = System.getProperty("java.class.path"); ! final URL[] path = (s == null) ? new URL[0] : getClassPath(s); return (AppClassLoader) AccessController.doPrivileged(new PrivilegedAction() { public Object run() { ! return new AppClassLoader(path, extcl); } }, getContext(path)); } *************** *** 290,298 **** * mentioned in the class path. In the case of a jar, it has to * be the directory containing the jar, not just the jar, as jar * files might refer to other jar files. */ ! private static AccessControlContext getContext(File[] cp) throws java.net.MalformedURLException { PathPermissions perms = --- 289,299 ---- * mentioned in the class path. In the case of a jar, it has to * be the directory containing the jar, not just the jar, as jar * files might refer to other jar files. + * Path items that are network based URLs will be given the right + * to connect to that computer. */ ! private static AccessControlContext getContext(URL[] cp) throws java.net.MalformedURLException { PathPermissions perms = *************** *** 323,329 **** urls = (URL[])AccessController.doPrivileged( new PrivilegedAction() { public Object run() { ! return pathToURLs(getClassPath(path)); } } ); --- 324,330 ---- urls = (URL[])AccessController.doPrivileged( new PrivilegedAction() { public Object run() { ! return getClassPath(path); } } ); *************** *** 333,386 **** return new URLClassPath(urls, factory); } ! private static URL[] pathToURLs(File[] path) { ! URL[] urls = new URL[path.length]; ! for (int i = 0; i < path.length; i++) { ! urls[i] = getFileURL(path[i]); ! } ! // DEBUG ! //for (int i = 0; i < urls.length; i++) { ! // System.out.println("urls[" + i + "] = " + '"' + urls[i] + '"'); ! //} ! return urls; ! } ! private static File[] getClassPath(String cp) { ! File[] path; if (cp != null) { int count = 0, maxCount = 1; int pos = 0, lastPos = 0; // Count the number of separators first while ((pos = cp.indexOf(File.pathSeparator, lastPos)) != -1) { maxCount++; lastPos = pos + 1; } ! path = new File[maxCount]; lastPos = pos = 0; // Now scan for each path component while ((pos = cp.indexOf(File.pathSeparator, lastPos)) != -1) { if (pos - lastPos > 0) { ! path[count++] = new File(cp.substring(lastPos, pos)); } else { // empty path component translates to "." ! path[count++] = new File("."); } lastPos = pos + 1; } // Make sure we include the last path component if (lastPos < cp.length()) { ! path[count++] = new File(cp.substring(lastPos)); } else { ! path[count++] = new File("."); } // Trim array to correct size if (count != maxCount) { ! File[] tmp = new File[count]; System.arraycopy(path, 0, tmp, 0, count); path = tmp; } } else { ! path = new File[0]; } // DEBUG //for (int i = 0; i < path.length; i++) { --- 334,401 ---- return new URLClassPath(urls, factory); } ! // No longer needed - getClassPath() now returns URLs ! // private static URL[] pathToURLs(String[] path) { ! // URL[] urls = new URL[path.length]; ! // for (int i = 0; i < path.length; i++) { ! // urls[i] = getFileURL(path[i]); ! // } ! // // DEBUG ! // //for (int i = 0; i < urls.length; i++) { ! // // System.out.println("urls[" + i + "] = " + '"' + urls[i] + '"'); ! // //} ! // return urls; ! // } ! private static URL[] getClassPath(String cp) { ! URL[] path; if (cp != null) { int count = 0, maxCount = 1; int pos = 0, lastPos = 0; + String pathItem; // Count the number of separators first while ((pos = cp.indexOf(File.pathSeparator, lastPos)) != -1) { maxCount++; lastPos = pos + 1; } ! path = new URL[maxCount]; lastPos = pos = 0; // Now scan for each path component while ((pos = cp.indexOf(File.pathSeparator, lastPos)) != -1) { if (pos - lastPos > 0) { ! pathItem = cp.substring(lastPos, pos); } else { // empty path component translates to "." ! pathItem = "."; ! } ! try { ! path[count] = new URL(pathItem); ! } catch (MalformedURLException e) { ! path[count] = getFileURL(pathItem); } lastPos = pos + 1; + count++; } // Make sure we include the last path component if (lastPos < cp.length()) { ! pathItem = cp.substring(lastPos); } else { ! pathItem = "."; ! } ! try { ! path[count] = new URL(pathItem); ! } catch (MalformedURLException e) { ! path[count] = getFileURL(pathItem); } + count++; // Trim array to correct size if (count != maxCount) { ! URL[] tmp = new URL[count]; System.arraycopy(path, 0, tmp, 0, count); path = tmp; } } else { ! path = new URL[0]; } // DEBUG //for (int i = 0; i < path.length; i++) { *************** *** 391,411 **** private static URLStreamHandler fileHandler; ! static URL getFileURL(File file) { ! try { ! file = file.getCanonicalFile(); ! } catch (IOException e) { ! } ! String path = file.getAbsolutePath(); if (File.separatorChar != '/') { path = path.replace(File.separatorChar, '/'); } if (!path.startsWith("/")) { path = "/" + path; } - if (!path.endsWith("/") && file.isDirectory()) { - path = path + "/"; - } if (fileHandler == null) { fileHandler = factory.createURLStreamHandler("file"); } --- 406,418 ---- private static URLStreamHandler fileHandler; ! static URL getFileURL(String path) { if (File.separatorChar != '/') { path = path.replace(File.separatorChar, '/'); } if (!path.startsWith("/")) { path = "/" + path; } if (fileHandler == null) { fileHandler = factory.createURLStreamHandler("file"); } *************** *** 443,454 **** class PathPermissions extends PermissionCollection { ! private File path[]; private Permissions perms; URL codeBase; ! PathPermissions(File path[]) { this.path = path; this.perms = null; --- 450,461 ---- class PathPermissions extends PermissionCollection { ! private URL path[]; private Permissions perms; URL codeBase; ! PathPermissions(URL path[]) { this.path = path; this.perms = null; *************** *** 480,510 **** AccessController.doPrivileged(new PrivilegedAction() { public Object run() { for (int i=0; i < path.length; i++) { - File f = path[i]; - String path; - try { - path = f.getCanonicalPath(); - } catch (IOException ioe) { - path = f.getAbsolutePath(); - } if (i == 0) { ! codeBase = Launcher.getFileURL(new File(path)); } ! if (f.isDirectory()) { ! if (path.endsWith(File.separator)) { ! perms.add(new FilePermission(path+"-", "read")); ! } else { ! perms.add(new FilePermission(path + ! File.separator+"-", "read")); ! } } else { ! int endIndex = path.lastIndexOf(File.separatorChar); ! if (endIndex != -1) { ! path = path.substring(0, endIndex+1) + "-"; ! perms.add(new FilePermission(path, "read")); ! } else { ! // XXX? ! } } } return null; --- 487,522 ---- AccessController.doPrivileged(new PrivilegedAction() { public Object run() { for (int i=0; i < path.length; i++) { if (i == 0) { ! codeBase = path[i]; } ! if (path[i].getProtocol().equals("file")) { ! File f = new File(path[i].getFile()); ! String pathItem = f.getAbsolutePath(); ! int endIndex; ! ! if (f.isDirectory() && !pathItem.endsWith (File.separator)) { ! pathItem = pathItem + File.separator; ! } ! endIndex = pathItem.lastIndexOf(File.separatorChar); ! if (endIndex != -1) { ! pathItem = pathItem.substring(0, endIndex+1) + "- "; ! perms.add(new FilePermission(pathItem, "read")); ! } else { ! // XXX? ! } } else { ! try { ! Permission perm = path[i].openConnection ().getPermission(); ! ! // Don't add AllPermission if subclass didn't override ! // getPermission() ! if (!(perm instanceof java.security.AllPermission)) { ! perms.add(perm); ! } ! } catch (IOException e) { ! // Ignore error - Assume there's no permission to add ! } } } return null; FILES CHANGED: share/classes/sun/misc/Launcher.java (Review ID: 101846) ====================================================================== Name: skT88420 Date: 03/17/2000 *** share\classes\sun\misc\Launcher.java Tue Jun 29 03:18:22 1999 --- share\classes\sun\misc\Launcher.java.new Sat Mar 04 10:16:31 2000 *************** *** 213,233 **** return null; } ! private static AccessControlContext getContext(File[] dirs) ! throws IOException ! { ! PathPermissions perms = ! new PathPermissions(dirs); ! ! ProtectionDomain domain = ! new ProtectionDomain(new CodeSource(perms.getCodeBase(), null), ! perms); ! ! AccessControlContext acc = ! new AccessControlContext(new ProtectionDomain[] { domain }); ! ! return acc; ! } } /** --- 213,234 ---- return null; } ! // This method isn't used, and is no longer similar to the one below. ! // private static AccessControlContext getContext(File[] dirs) ! // throws IOException ! // { ! // PathPermissions perms = ! // new PathPermissions(dirs); ! // ! // ProtectionDomain domain = ! // new ProtectionDomain(new CodeSource(perms.getCodeBase(), null), ! // perms); ! // ! // AccessControlContext acc = ! // new AccessControlContext(new ProtectionDomain[] { domain }); ! // ! // return acc; ! // } } /** *************** *** 240,253 **** throws IOException { final String s = System.getProperty("java.class.path"); ! final File[] path = (s == null) ? new File[0] : getClassPath(s); return (AppClassLoader) AccessController.doPrivileged(new PrivilegedAction() { public Object run() { ! URL[] urls = ! (s == null) ? new URL[0] : pathToURLs(path); ! return new AppClassLoader(urls, extcl); } }, getContext(path)); } --- 241,252 ---- throws IOException { final String s = System.getProperty("java.class.path"); ! final URL[] path = (s == null) ? new URL[0] : getClassPath(s); return (AppClassLoader) AccessController.doPrivileged(new PrivilegedAction() { public Object run() { ! return new AppClassLoader(path, extcl); } }, getContext(path)); } *************** *** 290,298 **** * mentioned in the class path. In the case of a jar, it has to * be the directory containing the jar, not just the jar, as jar * files might refer to other jar files. */ ! private static AccessControlContext getContext(File[] cp) throws java.net.MalformedURLException { PathPermissions perms = --- 289,299 ---- * mentioned in the class path. In the case of a jar, it has to * be the directory containing the jar, not just the jar, as jar * files might refer to other jar files. + * Path items that are network based URLs will be given the right + * to connect to that computer. */ ! private static AccessControlContext getContext(URL[] cp) throws java.net.MalformedURLException { PathPermissions perms = *************** *** 323,329 **** urls = (URL[])AccessController.doPrivileged( new PrivilegedAction() { public Object run() { ! return pathToURLs(getClassPath(path)); } } ); --- 324,330 ---- urls = (URL[])AccessController.doPrivileged( new PrivilegedAction() { public Object run() { ! return getClassPath(path); } } ); *************** *** 333,386 **** return new URLClassPath(urls, factory); } ! private static URL[] pathToURLs(File[] path) { ! URL[] urls = new URL[path.length]; ! for (int i = 0; i < path.length; i++) { ! urls[i] = getFileURL(path[i]); ! } ! // DEBUG ! //for (int i = 0; i < urls.length; i++) { ! // System.out.println("urls[" + i + "] = " + '"' + urls[i] + '"'); ! //} ! return urls; ! } ! private static File[] getClassPath(String cp) { ! File[] path; if (cp != null) { int count = 0, maxCount = 1; int pos = 0, lastPos = 0; // Count the number of separa
11-06-2004