Sometime in the recent past someone noticed that the mapping of a jsp 
file's name to a class name is not one-to-one -- the filename needs 
mangling to conform to java identifiers and to make sure that classes 
aren't named after keywords.

Whoever did this missed the fact that the same mangling needs to happen 
to the intermediate directories that are used to create the package 
name.  I've attached a patch that liberally grabs the mangling code from 
org.apache.jasper.compiler.CommandLineCompiler and drops it into 
org.apache.jasper.CommandLineContext to do that work.

As a heads-up, there's another problem that may need addressing in the 
class name mangling -- if a file is named, for instance, "com.jsp" or 
"org.jsp", the classname shadows any imports from the "com" or "org" 
packages respectively (this is a general problem, these are just 
examples).  I'm not really sure how to get around this -- the simple way 
would be to prepend each class name with some likely-never-to-be-used 
character sequence; the intelligent way would require actually parsing 
the generated .java to make sure that no top-level package name is being 
shadowed.

This requires a little more intelligence than what I was willing to put 
in for this patch. :)

- a.
--- org/apache/jasper/CommandLineContext.java.old       Thu Mar 21 17:01:27 2002
+++ org/apache/jasper/CommandLineContext.java   Thu Mar 21 17:07:48 2002
@@ -77,6 +77,8 @@
 import java.net.URLClassLoader;
 import java.net.MalformedURLException;
 
+import java.util.StringTokenizer;
+
 /**
  * Holds data used on a per-page compilation context that would otherwise spill
  * over to other pages being compiled.  Things like the taglib classloaders
@@ -236,12 +238,72 @@
         } else {
             packageName += pathName.replace('/', '.');
         }
+
+       // mangle package if necessary
+       StringTokenizer st = new StringTokenizer(packageName, ".");
+       StringBuffer mangledPackageName = new StringBuffer();
+       while (st.hasMoreTokens()) {
+           if (mangledPackageName.length() > 0)
+               mangledPackageName.append(".");
+           String tok = st.nextToken();
+
+           for (int i = 0; i < keywords.length; i++) {
+               if (tok.equals(keywords[i])) {
+                   tok += "%";
+               };
+           };
+
+           if (Character.isJavaIdentifierStart(tok.charAt(0))) 
+               mangledPackageName.append(tok.charAt(0));
+           else
+               mangledPackageName.append(mangleChar(tok.charAt(0)));
+           for (int i = 1; i < tok.length(); i++) {
+               if (Character.isJavaIdentifierPart(tok.charAt(i)))
+                   mangledPackageName.append(tok.charAt(i));
+               else
+                   mangledPackageName.append(mangleChar(tok.charAt(i)));
+           }
+       }
+       packageName = mangledPackageName.toString();
+
         //strip off any leading '.' in the package name
         if (!packageName.equals("") && packageName.charAt(0) == '.') {
             packageName = packageName.substring(1);
         }
         return packageName;
     }
+       
+    public static String [] keywords = {
+        "abstract", "boolean", "break", "byte",
+        "case", "catch", "char", "class",
+        "const", "continue", "default", "do",
+        "double", "else", "extends", "final",
+        "finally", "float", "for", "goto",
+        "if", "implements", "import",
+        "instanceof", "int", "interface",
+        "long", "native", "new", "package",
+        "private", "protected", "public",
+        "return", "short", "static", "super",
+        "switch", "synchronized", "this",
+        "throw", "throws", "transient",
+        "try", "void", "volatile", "while"
+    };
+
+    private static final String mangleChar(char ch) {
+       
+        if(ch == File.separatorChar) {
+           ch = '/';
+       }
+       String s = Integer.toHexString(ch);
+       int nzeros = 5 - s.length();
+       char[] result = new char[6];
+       result[0] = '_';
+       for (int i = 1; i <= nzeros; i++)
+           result[i] = '0';
+       for (int i = nzeros+1, j = 0; i < 6; i++, j++)
+           result[i] = s.charAt(j);
+       return new String(result);
+    }
 
     /**
      * Full path name of the Java file into which the servlet is being

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to