United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-4711907 (cl spec) Class.getResource{AsStream} makes unspecified changes to resource name
JDK-4711907 : (cl spec) Class.getResource{AsStream} makes unspecified changes to resource name

Details
Type:
Bug
Submit Date:
2002-07-09
Status:
Closed
Updated Date:
2012-10-08
Project Name:
JDK
Resolved Date:
2003-12-19
Component:
core-libs
OS:
generic
Sub-Component:
java.lang:class_loading
CPU:
generic
Priority:
P4
Resolution:
Fixed
Affected Versions:
1.4.0,5.0
Fixed Versions:
5.0 (b32)

Related Reports

Sub Tasks

Description

Name: erR10175			Date: 07/08/2002


 
New JCK testcases

api/java_lang/Class/index.html#Reflect2[Class2245]
api/java_lang/Class/index.html#Reflect2[Class2246]

fail with the following messages:
Class2245: Failed. unexpected changes detected
Class2246: Failed. unexpected changes detected
 
because both java.lang.Class.getResource(String name) and 
java.lang.Class.getResourceAsStream(String name), while delegating their call 
to class loader, make changes to the resource name that are not specified
explicitly in the descriptions of the methods.
 
The specification of the methods reads:
"This method delegates the call to its class loader, after making these 
changes to the resource name: if the resource name starts with "/", it is 
unchanged; otherwise, the package name is prepended to the resource name 
after converting "." to "/"."

The RI makes the following changes to the resource name that seem reasonable 
but are not specified in the documentation explicitly:
1. leading "/" is removed;
2. "/" is inserted between package name and resource name;
3. "." is converted to "/" in the package name, but is left unchanged 
   in resource name.
 
The following table shows 5 resource names that tested (the package 
name is "p1.p2"):

----------------------------------------------------------------
resource name        may be expected       made by RI
                     according to spec
----------------------------------------------------------------
"/"                     "/"                  ""            
""                      "p1.p2"            "p1/p2/"
"/repository\\dir/resource.dat" 
              "/repository\\dir/resource.dat"
                                  "repository\\dir/resource.dat"
"x.y.z"              "p1.p2x.y.z"       "p1/p2/x.y.z"
"x/y/z"              "p1.p2x/y/z"       "p1/p2/x/y/z"

----------------------------------------------------------------

To reproduce the first failure compile and run Class2245.java (see below) as 
the following log shows:
$java -version && javac Class2245.java && java Class2245; echo $?
java version "1.4.1-rc"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-rc-b15)
Java HotSpot(TM) Client VM (build 1.4.1-rc-b15, mixed mode)
getResource()
getResource(p1/p2/)
getResource(repository\dir/resource.dat)
getResource(p1/p2/x.y.z)
getResource(p1/p2/x/y/z)
unexpected changes detected
1
 
----------------------- Class2234.java
import java.io.PrintStream;
import java.util.Vector;
import java.net.URL;

/*
 * class loader that defines class p1.p2.B
 * and hook getResource calls
 */

class ResourceGetter extends ClassLoader { 

    protected ResourceGetter(ClassLoader parent) {
        super(parent);
        log = new Vector();
    }
    
    public static final String specialClass = "p1.p2.B";

    /* bytes of an empty class p1.p2.B
     */
    public static final byte[] specialClassCode = {
        (byte)0xCA, (byte)0xFE, (byte)0xBA, (byte)0xBE, 
        (byte)0x00, (byte)0x03, (byte)0x00, (byte)0x2D,
        (byte)0x00, (byte)0x05, (byte)0x07, (byte)0x00, 
        (byte)0x02, (byte)0x01, (byte)0x00, (byte)0x10,
        (byte)0x6A, (byte)0x61, (byte)0x76, (byte)0x61, 
        (byte)0x2F, (byte)0x6C, (byte)0x61, (byte)0x6E,
        (byte)0x67, (byte)0x2F, (byte)0x4F, (byte)0x62, 
        (byte)0x6A, (byte)0x65, (byte)0x63, (byte)0x74,
        (byte)0x07, (byte)0x00, (byte)0x04, (byte)0x01, 
        (byte)0x00, (byte)0x07, (byte)0x70, (byte)0x31,
        (byte)0x2F, (byte)0x70, (byte)0x32, (byte)0x2F, 
        (byte)0x42, (byte)0x00, (byte)0x20, (byte)0x00,
        (byte)0x03, (byte)0x00, (byte)0x01, (byte)0x00, 
        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
        (byte)0x00, (byte)0x00, (byte)0x00
    };

    protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
        if (name.equals(specialClass)) {
            return defineClass(specialClass, specialClassCode, 0, specialClassCode.length);
        } 
        return super.loadClass(name, resolve);
    }
    public Class loadClass(String name) throws ClassNotFoundException {
        return loadClass(name, false);
    }

    public Vector log;

    public URL getResource(String name) {
        log.add("getResource(" + name + ")");
        return getParent().getResource(name);
    }

    public void printLog() {
        for (int i=0; i < log.size(); ++i) {
            System.out.println(log.get(i));
        }
    };
}

public class Class2245 {
    public static void exit(int retCode, String msg) {
        System.out.println(msg);
        System.exit(retCode);
    }

    public static void main(String[] args) {
        ResourceGetter cl = new ResourceGetter(Class2245.class.getClassLoader());
        Class c = null;
        try {
            c = Class.forName(ResourceGetter.specialClass, false, cl);
        } catch (ClassNotFoundException e) {
            exit(1, "cannot load class " + ResourceGetter.specialClass);
        }
        
        String[][] cases = {
            {"/", "/"}, // unchanged
            {"", "p1.p2"},^G^G^G^G
            {"/repository\\dir/resource.dat", "/repository\\dir/resource.dat"}, // unchanged
            {"x.y.z", "p1.p2x.y.z"},
            {"x/y/z", "p1.p2x/y/z"},
        };
    
        boolean result = true;

        for (int i = 0; i < cases.length; ++i) {
            cl.log.clear();
            c.getResource(cases[i][0]);
            if (!cl.log.contains("getResource(" + cases[i][1] + ")")) {
                cl.printLog();
                result = false;
            }
        }
    
        if (!result) {
            exit(1, "unexpected changes detected");
        }
    
        exit(0, "OKAY");
    }
}
--------------------------------------

======================================================================

                                    

Comments
EVALUATION

These resource name changes have been performed since before jdk1.1.  They
are implemented in the private method Class.resolveName which was added
in update 1.45.  The javadoc for Class.getResourceAsStream (which was later
propagated to Class.getResource in bug 4062578) was updated to contain the
disputed specification in the same update.

-- iag@sfbay 2002-07-09

We should document the long-standing behaviour of both of these methods.

-- iag@sfbay 2003-11-24
                                     
2002-07-09
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
tiger-beta

FIXED IN:
tiger-beta

INTEGRATED IN:
tiger-b32
tiger-beta

VERIFIED IN:
tiger-beta2


                                     
2004-08-24



Hardware and Software, Engineered to Work Together