Bug 36534 - Context relative URLs returned by ServletContext.getResource() for the same path are not equal
Summary: Context relative URLs returned by ServletContext.getResource() for the same p...
Status: RESOLVED FIXED
Alias: None
Product: Tomcat 5
Classification: Unclassified
Component: Catalina (show other bugs)
Version: Nightly Build
Hardware: Other other
: P2 normal (vote)
Target Milestone: ---
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-09-07 04:52 UTC by Jan Luehe
Modified: 2005-09-08 12:39 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jan Luehe 2005-09-07 04:52:04 UTC
Consider the following servlet snippet:

  URL main = context.getResource("/WEB-INF/wsdl/hello_literal.wsdl");
  URL sub = new URL(main, "hello.xsd");
  URL sub1 = context.getResource("/WEB-INF/wsdl/hello.xsd");

While sub.toString().equals(sub1.toString()) is TRUE, sub.equals(sub1)
returns FALSE, where it should also return TRUE.

I noticed the reason sub.equals.(sub1) is FALSE is because their
getHost() values are different:

  sub.getHost() -> ""
  sub1.getHost() -> null

Notice that in the case of

  URL sub = new URL(main, "hello.xsd");

java.net.URLStreamHandler.parseURL() will set host to "", while in the
case of

  URL sub1 = context.getResource("/WEB-INF/wsdl/hello.xsd");

which is implemented by
org.apache.catalina.core.ApplicationContext.getResource() as follows:

  return new URL
      ("jndi", null, 0, getJNDIUri(hostName, fullPath),
      new DirContextURLStreamHandler(resources));

the host component is set to "null".

Changing

  return new URL
      ("jndi", null, 0, getJNDIUri(hostName, fullPath),
      new DirContextURLStreamHandler(resources));

to 

  return new URL
      ("jndi", "", 0, getJNDIUri(hostName, fullPath),
      new DirContextURLStreamHandler(resources));

in ApplicationContext.getResource() fixes the problem.

Unfortunately, I am having cvs problems, otherwise i would have committed
the fix myself.
Comment 1 Remy Maucherat 2005-09-07 12:05:30 UTC
I will not be fixing that, as this changes the value of toString for the URL.
Comment 2 Jan Luehe 2005-09-07 19:47:39 UTC
Good point about toString(). I have a solution for that as well. Just override
org.apache.naming.resources.DirContextURLStreamHandler.toExternalForm() and have
it ignore the "authority" part of the URL, as follows (this is copied from
java.net.URLStreamHandler.toExternalForm(), with "authority" part ignored):

    /**
     * Converts a <code>URL</code> of a specific protocol to a
     * <code>String</code>.
     *
     * @param   u   the URL.
     * @return  a string representation of the <code>URL</code> argument.
     */
    protected String toExternalForm(URL u) {

	// pre-compute length of StringBuffer
	int len = u.getProtocol().length() + 1;
	if (u.getPath() != null) {
	    len += u.getPath().length();
	}
	if (u.getQuery() != null) {
	    len += 1 + u.getQuery().length();
	}
	if (u.getRef() != null) 
	    len += 1 + u.getRef().length();

	StringBuffer result = new StringBuffer(len);
	result.append(u.getProtocol());
        result.append(":");
        if (u.getPath() != null) {
            result.append(u.getPath());
        }
        if (u.getQuery() != null) {
            result.append('?');
            result.append(u.getQuery());
        }
	if (u.getRef() != null) {
	    result.append("#");
            result.append(u.getRef());
	}
	return result.toString();
    }

It is important that URLs returned by ServletContext.getResource() that are
equal have equals() return TRUE. This works for all other kinds of URLs.