You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by rs...@apache.org on 2020/07/23 15:12:39 UTC

[avro] branch master updated: [AVRO-2571] avro-maven-plugin not escaping "public" keyword in namespace (#844)

This is an automated email from the ASF dual-hosted git repository.

rskraba pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/avro.git


The following commit(s) were added to refs/heads/master by this push:
     new 0394e17  [AVRO-2571] avro-maven-plugin not escaping "public" keyword in namespace (#844)
0394e17 is described below

commit 0394e1772e78d9b726bd015c9d02b146a1abaee0
Author: Henrique Mota <he...@gmail.com>
AuthorDate: Thu Jul 23 12:12:31 2020 -0300

    [AVRO-2571] avro-maven-plugin not escaping "public" keyword in namespace (#844)
    
    * [AVRO-2571] escape reserved java keywords in packages
    
    * using mangle to scape namespace
    
    * Revert "using mangle to scape namespace"
    
    This reverts commit eb788cc4
    
    * AVRO-2571: using mangle to scape namespace
    
    * AVRO-2571: removing inport  org.apache.commons.lang3.StringUtils
    
    * AVRO-2571: fix NullPointer error
---
 .../avro/compiler/specific/SpecificCompiler.java   | 22 +++++++++----
 .../specific/templates/java/classic/enum.vm        |  2 +-
 .../specific/templates/java/classic/fixed.vm       |  2 +-
 .../specific/templates/java/classic/protocol.vm    |  4 +--
 .../specific/templates/java/classic/record.vm      | 37 +++++++++++-----------
 .../compiler/specific/TestSpecificCompiler.java    |  8 +++++
 .../test/resources/simple_record_for_scape.avsc    |  9 ++++++
 7 files changed, 55 insertions(+), 29 deletions(-)

diff --git a/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java b/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java
index 9258a99..b88b3c9 100644
--- a/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java
+++ b/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java
@@ -51,6 +51,7 @@ import org.apache.avro.SchemaNormalization;
 import org.apache.avro.JsonProperties;
 import org.apache.avro.generic.GenericData;
 import org.apache.avro.generic.GenericData.StringType;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.velocity.Template;
 import org.apache.velocity.VelocityContext;
 import org.apache.velocity.app.VelocityEngine;
@@ -531,7 +532,7 @@ public class SpecificCompiler {
 
     OutputFile outputFile = new OutputFile();
     String mangledName = mangle(protocol.getName());
-    outputFile.path = makePath(mangledName, protocol.getNamespace());
+    outputFile.path = makePath(mangledName, mangle(protocol.getNamespace()));
     outputFile.contents = out;
     outputFile.outputCharacterEncoding = outputCharacterEncoding;
     return outputFile;
@@ -603,7 +604,7 @@ public class SpecificCompiler {
 
     OutputFile outputFile = new OutputFile();
     String name = mangle(schema.getName());
-    outputFile.path = makePath(name, schema.getNamespace());
+    outputFile.path = makePath(name, mangle(schema.getNamespace()));
     outputFile.contents = output;
     outputFile.outputCharacterEncoding = outputCharacterEncoding;
     return outputFile;
@@ -1018,13 +1019,20 @@ public class SpecificCompiler {
 
   /** Utility for template use. Adds a dollar sign to reserved words. */
   public static String mangle(String word, Set<String> reservedWords, boolean isMethod) {
+    if (StringUtils.isBlank(word)) {
+      return word;
+    }
     if (word.contains(".")) {
       // If the 'word' is really a full path of a class we must mangle just the
-      // classname
-      int lastDot = word.lastIndexOf(".");
-      String packageName = word.substring(0, lastDot + 1);
-      String className = word.substring(lastDot + 1);
-      return packageName + mangle(className, reservedWords, isMethod);
+      String[] packageWords = word.split("\\.");
+      String[] newPackageWords = new String[packageWords.length];
+
+      for (int i = 0; i < packageWords.length; i++) {
+        String oldName = packageWords[i];
+        newPackageWords[i] = mangle(oldName, reservedWords, false);
+      }
+
+      return String.join(".", newPackageWords);
     }
     if (reservedWords.contains(word) || (isMethod && reservedWords
         .contains(Character.toLowerCase(word.charAt(0)) + ((word.length() > 1) ? word.substring(1) : "")))) {
diff --git a/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/enum.vm b/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/enum.vm
index a0df265..c3feab9 100644
--- a/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/enum.vm
+++ b/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/enum.vm
@@ -16,7 +16,7 @@
 ## limitations under the License.
 ##
 #if ($schema.getNamespace())
-package $schema.getNamespace();
+package $this.mangle($schema.getNamespace());
 #end
 #if ($schema.getDoc())
 /** $schema.getDoc() */
diff --git a/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/fixed.vm b/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/fixed.vm
index 2beee5e..f4c935a 100644
--- a/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/fixed.vm
+++ b/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/fixed.vm
@@ -16,7 +16,7 @@
 ## limitations under the License.
 ##
 #if ($schema.getNamespace())
-package $schema.getNamespace();
+package $this.mangle($schema.getNamespace());
 #end
 #if ($schema.getDoc())
 /** $schema.getDoc() */
diff --git a/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/protocol.vm b/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/protocol.vm
index 4fd1fac..a35226b 100644
--- a/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/protocol.vm
+++ b/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/protocol.vm
@@ -16,7 +16,7 @@
 ## limitations under the License.
 ##
 #if ($protocol.getNamespace())
-package $protocol.getNamespace();
+package $this.mangle($protocol.getNamespace());
 #end
 
 #if ($protocol.getDoc())
@@ -66,7 +66,7 @@ ${this.mangle($error.getFullName())}##
   /** $protocol.getDoc() */
 #end
   public interface Callback extends $this.mangle($protocol.getName()) {
-    public static final org.apache.avro.Protocol PROTOCOL = #if ($protocol.getNamespace())$protocol.getNamespace().#end${this.mangle($protocol.getName())}.PROTOCOL;
+    public static final org.apache.avro.Protocol PROTOCOL = #if ($this.mangle($protocol.getNamespace()))$this.mangle($protocol.getNamespace()).#end${this.mangle($protocol.getName())}.PROTOCOL;
 #foreach ($e in $protocol.getMessages().entrySet())
 #set ($name = $e.getKey())
 #set ($message = $e.getValue())
diff --git a/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm b/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm
index b37a16f..4a2b714 100755
--- a/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm
+++ b/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm
@@ -16,7 +16,7 @@
 ## limitations under the License.
 ##
 #if ($schema.getNamespace())
-package $schema.getNamespace();
+package $this.mangle($schema.getNamespace());
 #end
 
 import org.apache.avro.generic.GenericArray;
@@ -260,8 +260,8 @@ static {
    * Creates a new ${this.mangle($schema.getName())} RecordBuilder.
    * @return A new ${this.mangle($schema.getName())} RecordBuilder
    */
-  public static #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder newBuilder() {
-    return new #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder();
+  public static #if ($schema.getNamespace())$this.mangle($schema.getNamespace()).#end${this.mangle($schema.getName())}.Builder newBuilder() {
+    return new #if ($schema.getNamespace())$this.mangle($schema.getNamespace()).#end${this.mangle($schema.getName())}.Builder();
   }
 
   /**
@@ -269,11 +269,11 @@ static {
    * @param other The existing builder to copy.
    * @return A new ${this.mangle($schema.getName())} RecordBuilder
    */
-  public static #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder newBuilder(#if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder other) {
+  public static #if ($schema.getNamespace())$this.mangle($schema.getNamespace()).#end${this.mangle($schema.getName())}.Builder newBuilder(#if ($schema.getNamespace())$this.mangle($schema.getNamespace()).#end${this.mangle($schema.getName())}.Builder other) {
     if (other == null) {
-      return new #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder();
+      return new #if ($schema.getNamespace())$this.mangle($schema.getNamespace()).#end${this.mangle($schema.getName())}.Builder();
     } else {
-      return new #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder(other);
+      return new #if ($schema.getNamespace())$this.mangle($schema.getNamespace()).#end${this.mangle($schema.getName())}.Builder(other);
     }
   }
 
@@ -282,11 +282,11 @@ static {
    * @param other The existing instance to copy.
    * @return A new ${this.mangle($schema.getName())} RecordBuilder
    */
-  public static #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder newBuilder(#if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())} other) {
+  public static #if ($schema.getNamespace())$this.mangle($schema.getNamespace()).#end${this.mangle($schema.getName())}.Builder newBuilder(#if ($schema.getNamespace())$this.mangle($schema.getNamespace()).#end${this.mangle($schema.getName())} other) {
     if (other == null) {
-      return new #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder();
+      return new #if ($schema.getNamespace())$this.mangle($schema.getNamespace()).#end${this.mangle($schema.getName())}.Builder();
     } else {
-      return new #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder(other);
+      return new #if ($schema.getNamespace())$this.mangle($schema.getNamespace()).#end${this.mangle($schema.getName())}.Builder(other);
     }
   }
 
@@ -317,7 +317,7 @@ static {
      * Creates a Builder by copying an existing Builder.
      * @param other The existing Builder to copy.
      */
-    private Builder(#if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder other) {
+    private Builder(#if ($schema.getNamespace())$this.mangle($schema.getNamespace()).#end${this.mangle($schema.getName())}.Builder other) {
       super(other);
 #foreach ($field in $schema.getFields())
       if (isValidValue(fields()[$field.pos()], other.${this.mangle($field.name(), $schema.isError())})) {
@@ -336,7 +336,7 @@ static {
      * Creates a Builder by copying an existing $this.mangle($schema.getName()) instance
      * @param other The existing instance to copy.
      */
-    private Builder(#if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())} other) {
+    private Builder(#if ($schema.getNamespace())$this.mangle($schema.getNamespace()).#end${this.mangle($schema.getName())} other) {
 #if ($schema.isError())      super(other)#else
       super(SCHEMA$)#end;
 #foreach ($field in $schema.getFields())
@@ -352,25 +352,25 @@ static {
 #if ($schema.isError())
 
     @Override
-    public #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder setValue(Object value) {
+    public #if ($schema.getNamespace())$this.mangle($schema.getNamespace()).#end${this.mangle($schema.getName())}.Builder setValue(Object value) {
       super.setValue(value);
       return this;
     }
 
     @Override
-    public #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder clearValue() {
+    public #if ($schema.getNamespace())$this.mangle($schema.getNamespace()).#end${this.mangle($schema.getName())}.Builder clearValue() {
       super.clearValue();
       return this;
     }
 
     @Override
-    public #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder setCause(Throwable cause) {
+    public #if ($schema.getNamespace())$this.mangle($schema.getNamespace()).#end${this.mangle($schema.getName())}.Builder setCause(Throwable cause) {
       super.setCause(cause);
       return this;
     }
 
     @Override
-    public #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder clearCause() {
+    public #if ($schema.getNamespace())$this.mangle($schema.getNamespace()).#end${this.mangle($schema.getName())}.Builder clearCause() {
       super.clearCause();
       return this;
     }
@@ -406,7 +406,7 @@ static {
       * @param value The value of '${this.mangle($field.name(), $schema.isError())}'.
       * @return This builder.
       */
-    public #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder ${this.generateSetMethod($schema, $field)}(${this.javaUnbox($field.schema(), false)} value) {
+    public #if ($schema.getNamespace())$this.mangle($schema.getNamespace()).#end${this.mangle($schema.getName())}.Builder ${this.generateSetMethod($schema, $field)}(${this.javaUnbox($field.schema(), false)} value) {
       validate(fields()[$field.pos()], value);
 #if (${this.hasBuilder($field.schema())})
       this.${this.mangle($field.name(), $schema.isError())}Builder = null;
@@ -451,7 +451,8 @@ static {
      * @param value The builder instance that must be set.
      * @return This builder.
      */
-    public #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder ${this.generateSetBuilderMethod($schema, $field)}(${this.javaUnbox($field.schema(), false)}.Builder value) {
+
+    public #if ($schema.getNamespace())$this.mangle($schema.getNamespace()).#end${this.mangle($schema.getName())}.Builder ${this.generateSetBuilderMethod($schema, $field)}(${this.javaUnbox($field.schema(), false)}.Builder value) {
       ${this.generateClearMethod($schema, $field)}();
       ${this.mangle($field.name(), $schema.isError())}Builder = value;
       return this;
@@ -474,7 +475,7 @@ static {
 #end
       * @return This builder.
       */
-    public #if ($schema.getNamespace())$schema.getNamespace().#end${this.mangle($schema.getName())}.Builder ${this.generateClearMethod($schema, $field)}() {
+    public #if ($schema.getNamespace())$this.mangle($schema.getNamespace()).#end${this.mangle($schema.getName())}.Builder ${this.generateClearMethod($schema, $field)}() {
 #if (${this.isUnboxedJavaTypeNullable($field.schema())})
       ${this.mangle($field.name(), $schema.isError())} = null;
 #end
diff --git a/lang/java/compiler/src/test/java/org/apache/avro/compiler/specific/TestSpecificCompiler.java b/lang/java/compiler/src/test/java/org/apache/avro/compiler/specific/TestSpecificCompiler.java
index a3c8a30..4c92422 100644
--- a/lang/java/compiler/src/test/java/org/apache/avro/compiler/specific/TestSpecificCompiler.java
+++ b/lang/java/compiler/src/test/java/org/apache/avro/compiler/specific/TestSpecificCompiler.java
@@ -606,6 +606,14 @@ public class TestSpecificCompiler {
   }
 
   @Test
+  public void testPackageNameScape() throws Exception {
+    Schema unionTypesWithMultipleFields = new Schema.Parser()
+        .parse(new File("src/test/resources/simple_record_for_scape.avsc"));
+    assertCompilesWithJavaCompiler(new File(this.outputFile, name.getMethodName()),
+        new SpecificCompiler(unionTypesWithMultipleFields).compile());
+  }
+
+  @Test
   public void testLogicalTypesWithMultipleFields() throws Exception {
     Schema logicalTypesWithMultipleFields = new Schema.Parser()
         .parse(new File("src/test/resources/logical_types_with_multiple_fields.avsc"));
diff --git a/lang/java/compiler/src/test/resources/simple_record_for_scape.avsc b/lang/java/compiler/src/test/resources/simple_record_for_scape.avsc
new file mode 100644
index 0000000..637f3d4
--- /dev/null
+++ b/lang/java/compiler/src/test/resources/simple_record_for_scape.avsc
@@ -0,0 +1,9 @@
+{
+  "type": "record", 
+  "name": "SimpleRecord",
+  "namespace" : "org.public.int.void",
+  "fields" : [
+    {"name": "value", "type": "int"},
+    {"name": "nullableValue", "type": ["null","int"], "doc" : "doc"}
+  ]
+}