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; | |||
} | |||
} |