org.apache.catalina.core.ApplicationContext.getContext(String uri) method was written to return the current context whenever the uri passed into it was a "sub-dir" of the current context's uri. for example, calling getContext("/store/common") from within a context that had as it's uri: "/store", would always return the context of "/store", even if "/store/common" was a valid context
*** Bug 11865 has been marked as a duplicate of this bug. ***
*** Bug 11652 has been marked as a duplicate of this bug. ***
Created attachment 3247 [details] proposed fix (diff)
The problem is much more trivial. We will always have a contextPath with a length > 0 since we always append "/" if there isn't one already. $ diff -u ApplicationContext.java-2002-10-21 ApplicationContext.java --- ApplicationContext.java-2002-10-21 Mon Sep 23 11:23:16 2002 +++ ApplicationContext.java Tue Oct 22 17:55:08 2002 @@ -442,7 +442,7 @@ String contextPath = context.getPath(); if (!contextPath.endsWith("/")) contextPath = contextPath + "/"; - if ((contextPath.length() > 0) && (uri.startsWith(contextPath))) { + if ((contextPath.length() > 1) && (uri.startsWith(contextPath))) { return (this); } Martin Algesten
In the general case, "/store/common" is supposed to return context "/store" if it exists. The current algorithm has a big problem with the root context, as pointed out by Martin. However, it actually has the same problem for all contexts, so I think there's a spec problem here.
The bit of code we're talking about is there in order to always allow for getting the current context, even if crossContext="false" (god knows why anyone would like to get the current context like that, but allowing it surely doesn't hurt). I don't understand why we are adding on a trailing "/" in case the contextPath doesn't have one. That seems wrong to me since it would require the caller to say "/store/" in order to trigger the optimisation. The incoming uri we need to handle could be on the forms (have I missed anyone?): "/" "/store" "/store/" "/store/common" "/store/common/even/more" The context paths can be on the forms (again, correct me if I'm wrong): "" "/store" It seems we would need to treat the ROOT context differently to the rest of them. A propose for the fix would then be: ---------------------------------------------------------------------- --- ApplicationContext.java-2002-10-21 Mon Sep 23 11:23:16 2002 +++ ApplicationContext.java Wed Oct 23 10:54:51 2002 @@ -439,13 +439,16 @@ return (null); // Return the current context if requested - String contextPath = context.getPath(); - if (!contextPath.endsWith("/")) - contextPath = contextPath + "/"; - if ((contextPath.length() > 0) && (uri.startsWith(contextPath))) { - return (this); - } - + if ( context.getPath().equals( "" ) ) { + if ( uri.equals( "/" ) ) { + return (this); + } + } else { + if ( uri.startsWith( context.getPath() ) ) { + return (this); + } + } + // Return other contexts only if allowed if (!context.getCrossContext()) return (null); ---------------------------------------------------------------------- I've tested this with the following JSP code: <% ServletContext ctx = getServletContext(); System.out.println( "/: "+ctx.getContext( "/" ) ); System.out.println( "/publisher: "+ctx.getContext( "/publisher" ) ); System.out.println( "/publisher/: "+ctx.getContext( "/publisher/" ) ); System.out.println( "/publisher/protected: "+ctx.getContext ( "/publisher/protected" ) ); System.out.println( "/publisher/protected/: "+ctx.getContext ( "/publisher/protected/" ) ); %> With crossContext="false". Running the JSP in the ROOT context gives me: /: org.apache.catalina.core.ApplicationContextFacade@a45a24 /publisher: null /publisher/: null /publisher/protected: null /publisher/protected/: null Running the JSP in the /publisher context gives me: /: null /publisher: org.apache.catalina.core.ApplicationContextFacade@15c6c8d /publisher/: org.apache.catalina.core.ApplicationContextFacade@15c6c8d /publisher/protected: org.apache.catalina.core.ApplicationContextFacade@15c6c8d /publisher/protected/: org.apache.catalina.core.ApplicationContextFacade@15c6c8d Martin Algesten
The "/" is added to avoid matching stuff like: Context name: "/foo" Uri: "/foobar" I still think the spec is bad, and should modify to specify that the desired context path should be matched exactly. BTW, there's a Watchdog test about this (unfortunately). I wonder why, since the API Javadocs are quite unclear.
Agreed, we need to add "/" to the end, but that goes for the incoming URI as well. We also need to treat the ROOT context differently. I agree the specs are bad, but we need to solve this with what we got, since the getContext() method as it currently stands isn't useful. ----------------------------------------------------------- --- ApplicationContext.java-2002-10-21 Mon Sep 23 11:23:16 2002 +++ ApplicationContext.java Wed Oct 23 14:08:41 2002 @@ -439,12 +439,25 @@ return (null); // Return the current context if requested - String contextPath = context.getPath(); - if (!contextPath.endsWith("/")) - contextPath = contextPath + "/"; - if ((contextPath.length() > 0) && (uri.startsWith(contextPath))) { - return (this); - } + String contextPath = context.getPath(); + if ( contextPath.equals( "" ) ) { + if ( uri.equals( "/" ) ) { + return (this); + } + } else { + String compareUri = uri; + if ( !uri.endsWith( "/" ) ) { + compareUri = compareUri+"/"; + } + if ( !contextPath.endsWith( "/" ) ) { + contextPath = contextPath+"/"; + } + if ( compareUri.startsWith( contextPath ) ) { + return (this); + } + } + + System.out.println( context.getCrossContext() ); // Return other contexts only if allowed if (!context.getCrossContext()) ----------------------------------------------------------- Martin Algesten
ok, from the servlet 2.3 spec: ----------------------------------------- getContext(String) public ServletContext getContext(java.lang.String uripath) Returns a ServletContext object that corresponds to a specified URL on the server. This method allows servlets to gain access to the context for various parts of the server, and as needed obtain RequestDispatcher objects from the context. The given path must be begin with “/”, is interpreted relative to the server’s document root and is matched against the context roots of other web applications hosted on this container. In a security conscious environment, the servlet container may return null for a given URL. Parameters: uripath - a String specifying the context path of another web application in the container. Returns: the ServletContext object that corresponds to the named URL, or null if either none exists or the container wishes to restrict this access. ----------------------------------------- There doesn't appear to be anything in here at all suggesting that when you call getContext(String) with a parameter specifying a uri which is a sub-dir of the current context's uri, it should ignore your request and simply return the current context. I also beleive that the following assumption is incorrect: "In the general case, '/store/common' is supposed to return context '/store' if it exists.". The spec states that the given path is "matched" against the context roots of other web apps. That implies to me that it must match exactly. The solutions provided here do not address this bug: "can't retrieve external context who's uri is a sub-dir of current context". Each of them actually still has the same problem (except for the initial postings attachment). Here's a solution, with minimal changes, that fixes this bug: ----------------------------------------- 445c445 < if ((contextPath.length() > 0) && (uri.startsWith(contextPath))) { --- > if ((contextPath.length() > 1) && (uri.equals(contextPath))) { ----------------------------------------- Ryan Smith
That doesn't fix it properly. To trigger the optimisation you would need to send in the uri "/store/" to get a match. Agreed that if we can ditch handling the "/store/common" uri, we could make this work much easier. --- ApplicationContext.java-2002-10-21 Mon Sep 23 11:23:16 2002 +++ ApplicationContext.java Thu Oct 24 10:30:56 2002 @@ -439,12 +439,13 @@ return (null); // Return the current context if requested - String contextPath = context.getPath(); - if (!contextPath.endsWith("/")) - contextPath = contextPath + "/"; - if ((contextPath.length() > 0) && (uri.startsWith(contextPath))) { - return (this); - } + String contextPath = context.getPath(); + if ( contextPath.equals( "" ) && uri.equals( "/" ) || + !contextPath.equals( "" ) && uri.equals( contextPath ) ) { + return (this); + } + + System.out.println( context.getCrossContext() ); // Return other contexts only if allowed if (!context.getCrossContext()) Martin Algesten
That System.out should of course not be there. --- ApplicationContext.java-2002-10-21 Mon Sep 23 11:23:16 2002 +++ ApplicationContext.java Wed Oct 30 16:40:08 2002 @@ -439,12 +439,11 @@ return (null); // Return the current context if requested - String contextPath = context.getPath(); - if (!contextPath.endsWith("/")) - contextPath = contextPath + "/"; - if ((contextPath.length() > 0) && (uri.startsWith(contextPath))) { - return (this); - } + String contextPath = context.getPath(); + if ( contextPath.equals( "" ) && uri.equals( "/" ) || + !contextPath.equals( "" ) && uri.equals( contextPath ) ) { + return (this); + } // Return other contexts only if allowed if (!context.getCrossContext())
*** Bug 14114 has been marked as a duplicate of this bug. ***
This is a serious bug that needs to be fixed. I agree that the last patch submited by Martin Algesten lookes nice. Please add it yo the CVS tree. Thanks! Christer Grimsæth
*** Bug 10544 has been marked as a duplicate of this bug. ***
*** Bug 16258 has been marked as a duplicate of this bug. ***
Is there a chance that this bug gets fixed within 2003? For us it's really a show stopper. Thanks a lot, Christian
Is this bug solved?
Not completely no. The most recent debate on this is here: http://marc.theaimsgroup.com/?l=tomcat-dev&m=108109687130165&w=2
Can you give us a short status about this bug ? the last entry is April '04 ?
No change. What is needed to move this forward is input from the servlet spec team on the proposal in http://marc.theaimsgroup.com/?l=tomcat-dev&m=108109687130165&w=2 This is still on my todo list - just not going anywhere at the moment. If you want to try and get some spec team input that would be great.
After some discussion on what the spec actually means on the dev list, we have agreed a way forward for this bug and I have just commited a change that fixes this issue for TC4. A similar change will be ported to TC5. The dev discussion can be found on this thread http://marc.theaimsgroup.com/?l=tomcat-dev&m=113286089307014&w=2