Author: cutting
Date: Wed Oct 21 17:10:06 2009
New Revision: 828110

URL: http://svn.apache.org/viewvc?rev=828110&view=rev
Log:
AVRO-166.  Improve error checking in Java schema parser.  Contributed by Philip 
Zeyliger.

Modified:
    hadoop/avro/trunk/CHANGES.txt
    hadoop/avro/trunk/src/java/org/apache/avro/Schema.java
    hadoop/avro/trunk/src/test/java/org/apache/avro/io/TestValidatingIO.java

Modified: hadoop/avro/trunk/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/hadoop/avro/trunk/CHANGES.txt?rev=828110&r1=828109&r2=828110&view=diff
==============================================================================
--- hadoop/avro/trunk/CHANGES.txt (original)
+++ hadoop/avro/trunk/CHANGES.txt Wed Oct 21 17:10:06 2009
@@ -20,6 +20,9 @@
 
     AVRO-148. Add ant target to build c++ project.  (sbanacho)
 
+    AVRO-166. Improve error checking in Java schema parser.
+    (Philip Zeyliger via cutting)
+
   OPTIMIZATIONS
 
   BUG FIXES

Modified: hadoop/avro/trunk/src/java/org/apache/avro/Schema.java
URL: 
http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/Schema.java?rev=828110&r1=828109&r2=828110&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/Schema.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/Schema.java Wed Oct 21 17:10:06 
2009
@@ -552,6 +552,8 @@
     private final int size;
     public FixedSchema(String name, String space, int size) {
       super(Type.FIXED, name, space);
+      if (size < 0)
+        throw new IllegalArgumentException("Invalid fixed size: "+size);
       this.size = size;
     }
     public int getFixedSize() { return size; }
@@ -689,21 +691,16 @@
         throw new SchemaParseException("Undefined name: "+schema);
       return result;
     } else if (schema.isObject()) {
-      JsonNode typeNode = schema.get("type");
-      if (typeNode == null)
-        throw new SchemaParseException("No type: "+schema);
-      String type = typeNode.getTextValue();
+      String type = getRequiredText(schema, "type", "No type");
       String name = null, space = null;
       if (type.equals("record") || type.equals("error")
           || type.equals("enum") || type.equals("fixed")) {
-        JsonNode nameNode = schema.get("name");
-        name = nameNode != null ? nameNode.getTextValue() : null;
-        JsonNode spaceNode = schema.get("namespace");
-        space = spaceNode!=null?spaceNode.getTextValue():names.space();
+        name = getRequiredText(schema, "name", "No name in schema");
+        space = getOptionalText(schema, "namespace");
+        if (space == null)
+          space = names.space();
         if (names.space() == null && space != null)
           names.space(space);                     // set default namespace
-        if (name == null)
-          throw new SchemaParseException("No name in schema: "+schema);
       }
       if (type.equals("record") || type.equals("error")) { // record
         LinkedHashMap<String,Field> fields = new LinkedHashMap<String,Field>();
@@ -745,8 +742,10 @@
       } else if (type.equals("map")) {            // map
         return new MapSchema(parse(schema.get("values"), names));
       } else if (type.equals("fixed")) {          // fixed
-        Schema result = new FixedSchema(name, space,
-                                        schema.get("size").getIntValue());
+        JsonNode sizeNode = schema.get("size");
+        if (sizeNode == null || !sizeNode.isInt())
+          throw new SchemaParseException("Invalid or no size: "+schema);
+        Schema result = new FixedSchema(name, space, sizeNode.getIntValue());
         if (name != null) names.add(result);
         return result;
       } else
@@ -761,6 +760,29 @@
     }
   }
 
+  /** Extracts text value associated to key from the container JsonNode,
+   * and throws {...@link SchemaParseException} if it doesn't exist.
+   *
+   * @param container Container where to find key.
+   * @param key Key to look for in container.
+   * @param error String to prepend to the SchemaParseException.
+   * @return
+   */
+  private static String getRequiredText(JsonNode container, String key,
+      String error) {
+    String out = getOptionalText(container, key);
+    if (null == out) {
+      throw new SchemaParseException(error + ": " + container);
+    }
+    return out;
+  }
+
+  /** Extracts text value associated to key from the container JsonNode. */
+  private static String getOptionalText(JsonNode container, String key) {
+    JsonNode jsonNode = container.get(key);
+    return jsonNode != null ? jsonNode.getTextValue() : null;
+  }
+
   static JsonNode parseJson(String s) {
     try {
       return MAPPER.readTree(FACTORY.createJsonParser(new StringReader(s)));

Modified: 
hadoop/avro/trunk/src/test/java/org/apache/avro/io/TestValidatingIO.java
URL: 
http://svn.apache.org/viewvc/hadoop/avro/trunk/src/test/java/org/apache/avro/io/TestValidatingIO.java?rev=828110&r1=828109&r2=828110&view=diff
==============================================================================
--- hadoop/avro/trunk/src/test/java/org/apache/avro/io/TestValidatingIO.java 
(original)
+++ hadoop/avro/trunk/src/test/java/org/apache/avro/io/TestValidatingIO.java 
Wed Oct 21 17:10:06 2009
@@ -659,7 +659,7 @@
         { "\"string\"", "S10" },
         { "\"bytes\"", "b0" },
         { "\"bytes\"", "b10" },
-        { "{\"type\":\"fixed\", \"name\":\"fi\", \"size\": 0}", "f0" },
+        { "{\"type\":\"fixed\", \"name\":\"fi\", \"size\": 1}", "f1" },
         { "{\"type\":\"fixed\", \"name\":\"fi\", \"size\": 10}", "f10" },
         { "{\"type\":\"enum\", \"name\":\"en\", \"symbols\":[\"v1\", \"v2\"]}",
             "e1" },


Reply via email to