Author: markt Date: Fri Aug 12 08:13:09 2011 New Revision: 1157000 URL: http://svn.apache.org/viewvc?rev=1157000&view=rev Log: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=36362 Handle tag files with attribute names that are not valid Java identifiers
Modified: tomcat/tc5.5.x/trunk/STATUS.txt tomcat/tc5.5.x/trunk/container/modules/cluster/src/share/org/apache/catalina/cluster/session/ReplicationStream.java tomcat/tc5.5.x/trunk/container/modules/groupcom/src/share/org/apache/catalina/tribes/io/ReplicationStream.java tomcat/tc5.5.x/trunk/container/webapps/docs/changelog.xml tomcat/tc5.5.x/trunk/jasper/src/share/org/apache/jasper/compiler/Generator.java tomcat/tc5.5.x/trunk/jasper/src/share/org/apache/jasper/compiler/JspUtil.java Modified: tomcat/tc5.5.x/trunk/STATUS.txt URL: http://svn.apache.org/viewvc/tomcat/tc5.5.x/trunk/STATUS.txt?rev=1157000&r1=1156999&r2=1157000&view=diff ============================================================================== --- tomcat/tc5.5.x/trunk/STATUS.txt (original) +++ tomcat/tc5.5.x/trunk/STATUS.txt Fri Aug 12 08:13:09 2011 @@ -77,15 +77,6 @@ PATCHES PROPOSED TO BACKPORT: +1: markt -1: -* Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=36362 - Handle tag files with attribute names that are not valid Java identifiers - http://svn.apache.org/viewvc?rev=1138950&view=rev - http://svn.apache.org/viewvc?rev=1138953&view=rev - http://svn.apache.org/viewvc?rev=1140693&view=rev - http://svn.apache.org/viewvc?rev=1142043&view=rev - +1: markt, kkolinko, kfujino - -1: - * Multiple improvements to the Windows Installer - https://issues.apache.org/bugzilla/show_bug.cgi?id=33262 Install monitor to auto-start for current user only rather than all users to Modified: tomcat/tc5.5.x/trunk/container/modules/cluster/src/share/org/apache/catalina/cluster/session/ReplicationStream.java URL: http://svn.apache.org/viewvc/tomcat/tc5.5.x/trunk/container/modules/cluster/src/share/org/apache/catalina/cluster/session/ReplicationStream.java?rev=1157000&r1=1156999&r2=1157000&view=diff ============================================================================== --- tomcat/tc5.5.x/trunk/container/modules/cluster/src/share/org/apache/catalina/cluster/session/ReplicationStream.java (original) +++ tomcat/tc5.5.x/trunk/container/modules/cluster/src/share/org/apache/catalina/cluster/session/ReplicationStream.java Fri Aug 12 08:13:09 2011 @@ -22,6 +22,8 @@ import java.io.InputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectStreamClass; +import java.lang.reflect.Modifier; +import java.lang.reflect.Proxy; /** * Custom subclass of <code>ObjectInputStream</code> that loads from the @@ -86,6 +88,43 @@ public final class ReplicationStream ext } } + /** + * ObjectInputStream.resolveProxyClass has some funky way of using + * the incorrect class loader to resolve proxy classes, let's do it our way instead + */ + protected Class resolveProxyClass(String[] interfaces) + throws IOException, ClassNotFoundException { + + ClassLoader latestLoader = classLoader; + ClassLoader nonPublicLoader = null; + boolean hasNonPublicInterface = false; + + // define proxy in class loader of non-public interface(s), if any + Class[] classObjs = new Class[interfaces.length]; + for (int i = 0; i < interfaces.length; i++) { + Class cl = this.findWebappClass(interfaces[i]); + if (latestLoader == null) latestLoader = cl.getClassLoader(); + if ((cl.getModifiers() & Modifier.PUBLIC) == 0) { + if (hasNonPublicInterface) { + if (nonPublicLoader != cl.getClassLoader()) { + throw new IllegalAccessError( + "conflicting non-public interface class loaders"); + } + } else { + nonPublicLoader = cl.getClassLoader(); + hasNonPublicInterface = true; + } + } + classObjs[i] = cl; + } + try { + return Proxy.getProxyClass(hasNonPublicInterface ? nonPublicLoader + : latestLoader, classObjs); + } catch (IllegalArgumentException e) { + throw new ClassNotFoundException(null, e); + } + } + public Class findReplicationClass(String name) throws ClassNotFoundException, IOException { return Class.forName(name, false, getClass().getClassLoader()); Modified: tomcat/tc5.5.x/trunk/container/modules/groupcom/src/share/org/apache/catalina/tribes/io/ReplicationStream.java URL: http://svn.apache.org/viewvc/tomcat/tc5.5.x/trunk/container/modules/groupcom/src/share/org/apache/catalina/tribes/io/ReplicationStream.java?rev=1157000&r1=1156999&r2=1157000&view=diff ============================================================================== --- tomcat/tc5.5.x/trunk/container/modules/groupcom/src/share/org/apache/catalina/tribes/io/ReplicationStream.java (original) +++ tomcat/tc5.5.x/trunk/container/modules/groupcom/src/share/org/apache/catalina/tribes/io/ReplicationStream.java Fri Aug 12 08:13:09 2011 @@ -22,6 +22,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectStreamClass; +import java.lang.reflect.Modifier; +import java.lang.reflect.Proxy; /** * Custom subclass of <code>ObjectInputStream</code> that loads from the @@ -71,23 +73,68 @@ public final class ReplicationStream ext public Class resolveClass(ObjectStreamClass classDesc) throws ClassNotFoundException, IOException { String name = classDesc.getName(); - boolean tryRepFirst = name.startsWith("org.apache.catalina.tribes"); try { - try - { - if ( tryRepFirst ) return findReplicationClass(name); - else return findExternalClass(name); - } - catch ( Exception x ) - { - if ( tryRepFirst ) return findExternalClass(name); - else return findReplicationClass(name); - } + return resolveClass(name); } catch (ClassNotFoundException e) { return super.resolveClass(classDesc); } } + public Class resolveClass(String name) + throws ClassNotFoundException, IOException { + + boolean tryRepFirst = name.startsWith("org.apache.catalina.tribes"); + try { + if (tryRepFirst) + return findReplicationClass(name); + else + return findExternalClass(name); + } catch (Exception x) { + if (tryRepFirst) + return findExternalClass(name); + else + return findReplicationClass(name); + } + } + + /** + * ObjectInputStream.resolveProxyClass has some funky way of using + * the incorrect class loader to resolve proxy classes, let's do it our way instead + */ + protected Class resolveProxyClass(String[] interfaces) + throws IOException, ClassNotFoundException { + + ClassLoader latestLoader = (classLoaders!=null && classLoaders.length==0)?null:classLoaders[0]; + ClassLoader nonPublicLoader = null; + boolean hasNonPublicInterface = false; + + // define proxy in class loader of non-public interface(s), if any + Class[] classObjs = new Class[interfaces.length]; + for (int i = 0; i < interfaces.length; i++) { + Class cl = this.resolveClass(interfaces[i]); + if (latestLoader==null) latestLoader = cl.getClassLoader(); + if ((cl.getModifiers() & Modifier.PUBLIC) == 0) { + if (hasNonPublicInterface) { + if (nonPublicLoader != cl.getClassLoader()) { + throw new IllegalAccessError( + "conflicting non-public interface class loaders"); + } + } else { + nonPublicLoader = cl.getClassLoader(); + hasNonPublicInterface = true; + } + } + classObjs[i] = cl; + } + try { + return Proxy.getProxyClass(hasNonPublicInterface ? nonPublicLoader + : latestLoader, classObjs); + } catch (IllegalArgumentException e) { + throw new ClassNotFoundException(null, e); + } + } + + public Class findReplicationClass(String name) throws ClassNotFoundException, IOException { Class clazz = Class.forName(name, false, getClass().getClassLoader()); Modified: tomcat/tc5.5.x/trunk/container/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/tc5.5.x/trunk/container/webapps/docs/changelog.xml?rev=1157000&r1=1156999&r2=1157000&view=diff ============================================================================== --- tomcat/tc5.5.x/trunk/container/webapps/docs/changelog.xml (original) +++ tomcat/tc5.5.x/trunk/container/webapps/docs/changelog.xml Fri Aug 12 08:13:09 2011 @@ -66,6 +66,15 @@ </fix> </changelog> </subsection> + <subsection name="Jasper"> + <changelog> + <fix> + <bug>36362</bug>: Handle the case where tag file attributes (which can + use any valid XML name) have a name which is not a Java identifier. + (markt) + </fix> + </changelog> + </subsection> <subsection name="Webapps"> <changelog> <fix> Modified: tomcat/tc5.5.x/trunk/jasper/src/share/org/apache/jasper/compiler/Generator.java URL: http://svn.apache.org/viewvc/tomcat/tc5.5.x/trunk/jasper/src/share/org/apache/jasper/compiler/Generator.java?rev=1157000&r1=1156999&r2=1157000&view=diff ============================================================================== --- tomcat/tc5.5.x/trunk/jasper/src/share/org/apache/jasper/compiler/Generator.java (original) +++ tomcat/tc5.5.x/trunk/jasper/src/share/org/apache/jasper/compiler/Generator.java Fri Aug 12 08:13:09 2011 @@ -3558,54 +3558,56 @@ class Generator { out.print(JspUtil.toJavaSourceType(attrInfos[i].getTypeName())); out.print(" "); } - out.print(attrInfos[i].getName()); + out.print(JspUtil.makeJavaIdentifierForAttribute( + attrInfos[i].getName())); out.println(";"); } out.println(); // Define attribute getter and setter methods - if (attrInfos != null) { - for (int i = 0; i < attrInfos.length; i++) { - // getter method - out.printin("public "); - if (attrInfos[i].isFragment()) { - out.print("javax.servlet.jsp.tagext.JspFragment "); - } else { - out.print(JspUtil.toJavaSourceType(attrInfos[i].getTypeName())); - out.print(" "); - } - out.print(toGetterMethod(attrInfos[i].getName())); - out.println(" {"); - out.pushIndent(); - out.printin("return this."); - out.print(attrInfos[i].getName()); - out.println(";"); - out.popIndent(); - out.printil("}"); - out.println(); + for (int i = 0; i < attrInfos.length; i++) { + String javaName = + JspUtil.makeJavaIdentifierForAttribute(attrInfos[i].getName()); - // setter method - out.printin("public void "); - out.print(toSetterMethodName(attrInfos[i].getName())); - if (attrInfos[i].isFragment()) { - out.print("(javax.servlet.jsp.tagext.JspFragment "); - } else { - out.print("("); - out.print(JspUtil.toJavaSourceType(attrInfos[i].getTypeName())); - out.print(" "); - } - out.print(attrInfos[i].getName()); - out.println(") {"); - out.pushIndent(); - out.printin("this."); - out.print(attrInfos[i].getName()); - out.print(" = "); - out.print(attrInfos[i].getName()); - out.println(";"); - out.popIndent(); - out.printil("}"); - out.println(); + // getter method + out.printin("public "); + if (attrInfos[i].isFragment()) { + out.print("javax.servlet.jsp.tagext.JspFragment "); + } else { + out.print(JspUtil.toJavaSourceType(attrInfos[i].getTypeName())); + out.print(" "); } + out.print(toGetterMethod(attrInfos[i].getName())); + out.println(" {"); + out.pushIndent(); + out.printin("return this."); + out.print(javaName); + out.println(";"); + out.popIndent(); + out.printil("}"); + out.println(); + + // setter method + out.printin("public void "); + out.print(toSetterMethodName(attrInfos[i].getName())); + if (attrInfos[i].isFragment()) { + out.print("(javax.servlet.jsp.tagext.JspFragment "); + } else { + out.print("("); + out.print(JspUtil.toJavaSourceType(attrInfos[i].getTypeName())); + out.print(" "); + } + out.print(javaName); + out.println(") {"); + out.pushIndent(); + out.printin("this."); + out.print(javaName); + out.print(" = "); + out.print(javaName); + out.println(";"); + out.popIndent(); + out.printil("}"); + out.println(); } } Modified: tomcat/tc5.5.x/trunk/jasper/src/share/org/apache/jasper/compiler/JspUtil.java URL: http://svn.apache.org/viewvc/tomcat/tc5.5.x/trunk/jasper/src/share/org/apache/jasper/compiler/JspUtil.java?rev=1157000&r1=1156999&r2=1157000&view=diff ============================================================================== --- tomcat/tc5.5.x/trunk/jasper/src/share/org/apache/jasper/compiler/JspUtil.java (original) +++ tomcat/tc5.5.x/trunk/jasper/src/share/org/apache/jasper/compiler/JspUtil.java Fri Aug 12 08:13:09 2011 @@ -979,6 +979,32 @@ public class JspUtil { * @return Legal Java identifier corresponding to the given identifier */ public static final String makeJavaIdentifier(String identifier) { + return makeJavaIdentifier(identifier, true); + } + + /** + * Converts the given identifier to a legal Java identifier + * to be used for JSP Tag file attribute names. + * + * @param identifier + * Identifier to convert + * + * @return Legal Java identifier corresponding to the given identifier + */ + public static final String makeJavaIdentifierForAttribute(String identifier) { + return makeJavaIdentifier(identifier, false); + } + + /** + * Converts the given identifier to a legal Java identifier. + * + * @param identifier + * Identifier to convert + * + * @return Legal Java identifier corresponding to the given identifier + */ + private static final String makeJavaIdentifier(String identifier, + boolean periodToUnderscore) { StringBuffer modifiedIdentifier = new StringBuffer(identifier.length()); if (!Character.isJavaIdentifierStart(identifier.charAt(0))) { @@ -986,9 +1012,10 @@ public class JspUtil { } for (int i = 0; i < identifier.length(); i++) { char ch = identifier.charAt(i); - if (Character.isJavaIdentifierPart(ch) && ch != '_') { + if (Character.isJavaIdentifierPart(ch) && + (ch != '_' || !periodToUnderscore)) { modifiedIdentifier.append(ch); - } else if (ch == '.') { + } else if (ch == '.' && periodToUnderscore) { modifiedIdentifier.append('_'); } else { modifiedIdentifier.append(mangleChar(ch)); --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org