avro-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cutt...@apache.org
Subject svn commit: r882689 - in /hadoop/avro/trunk: CHANGES.txt src/java/org/apache/avro/specific/SpecificCompiler.java src/test/java/org/apache/avro/specific/TestSpecificCompiler.java
Date Fri, 20 Nov 2009 19:22:34 GMT
Author: cutting
Date: Fri Nov 20 19:22:34 2009
New Revision: 882689

URL: http://svn.apache.org/viewvc?rev=882689&view=rev
Log:
AVRO-221.  Mangle Java reserved words in generated code to avoid name conflicts.  Contributed
by Philip Zeyliger.

Modified:
    hadoop/avro/trunk/CHANGES.txt
    hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificCompiler.java
    hadoop/avro/trunk/src/test/java/org/apache/avro/specific/TestSpecificCompiler.java

Modified: hadoop/avro/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/CHANGES.txt?rev=882689&r1=882688&r2=882689&view=diff
==============================================================================
--- hadoop/avro/trunk/CHANGES.txt (original)
+++ hadoop/avro/trunk/CHANGES.txt Fri Nov 20 19:22:34 2009
@@ -135,6 +135,9 @@
     AVRO-224. Code cleanup: cleaner distinction between public and private 
     methods (massie)
 
+    AVRO-221. Mangle Java reserved words in generated code to avoid
+    name conflicts.  (Philip Zeyliger via cutting)
+
 Avro 1.2.0 (14 October 2009)
 
   INCOMPATIBLE CHANGES

Modified: hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificCompiler.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificCompiler.java?rev=882689&r1=882688&r2=882689&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificCompiler.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificCompiler.java Fri Nov 20 19:22:34
2009
@@ -21,6 +21,7 @@
 import java.io.FileWriter;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
@@ -32,11 +33,30 @@
 import org.apache.avro.Protocol.Message;
 import org.apache.avro.tool.Tool;
 
