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

mgrigorov 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 d87a99d53 AVRO-3698: SpecificData.getClassName must replace reserved 
words (#2048)
d87a99d53 is described below

commit d87a99d532719ba6f619ba68e07dbaa77fe4f84e
Author: 정승현 <[email protected]>
AuthorDate: Tue Jan 10 20:42:32 2023 +0900

    AVRO-3698: SpecificData.getClassName must replace reserved words (#2048)
---
 .../org/apache/avro/specific/SpecificData.java     | 24 ++++++++++++++++++++--
 .../org/apache/avro/specific/TestSpecificData.java |  7 +++++++
 .../avro/compiler/specific/SpecificCompiler.java   |  3 ++-
 3 files changed, 31 insertions(+), 3 deletions(-)

diff --git 
a/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificData.java 
b/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificData.java
index 966acb5fc..0476b2e2f 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificData.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificData.java
@@ -91,6 +91,8 @@ public class SpecificData extends GenericData {
   public static final String KEY_CLASS_PROP = "java-key-class";
   public static final String ELEMENT_PROP = "java-element-class";
 
+  public static final char RESERVED_WORD_ESCAPE_CHAR = '$';
+
   /**
    * Reserved words from
    * https://docs.oracle.com/javase/specs/jls/se16/html/jls-3.html require
@@ -329,8 +331,26 @@ public class SpecificData extends GenericData {
     String name = schema.getName();
     if (namespace == null || "".equals(namespace))
       return name;
-    String dot = namespace.endsWith("$") ? "" : "."; // back-compatibly handle 
$
-    return namespace + dot + name;
+
+    StringBuilder classNameBuilder = new StringBuilder();
+    String[] words = namespace.split("\\.");
+
+    for (int i = 0; i < words.length; i++) {
+      String word = words[i];
+      classNameBuilder.append(word);
+
+      if (RESERVED_WORDS.contains(word)) {
+        classNameBuilder.append(RESERVED_WORD_ESCAPE_CHAR);
+      }
+
+      if (i != words.length - 1 || !word.endsWith("$")) { // back-compatibly 
handle $
+        classNameBuilder.append(".");
+      }
+    }
+
+    classNameBuilder.append(name);
+
+    return classNameBuilder.toString();
   }
 
   // cache for schemas created from Class objects. Use ClassValue to avoid
diff --git 
a/lang/java/avro/src/test/java/org/apache/avro/specific/TestSpecificData.java 
b/lang/java/avro/src/test/java/org/apache/avro/specific/TestSpecificData.java
index 0db2a8b44..4fe9abb6b 100644
--- 
a/lang/java/avro/src/test/java/org/apache/avro/specific/TestSpecificData.java
+++ 
b/lang/java/avro/src/test/java/org/apache/avro/specific/TestSpecificData.java
@@ -178,4 +178,11 @@ public class TestSpecificData {
       // Expected error
     }
   }
+
+  @Test
+  void classNameContainingReservedWords() {
+    final Schema schema = Schema.createRecord("AnyName", null, 
"db.public.table", false);
+
+    assertEquals("db.public$.table.AnyName", 
SpecificData.getClassName(schema));
+  }
 }
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 6f46845bb..baa2fd793 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
@@ -61,6 +61,7 @@ import org.slf4j.LoggerFactory;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.apache.avro.specific.SpecificData.RESERVED_WORDS;
+import static org.apache.avro.specific.SpecificData.RESERVED_WORD_ESCAPE_CHAR;
 
 /**
  * Generate specific Java interfaces and classes for protocols and schemas.
@@ -1126,7 +1127,7 @@ public class SpecificCompiler {
     }
     if (reservedWords.contains(word) || (isMethod && reservedWords
         .contains(Character.toLowerCase(word.charAt(0)) + ((word.length() > 1) 
? word.substring(1) : "")))) {
-      return word + "$";
+      return word + RESERVED_WORD_ESCAPE_CHAR;
     }
     return word;
   }

Reply via email to