PR: 37169 git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@327675 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -20,6 +20,7 @@ package org.apache.tools.ant.taskdefs; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.DirectoryScanner; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.util.StringUtils; | |||
| import org.apache.tools.ant.types.EnumeratedAttribute; | |||
| import org.apache.tools.ant.types.FileSet; | |||
| @@ -441,7 +442,7 @@ public class SQLExec extends JDBCTask { | |||
| protected void runStatements(Reader reader, PrintStream out) | |||
| throws SQLException, IOException { | |||
| StringBuffer sql = new StringBuffer(); | |||
| String line = ""; | |||
| String line; | |||
| BufferedReader in = new BufferedReader(reader); | |||
| @@ -481,7 +482,7 @@ public class SQLExec extends JDBCTask { | |||
| } | |||
| } | |||
| if ((delimiterType.equals(DelimiterType.NORMAL) | |||
| && sql.toString().endsWith(delimiter)) | |||
| && StringUtils.endsWith(sql, delimiter)) | |||
| || | |||
| (delimiterType.equals(DelimiterType.ROW) | |||
| && line.equals(delimiter))) { | |||
| @@ -574,8 +575,7 @@ public class SQLExec extends JDBCTask { | |||
| * @throws SQLException on SQL problems. | |||
| */ | |||
| protected void printResults(PrintStream out) throws SQLException { | |||
| ResultSet rs = null; | |||
| rs = statement.getResultSet(); | |||
| ResultSet rs = statement.getResultSet(); | |||
| try { | |||
| printResults(rs, out); | |||
| } finally { | |||
| @@ -98,4 +98,35 @@ public final class StringUtils { | |||
| return sw.toString(); | |||
| } | |||
| /** | |||
| * Checks that a string buffer ends up with a given string. It may sound trivial with the existing | |||
| * JDK API but the various implementation among JDKs can make those methods extremely resource intensive | |||
| * and perform poorly due to massive memory allocation and copying. See | |||
| * @param buffer the buffer to perform the check on | |||
| * @param suffix the suffix | |||
| * @return <code>true</code> if the character sequence represented by the | |||
| * argument is a suffix of the character sequence represented by | |||
| * the StringBuffer object; <code>false</code> otherwise. Note that the | |||
| * result will be <code>true</code> if the argument is the | |||
| * empty string. | |||
| */ | |||
| public static boolean endsWith(StringBuffer buffer, String suffix) { | |||
| if (suffix.length() > buffer.length()) { | |||
| return false; | |||
| } | |||
| // this loop is done on purpose to avoid memory allocation performance problems on various JDKs | |||
| // StringBuffer.lastIndexOf() was introduced in jdk 1.4 and implementation is ok though does allocation/copying | |||
| // StringBuffer.toString().endsWith() does massive memory allocation/copying on JDK 1.5 | |||
| // See http://issues.apache.org/bugzilla/show_bug.cgi?id=37169 | |||
| int endIndex = suffix.length() - 1; | |||
| int bufferIndex = buffer.length() - 1; | |||
| while ( endIndex >= 0 ) { | |||
| if ( buffer.charAt(bufferIndex) != suffix.charAt(endIndex) ) { | |||
| return false; | |||
| } | |||
| bufferIndex--; | |||
| endIndex--; | |||
| } | |||
| return true; | |||
| } | |||
| } | |||
| @@ -55,4 +55,51 @@ public class StringUtilsTest extends TestCase { | |||
| assertEquals("bcbcbc", res); | |||
| } | |||
| public void testEndsWithBothEmpty() { | |||
| assertTrue( StringUtils.endsWith( new StringBuffer(), "") ); | |||
| } | |||
| public void testEndsWithEmptyString() { | |||
| assertTrue( StringUtils.endsWith( new StringBuffer("12234545"), "") ); | |||
| } | |||
| public void testEndsWithShorterString() { | |||
| assertTrue( StringUtils.endsWith( new StringBuffer("12345678"), "78")); | |||
| } | |||
| public void testEndsWithSameString() { | |||
| assertTrue( StringUtils.endsWith( new StringBuffer("123"), "123")); | |||
| } | |||
| public void testEndsWithLongerString() { | |||
| assertFalse( StringUtils.endsWith( new StringBuffer("12"), "1245")); | |||
| } | |||
| public void testEndsWithNoMatch() { | |||
| assertFalse( StringUtils.endsWith( new StringBuffer("12345678"), "789")); | |||
| } | |||
| public void testEndsWithEmptyBuffer() { | |||
| assertFalse( StringUtils.endsWith( new StringBuffer(""), "12345667") ); | |||
| } | |||
| public void testEndsWithJDKPerf() { | |||
| StringBuffer buf = getFilledBuffer(1024*300, 'a'); | |||
| for (int i = 0; i < 1000; i++) { | |||
| assertTrue(buf.toString().endsWith("aa")); | |||
| } | |||
| } | |||
| public void testEndsWithPerf() { | |||
| StringBuffer buf = getFilledBuffer(1024*300, 'a'); | |||
| for (int i = 0; i < 1000; i++) { | |||
| assertTrue(StringUtils.endsWith(buf, "aa")); | |||
| } | |||
| } | |||
| private StringBuffer getFilledBuffer(int size, char ch) { | |||
| StringBuffer buf = new StringBuffer(size); | |||
| for (int i = 0; i < size; i++) { buf.append(ch); }; | |||
| return buf; | |||
| } | |||
| } | |||