cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Paul Lamb <p...@oil-law.com>
Subject RE: Utils.getBasename hack
Date Tue, 28 Mar 2000 16:26:22 GMT
Here's the complete hack I came up with for getBasename. And this is really
a hack. It really begs to be changed to use getResource, but that requires
changes in several other places. If I can free up some time this week I'll
see if I can tackle that.

Since context.getRealPath is a 2.1 function couldn't the entire thing be
condensed down to using it?

    public static String getBasename(HttpServletRequest request, Object
context) {
        try {
			// force a NoSuchMethod exception in pre 2.2 engines
			request.getContextPath();	
			// we need to check this in case we've been included
in a servlet or jsp
			String path = (String)
request.getAttribute("javax.servlet.include.servlet_path");
			if( path == null ) {
				path = request.getServletPath();
			}
			String resource = ((ServletContext)
context).getRealPath(path);

			if( resource == null ) {
				throw new RuntimeException("Cannot access
non-file/war resources");
			} else {
				return resource.replace('\\', '/');
			}
        } catch (NoSuchMethodError e) {
            // if there is no such method we must be in Servlet API 2.1
            if (request.getPathInfo() != null) {
                // this must be Apache JServ
                return request.getPathTranslated().replace('\\','/');
            } else {
                // otherwise use the deprecated method on all other servlet
engines.
                return
request.getRealPath(request.getRequestURI()).replace('\\', '/');
            }
        } catch (NullPointerException e) {
            // if there is no context set, we must be called from the
command line
            return request.getPathTranslated().replace('\\','/');
        }
    }

> This is getting way out my comfort zone, but in trying out 
> this mornings
> 1.71-dev with a couple of different servlet engines I came 
> across a problem
> with the servlet 2.2 specific code in
> org.apache.cocoon.Utils.getBasename(..) The code wants to get 
> a filename
> string that it can do a File(filename) on.
> 
> The problem is with:
> 
>             // detect if the engine supports at least Servlet API 2.2
>             request.getContextPath();
>             URL resource = ((ServletContext)
> context).getResource(request.getServletPath());
>             if (resource.getProtocol().equals("file")) {
>                 return resource.getFile();
>             } else {
>                 throw new RuntimeException("Cannot handle remote
> resources.");
>             }
> 
> The problem is that the spec doesn't guarantee that a 
> protocol of "file"
> should be returned, even if it is a file resource. Second, if 
> the request
> originates from a forward, then getServletPath returns that 
> path of the
> caller. Third, if the resource is inside a war file, it will fail.
> 
> While it seems that we should be doing a getContent and using the
> InputStream, this would require changes in many places. The 
> best I've come
> up with is something like:
> 
>    // we need to check this in case we've been included in a 
> servlet or jsp
>    String path = 
> request.getAttribute("javax.servlet.include.servlet_path");
>    if( path == null ) {
>     path = request.getServletPath();
>    }
>    String resource = ((ServletContext) context).getRealPath(path);
>    if( resource == null ) {
>     throw new RuntimeException("Cannot access non-file resources/war
> resources");
>    } else {
>     return resource;
>    }
> 
> This doesn't solve the problem of the file being inside a war 
> file, but it
> does overcome the other problems. Maybe some of the jakarta 
> folks on the
> list can shed some light on this.
> 
> Paul Lamb
> 

Mime
View raw message