From 0319f8134564bb4a4912608e046728fd72a9fcf4 Mon Sep 17 00:00:00 2001 From: Stefan Bodewig Date: Sun, 24 Jul 2016 12:19:51 +0200 Subject: [PATCH] built-in implementation of native2ascii https://bz.apache.org/bugzilla/show_bug.cgi?id=59855 --- WHATSNEW | 5 ++ manual/Tasks/native2ascii.html | 11 ++- .../native2ascii/BuiltinNative2Ascii.java | 82 +++++++++++++++++++ .../Native2AsciiAdapterFactory.java | 29 +++++-- .../tools/ant/util/Native2AsciiUtils.java | 51 ++++++++++++ .../taskdefs/optional/native2ascii-test.xml | 7 ++ .../tools/ant/util/Native2AsciiUtilsTest.java | 46 +++++++++++ 7 files changed, 221 insertions(+), 10 deletions(-) create mode 100644 src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/BuiltinNative2Ascii.java create mode 100644 src/main/org/apache/tools/ant/util/Native2AsciiUtils.java create mode 100644 src/tests/junit/org/apache/tools/ant/util/Native2AsciiUtilsTest.java diff --git a/WHATSNEW b/WHATSNEW index bd90733d6..0253e7e59 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -39,6 +39,11 @@ Other changes: * now supports compression via the optional compressed attribute. Bugzilla Report 47552 + * a new implementation "builtin" has been added to and + is the default when running on JDK9+ since the tool itself has been + removed from the JDK. + Bugzilla Report 59855 + Changes from Ant 1.9.6 TO Ant 1.9.7 =================================== diff --git a/manual/Tasks/native2ascii.html b/manual/Tasks/native2ascii.html index c50483b9f..acbd46085 100644 --- a/manual/Tasks/native2ascii.html +++ b/manual/Tasks/native2ascii.html @@ -61,9 +61,14 @@ with the implementation attribute or a nested element. Here are the choices of the attribute:

    -
  • default - the default converter (kaffe or sun) for the platform.
  • -
  • sun (the standard converter of the JDK)
  • -
  • kaffe (the standard converter of Kaffe)
  • +
  • default - the default converter for the platform - kaffee + when run on Kaffee, builtin if JDK9 or newer is detected, sun + otherwise.
  • +
  • sun (the standard converter of the JDK < 9)
  • +
  • kaffe (the standard converter + of Kaffe)
  • +
  • builtin - Ant's internal implementation used for + JDK9+. since ant 1.9.8
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/BuiltinNative2Ascii.java b/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/BuiltinNative2Ascii.java new file mode 100644 index 000000000..b9e600ced --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/BuiltinNative2Ascii.java @@ -0,0 +1,82 @@ +/* + * 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.tools.ant.taskdefs.optional.native2ascii; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.Writer; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.taskdefs.optional.Native2Ascii; +import org.apache.tools.ant.util.FileUtils; +import org.apache.tools.ant.util.Native2AsciiUtils; +import org.apache.tools.ant.util.StringUtils; + +/** + * Encapsulates the built-in Native2Ascii implementation. + * + * @since Ant 1.9.8 + */ +public class BuiltinNative2Ascii implements Native2AsciiAdapter { + + static final String IMPLEMENTATION_NAME = "builtin"; + + public final boolean convert(Native2Ascii args, File srcFile, + File destFile) throws BuildException { + BufferedReader input = null; + try { + if (args.getEncoding() != null) { + input = new BufferedReader(new InputStreamReader( + new FileInputStream(srcFile), args.getEncoding())); + } else { + input = new BufferedReader(new FileReader(srcFile)); + } + try { + BufferedWriter output = new BufferedWriter( + new OutputStreamWriter(new FileOutputStream(destFile), + "ASCII")); + try { + translate(input, output, args.getReverse()); + } finally { + FileUtils.close(output); + } + } finally { + FileUtils.close(input); + } + return true; + } catch (IOException ex) { + throw new BuildException("Exception trying to translate data", ex); + } + } + + private void translate(BufferedReader input, Writer output, + boolean reverse) throws IOException { + String line = null; + while ((line = input.readLine()) != null) { + output.write(Native2AsciiUtils.native2ascii(line)); + output.write(StringUtils.LINE_SEP); + } + } +} diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/Native2AsciiAdapterFactory.java b/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/Native2AsciiAdapterFactory.java index ae4190395..e8bd74d16 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/Native2AsciiAdapterFactory.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/Native2AsciiAdapterFactory.java @@ -40,10 +40,13 @@ public class Native2AsciiAdapterFactory { * vendor */ public static String getDefault() { - if (JavaEnvUtils.isKaffe() || JavaEnvUtils.isClasspathBased()) { + if (shouldUseKaffee()) { return KaffeNative2Ascii.IMPLEMENTATION_NAME; } - return SunNative2Ascii.IMPLEMENTATION_NAME; + if (shouldUseSun()) { + return SunNative2Ascii.IMPLEMENTATION_NAME; + } + return BuiltinNative2Ascii.IMPLEMENTATION_NAME; } /** @@ -79,11 +82,14 @@ public class Native2AsciiAdapterFactory { ProjectComponent log, Path classpath) throws BuildException { - if (((JavaEnvUtils.isKaffe() || JavaEnvUtils.isClasspathBased()) && choice == null) + if ((shouldUseKaffee() && choice == null) || KaffeNative2Ascii.IMPLEMENTATION_NAME.equals(choice)) { return new KaffeNative2Ascii(); - } else if (SunNative2Ascii.IMPLEMENTATION_NAME.equals(choice)) { + } else if ((shouldUseSun() && choice == null) + || SunNative2Ascii.IMPLEMENTATION_NAME.equals(choice)) { return new SunNative2Ascii(); + } else if (BuiltinNative2Ascii.IMPLEMENTATION_NAME.equals(choice)) { + return new BuiltinNative2Ascii(); } else if (choice != null) { return resolveClassName(choice, // Memory leak in line below @@ -91,9 +97,7 @@ public class Native2AsciiAdapterFactory { .createClassLoader(classpath)); } - // This default has been good enough until Ant 1.6.3, so stick - // with it - return new SunNative2Ascii(); + return new BuiltinNative2Ascii(); } /** @@ -113,4 +117,15 @@ public class Native2AsciiAdapterFactory { Native2AsciiAdapterFactory.class.getClassLoader(), Native2AsciiAdapter.class); } + + private static final boolean shouldUseKaffee() { + return JavaEnvUtils.isKaffe() || JavaEnvUtils.isClasspathBased(); + } + + private static final boolean shouldUseSun() { + return JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_5) + || JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_6) + || JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_7) + || JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_8); + } } diff --git a/src/main/org/apache/tools/ant/util/Native2AsciiUtils.java b/src/main/org/apache/tools/ant/util/Native2AsciiUtils.java new file mode 100644 index 000000000..acdfaaa92 --- /dev/null +++ b/src/main/org/apache/tools/ant/util/Native2AsciiUtils.java @@ -0,0 +1,51 @@ +/* + * 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.tools.ant.util; + +/** + * Contains helper methods for Ant's built-in implementation of native2ascii. + * + * @since Ant 1.9.8 + */ +public class Native2AsciiUtils { + + private static final int MAX_ASCII = 127; + + /** + * Replaces non-ASCII characters with their Unicode-Escapes. + *

Expects to be called once per line if applied to a file.

+ * @param line the input line + * @return the translated line + */ + public static String native2ascii(String line) { + StringBuilder sb = new StringBuilder(); + for (char c : line.toCharArray()) { + if (c <= MAX_ASCII) { + sb.append(c); + } else { + sb.append("\\u"); + String encoded = Integer.toHexString(c); + for (int i = encoded.length(); i < 4; i++) { + sb.append("0"); + } + sb.append(encoded); + } + } + return sb.toString(); + } +} diff --git a/src/tests/antunit/taskdefs/optional/native2ascii-test.xml b/src/tests/antunit/taskdefs/optional/native2ascii-test.xml index a7e6b5731..8705f6a1c 100644 --- a/src/tests/antunit/taskdefs/optional/native2ascii-test.xml +++ b/src/tests/antunit/taskdefs/optional/native2ascii-test.xml @@ -109,6 +109,13 @@ public class Adapter implements Native2AsciiAdapter { expected="${umlauts.expected}"/> + + + + + diff --git a/src/tests/junit/org/apache/tools/ant/util/Native2AsciiUtilsTest.java b/src/tests/junit/org/apache/tools/ant/util/Native2AsciiUtilsTest.java new file mode 100644 index 000000000..75719f2ab --- /dev/null +++ b/src/tests/junit/org/apache/tools/ant/util/Native2AsciiUtilsTest.java @@ -0,0 +1,46 @@ +/* + * 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.tools.ant.util; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class Native2AsciiUtilsTest { + + @Test + public void doesntTouchAscii() { + StringBuilder sb = new StringBuilder(); + for (char i = 0; i < 128; i++) { + sb.append(i); + } + assertEquals(sb.toString(), Native2AsciiUtils.native2ascii(sb.toString())); + } + + @Test + public void escapes() { + assertEquals("\\u00e4\\u00f6\\u00fc", + Native2AsciiUtils.native2ascii("\u00e4\u00f6\u00fc")); + } + + @Test + public void pads() { + assertEquals("\\u00e4\\u01f6\\u12fc", + Native2AsciiUtils.native2ascii("\u00e4\u01f6\u12fc")); + } +}