On Wed, 4 Jul 2001, Stuart Roebuck wrote:

> I've been hitting against getCanonicalPath myself recently in the context 
> of Cocoon 2 and Tomcat 4 under Mac OS X.
> 
> I've taken a look through some of the code of Tomcat and it appears that 
> there are opportunities to cut down on calls to getCanonicalPath, but I'm 
> conscious that I really am not at all familiar with the code and the 
> possible underlying issues.
> 

One thing to be *very* cautious about here is security.  You have to make
absolutely sure, for example, that resource references are case sensitive
(even on case insensitive platforms), and that malicious users can't use
things like "../../../../../other/place" to access things outside of the
web app.

> Here are some examples of bits of code in the current Tomcat source which 
> appear open to optimization, perhaps you could comment on whether such 
> optimizations would work:
> 
> StandardContext.java:
> 
> >         if (directory.exists() && directory.canRead() &&
> >             directory.isDirectory()) {
> >             String filenames[] = directory.list();
> >             for (int i = 0; i < filenames.length; i++) {
> >                 if (!filenames[i].endsWith(".jar"))
> >                     continue;
> >                 File file = new File(directory, filenames[i]);
> >                 try {
> >                     URL url = new URL("file", null, file.getCanonicalPath(
> > ));
> >                     newLoader.addRepository(url.toString());
> >                 } catch (IOException e) {
> >                     throw new IllegalArgumentException(e.toString());
> >                 }
> >             }
> >         }
> 
> Couldn't we get the Canonical path of the directory and then assume that 
> the absolute path of the filenames returned would be Canonical too, 
> thereby taking getCanonicalPath out of the loop?
> 

Depends on where the list of filenames comes from.  In this case, it might
be feasible (since they come from the operating system and not the web
app), but a thorough security review would be important first.

> >     // Create this directory if necessary
> >     File dir = new File(workDir);
> >     if (!dir.isAbsolute()) {
> >             File catalinaHome = new 
> > File(System.getProperty("catalina.home"));
> >             String catalinaHomePath = null;
> >             try {
> >                 catalinaHomePath = catalinaHome.getCanonicalPath();
> >                 dir = new File(catalinaHomePath, workDir);
> >             } catch (IOException e) {
> >             }
> >         }
> 
> Isn't getAbsolutePath sufficient here?
> 

IIRC, getAbsolutePath caused problems here on Windows but worked
correctly on Solaris and Linux.  Such is life when you've got to be
portable across multiple JVMs.

> Similar issues exist in Bootstrap.java.
> 
> HostConfig:
> 
> >                 // Deploy the application in this directory
> >                 if (debug >= 1)
> >                     log(sm.getString("hostConfig.deployDir", files[i]));
> >                 try {
> >                     URL url = new URL("file", null, dir.getCanonicalPath(
> > ));
> >                     ((Deployer) host).install(contextPath, url);
> >                 } catch (Throwable t) {
> >                     log(sm.getString("hostConfig.deployDir.error", files[
> > i]),
> >                         t);
> >                 }
> 
> dir is derived using the list method on the appBase variable (not shown on 
> listing) which is canonical.  Do we need to use getCanonicalPath here or 
> can we just use getAbsolutePath?
> 
> Finally, how about having some form of cached getCanonicalPath method 
> which returns results from cache for requests for the same file path?  I 
> tried replacing the actual getCanonicalPath method in the main Java 
> classes with a simple unlimited hashTable and the performance improvements 
> running Tomcat and Cocoon were very visible.  Clearly the hash table would 
> need to be time and size limited, but are there any other fundamental 
> issues with this idea?
> 

The cases you've described above all happen only once (at startup
time).  Assuming that we could safely optimize these cases, would it
really make a significant difference?

To influence the performance of Cocoon, we'd want to look at the Resources
implementation.  It's been worked on, but I would certainly not say we've
really optimized it yet.  And reducing the number of calls to
getCanonicalPath() sounds like a good strategy -- as long as it can be
done safely.

> Stuart.
> 

Craig

Reply via email to