Author: markt Date: Sun Oct 28 21:51:02 2012 New Revision: 1403099 URL: http://svn.apache.org/viewvc?rev=1403099&view=rev Log: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=53867 Improve performance of XML escaping Based on a patch by Sheldon Shao
Added: tomcat/trunk/test/org/apache/jasper/runtime/TesterPageContextImpl.java (with props) Modified: tomcat/trunk/java/org/apache/jasper/runtime/PageContextImpl.java Modified: tomcat/trunk/java/org/apache/jasper/runtime/PageContextImpl.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/runtime/PageContextImpl.java?rev=1403099&r1=1403098&r2=1403099&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/runtime/PageContextImpl.java (original) +++ tomcat/trunk/java/org/apache/jasper/runtime/PageContextImpl.java Sun Oct 28 21:51:02 2012 @@ -902,27 +902,67 @@ public class PageContextImpl extends Pag } } - private static String XmlEscape(String s) { - if (s == null) + protected static String XmlEscape(String s) { + if (s == null) { return null; - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < s.length(); i++) { + } + int len = s.length(); + + /* + * Look for any "bad" characters, Escape "bad" character was found + */ + // ASCII " 34 & 38 ' 39 < 60 > 62 + for (int i = 0; i < len; i++) { char c = s.charAt(i); - if (c == '<') { - sb.append("<"); - } else if (c == '>') { - sb.append(">"); - } else if (c == '\'') { - sb.append("'"); // ' - } else if (c == '&') { - sb.append("&"); - } else if (c == '"') { - sb.append("""); // " - } else { - sb.append(c); + if (c >= '\"' && c <= '>' && + (c == '<' || c == '>' || c == '\'' || c == '&' || c == '"')) { + // need to escape them and then quote the whole string + StringBuilder sb = new StringBuilder((int) (len * 1.2)); + sb.append(s, 0, i); + int pos = i + 1; + for (int j = i; j < len; j++) { + c = s.charAt(j); + if (c >= '\"' && c <= '>') { + if (c == '<') { + if (j > pos) { + sb.append(s, pos, j); + } + sb.append("<"); + pos = j + 1; + } else if (c == '>') { + if (j > pos) { + sb.append(s, pos, j); + } + sb.append(">"); + pos = j + 1; + } else if (c == '\'') { + if (j > pos) { + sb.append(s, pos, j); + } + sb.append("'"); // ' + pos = j + 1; + } else if (c == '&') { + if (j > pos) { + sb.append(s, pos, j); + } + sb.append("&"); + pos = j + 1; + } else if (c == '"') { + if (j > pos) { + sb.append(s, pos, j); + } + sb.append("""); // " + pos = j + 1; + } + } + } + if (pos < len) { + sb.append(s, pos, len); + } + return sb.toString(); } } - return sb.toString(); + return s; } /** Added: tomcat/trunk/test/org/apache/jasper/runtime/TesterPageContextImpl.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/jasper/runtime/TesterPageContextImpl.java?rev=1403099&view=auto ============================================================================== --- tomcat/trunk/test/org/apache/jasper/runtime/TesterPageContextImpl.java (added) +++ tomcat/trunk/test/org/apache/jasper/runtime/TesterPageContextImpl.java Sun Oct 28 21:51:02 2012 @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jasper.runtime; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Performance tests for {@link PageContextImpl}. + */ +public class TesterPageContextImpl { + + private static String[] bug53867TestData = new String[] { + "Hello World!", + "<meta http-equiv=\"Content-Language\">", + "This connection has limited network connectivity.", + "Please use this web page & to access file server resources." }; + + @Test + public void testBug53867() { + for (int i = 0; i < 10; i++) { + doTestBug53867(); + } + } + + private static void doTestBug53867() { + int count = 100000; + + for (int j = 0; j < bug53867TestData.length; j++) { + Assert.assertEquals(doTestBug53867OldVersion(bug53867TestData[j]), + PageContextImpl.XmlEscape(bug53867TestData[j])); + } + + for (int i = 0; i < 100; i++) { + for (int j = 0; j < bug53867TestData.length; j++) { + doTestBug53867OldVersion(bug53867TestData[j]); + } + } + for (int i = 0; i < 100; i++) { + for (int j = 0; j < bug53867TestData.length; j++) { + PageContextImpl.XmlEscape(bug53867TestData[j]); + } + } + + long start = System.currentTimeMillis(); + for (int i = 0; i < count; i++) { + for (int j = 0; j < bug53867TestData.length; j++) { + doTestBug53867OldVersion(bug53867TestData[j]); + } + } + System.out.println( + "Old escape:" + (System.currentTimeMillis() - start)); + + start = System.currentTimeMillis(); + for (int i = 0; i < count; i++) { + for (int j = 0; j < bug53867TestData.length; j++) { + PageContextImpl.XmlEscape(bug53867TestData[j]); + } + } + System.out.println( + "New escape:" + (System.currentTimeMillis() - start)); + } + + private static String doTestBug53867OldVersion(String s) { + if (s == null) + return null; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c == '<') { + sb.append("<"); + } else if (c == '>') { + sb.append(">"); + } else if (c == '\'') { + sb.append("'"); // ' + } else if (c == '&') { + sb.append("&"); + } else if (c == '"') { + sb.append("""); // " + } else { + sb.append(c); + } + } + return sb.toString(); + } +} Propchange: tomcat/trunk/test/org/apache/jasper/runtime/TesterPageContextImpl.java ------------------------------------------------------------------------------ svn:eol-style = native --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org