-/** Generate specific Java interfaces and classes for protocols and schemas. */
+/**
+ * Generate specific Java interfaces and classes for protocols and schemas.
+ *
+ * Java reserved keywords are mangled to preserve compilation.
+ */
 public class SpecificCompiler {
   private final Set<Schema> queue = new HashSet<Schema>();
   private final Protocol protocol;
 
+  /** List of Java reserved words from
+   * <a href="http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html">Sun</a>.
+   */
+  private static final Set<String> RESERVED_WORDS = new HashSet<String>(
+      Arrays.asList(new String[] {
+          "abstract", "assert", "boolean", "break", "byte", "case", "catch",
+          "char", "class", "const", "continue", "default", "do", "double",
+          "else", "enum", "extends", "false", "final", "finally", "float",
+          "for", "goto", "if", "implements", "import", "instanceof", "int",
+          "interface", "long", "native", "new", "null", "package", "private",
+          "protected", "public", "return", "short", "static", "strictfp",
+          "super", "switch", "synchronized", "this", "throw", "throws",
+          "transient", "true", "try", "void", "volatile", "while"
+        }));
+
   public SpecificCompiler(Protocol protocol) {
     // enqueue all types
     for (Schema s : protocol.getTypes()) {
@@ -91,6 +111,13 @@
     compiler.compileToDestination(dest);
   }
 
+  static String mangle(String word) {
+    if (RESERVED_WORDS.contains(word)) {
+      return word + "$";
+    }
+    return word;
+  }
+
   /** Recursively enqueue schemas that need a class generated. */
   private void enqueue(Schema schema) {
     if (queue.contains(schema)) return;
@@ -150,7 +177,7 @@
     outputFile.path = makePath(protocol.getName(), protocol.getNamespace());
     StringBuilder out = new StringBuilder();
     header(out, protocol.getNamespace());
-    line(out, 0, "public interface "+protocol.getName()+" {");
+    line(out, 0, "public interface "+mangle(protocol.getName())+" {");
     line(out, 1, "public static final Protocol _PROTOCOL = Protocol.parse(\""
            +esc(protocol)+"\");");
     for (Map.Entry<String,Message> e : protocol.getMessages().entrySet()) {
@@ -158,7 +185,7 @@
       Message message = e.getValue();
       Schema request = message.getRequest();
       Schema response = message.getResponse();
-      line(out, 1, unbox(response)+" "+name+"("+params(request)+")");
+      line(out, 1, unbox(response)+" "+ mangle(name)+"("+params(request)+")");
       line(out, 2,"throws AvroRemoteException"+errors(message.getErrors())+";");
     }
     line(out, 0, "}");
@@ -207,7 +234,7 @@
     StringBuilder b = new StringBuilder();
     int count = 0;
     for (Map.Entry<String, Schema> param : request.getFieldSchemas()) {
-      String paramName = param.getKey();
+      String paramName = mangle(param.getKey());
       b.append(unbox(param.getValue()));
       b.append(" ");
       b.append(paramName);
@@ -221,7 +248,7 @@
     StringBuilder b = new StringBuilder();
     for (Schema error : errs.getTypes().subList(1, errs.getTypes().size())) {
       b.append(", ");
-      b.append(error.getName());
+      b.append(mangle(error.getName()));
     }
     return b.toString();
   }
@@ -243,8 +270,8 @@
            +esc(schema)+"\");");
       // field declations
       for (Map.Entry<String,Schema.Field> field: schema.getFields().entrySet())
-        line(out, 1,
-             "public "+unbox(field.getValue().schema())+" "+field.getKey()+";");
+        line(out, 1, "public " + unbox(field.getValue().schema()) + " "
+             + mangle(field.getKey()) + ";");
       // schema method
       line(out, 1, "public Schema getSchema() { return _SCHEMA; }");
       // get method
@@ -252,7 +279,7 @@
       line(out, 2, "switch (_field) {");
       int i = 0;
       for (Map.Entry<String, Schema> field : schema.getFieldSchemas())
-        line(out, 2, "case "+(i++)+": return "+field.getKey()+";");
+        line(out, 2, "case "+(i++)+": return "+mangle(field.getKey())+";");
       line(out, 2, "default: throw new AvroRuntimeException(\"Bad index\");");
       line(out, 2, "}");
       line(out, 1, "}");
@@ -274,7 +301,7 @@
       StringBuilder b = new StringBuilder();
       int count = 0;
       for (String symbol : schema.getEnumSymbols()) {
-        b.append(symbol);
+        b.append(mangle(symbol));
         if (++count < schema.getEnumSymbols().size())
           b.append(", ");
       }
@@ -302,7 +329,7 @@
     case RECORD:
     case ENUM:
     case FIXED:
-      return schema.getName();
+      return mangle(schema.getName());
     case ARRAY:
       return "GenericArray<"+type(schema.getElementType())+">";
     case MAP:

Modified: hadoop/avro/trunk/src/test/java/org/apache/avro/specific/TestSpecificCompiler.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/test/java/org/apache/avro/specific/TestSpecificCompiler.java?rev=882689&r1=882688&r2=882689&view=diff
==============================================================================
--- hadoop/avro/trunk/src/test/java/org/apache/avro/specific/TestSpecificCompiler.java (original)
+++ hadoop/avro/trunk/src/test/java/org/apache/avro/specific/TestSpecificCompiler.java Fri
Nov 20 19:22:34 2009
@@ -22,7 +22,9 @@
 
 import java.io.File;
 import java.util.Collection;
+import java.util.Iterator;
 
+import org.apache.avro.Protocol;
 import org.apache.avro.Schema;
 import org.apache.avro.TestSchema;
 import org.apache.avro.specific.SpecificCompiler.OutputFile;
@@ -62,6 +64,74 @@
     assertTrue(o.contents.contains("public enum Test"));
   }
 
+  @Test
+  public void testMangleIfReserved() {
+    assertEquals("foo", SpecificCompiler.mangle("foo"));
+    assertEquals("goto$", SpecificCompiler.mangle("goto"));
+  }
+
+  @Test
+  public void testManglingForProtocols() {
+    String protocolDef = "" +
+      "{ \"protocol\": \"default\",\n" +
+      "  \"types\":\n" +
+      "    [\n" +
+      "      {\n" +
+      "       \"name\": \"finally\",\n" +
+      "       \"type\": \"error\",\n" +
+      "       \"fields\": [{\"name\": \"catch\", \"type\": \"boolean\"}]\n" +
+      "      }\n" +
+      "    ],\n" +
+      "  \"messages\": { \"goto\":\n" +
+      "    { \"request\": [{\"name\": \"break\", \"type\": \"string\"}],\n" +
+      "      \"response\": \"string\",\n" +
+      "      \"errors\": [\"finally\"]\n" +
+      "    }" +
+      "   }\n" +
+      "}\n";
+    Iterator<OutputFile> i =
+      new SpecificCompiler(Protocol.parse(protocolDef)).compile().iterator();
+    String errType = i.next().contents;
+    String protocol = i.next().contents;
+
+    assertTrue(errType.contains("public class finally$ extends SpecificExceptionBase"));
+    assertTrue(errType.contains("public boolean catch$;"));
+
+    assertTrue(protocol.contains("Utf8 goto$(Utf8 break$)"));
+    assertTrue(protocol.contains("public interface default$"));
+    assertTrue(protocol.contains("throws AvroRemoteException, finally$"));
+
+  }
+
+  @Test
+  public void testManglingForRecords() {
+    String schema = "" +
+      "{ \"name\": \"volatile\", \"type\": \"record\", " +
+      "  \"fields\": [ {\"name\": \"package\", \"type\": \"string\" }," +
+      "                {\"name\": \"short\", \"type\": \"volatile\" } ] }";
+    Collection<OutputFile> c =
+      new SpecificCompiler(Schema.parse(schema)).compile();
+    assertEquals(1, c.size());
+    String contents = c.iterator().next().contents;
+
+    assertTrue(contents.contains("public Utf8 package$;"));
+    assertTrue(contents.contains("class volatile$ extends"));
+    assertTrue(contents.contains("volatile$ short$;"));
+  }
+
+  @Test
+  public void testManglingForEnums() {
+    String enumSchema = "" +
+      "{ \"name\": \"instanceof\", \"type\": \"enum\"," +
+      "  \"symbols\": [\"new\", \"super\", \"switch\"] }";
+    Collection<OutputFile> c =
+      new SpecificCompiler(Schema.parse(enumSchema)).compile();
+    assertEquals(1, c.size());
+    String contents = c.iterator().next().contents;
+
+    assertTrue(contents.contains("new$"));
+  }
+
   /**
    * Called from TestSchema as part of its comprehensive checks.
    */



Mime
View raw message