github-code-scanning[bot] commented on code in PR #1768:
URL: https://github.com/apache/avro/pull/1768#discussion_r918924967


##########
lang/java/avro/src/main/java/org/apache/avro/Schema.java:
##########
@@ -694,6 +697,81 @@
     public String toString() {
       return name + " type:" + schema.type + " pos:" + position;
     }
+
+    static Field parse(JsonNode field, Names names, String namespace) {
+      String fieldName = getRequiredText(field, "name", "No field name");
+      String fieldDoc = getOptionalText(field, "doc");
+      JsonNode fieldTypeNode = field.get("type");
+      if (fieldTypeNode == null) {
+        throw new SchemaParseException("No field type: " + field);
+      }
+
+      Schema fieldSchema = null;
+      if (fieldTypeNode.isTextual()) {
+        Schema schemaField = names.get(fieldTypeNode.textValue());
+        if (schemaField == null) {
+          schemaField = names.get(namespace + "." + fieldTypeNode.textValue());
+        }
+        if (schemaField == null) {
+          throw new SchemaParseException(fieldTypeNode + " is not a defined 
name." + " The type of the \"" + fieldName
+              + "\" field must be a defined name or a {\"type\": ...} 
expression.");
+        }
+        fieldSchema = schemaField;
+      } else if (fieldTypeNode.isObject()) {
+        fieldSchema = resolveSchema(fieldTypeNode, names, namespace);
+        if (fieldSchema == null) {
+          fieldSchema = Schema.parseFieldsOnly(fieldTypeNode, names, 
namespace);
+        }
+      } else if (fieldTypeNode.isArray()) {
+        List<Schema> unionTypes = new ArrayList<>();
+
+        fieldTypeNode.forEach((JsonNode node) -> {
+          Schema subSchema = null;
+          if (node.isTextual()) {
+            subSchema = names.get(node.asText());
+            if (subSchema == null) {
+              subSchema = names.get(namespace + "." + node.asText());
+            }
+          } else if (node.isObject()) {
+            subSchema = Schema.parseFieldsOnly(node, names, namespace);
+          } else {
+            throw new SchemaParseException("Illegal type in union : " + node);
+          }
+          if (subSchema == null) {
+            throw new SchemaParseException("Null element in union : " + node);
+          }
+          unionTypes.add(subSchema);
+        });
+
+        fieldSchema = Schema.createUnion(unionTypes);
+      }
+
+      if (fieldSchema == null) {
+        throw new SchemaParseException("Can't find type for field " + 
fieldName);
+      }
+      Field.Order order = Field.Order.ASCENDING;
+      JsonNode orderNode = field.get("order");
+      if (orderNode != null)
+        order = 
Field.Order.valueOf(orderNode.textValue().toUpperCase(Locale.ENGLISH));
+      JsonNode defaultValue = field.get("default");
+
+      if (defaultValue != null && fieldSchema != null
+          && (Type.FLOAT.equals(fieldSchema.getType()) || 
Type.DOUBLE.equals(fieldSchema.getType()))
+          && defaultValue.isTextual())
+        defaultValue = new 
DoubleNode(Double.valueOf(defaultValue.textValue()));

Review Comment:
   ## Missing catch of NumberFormatException
   
   Potential uncaught 'java.lang.NumberFormatException'.
   
   [Show more 
details](https://github.com/apache/avro/security/code-scanning/2776)



##########
lang/java/avro/src/main/java/org/apache/avro/Schema.java:
##########
@@ -694,6 +697,81 @@
     public String toString() {
       return name + " type:" + schema.type + " pos:" + position;
     }
+
+    static Field parse(JsonNode field, Names names, String namespace) {
+      String fieldName = getRequiredText(field, "name", "No field name");
+      String fieldDoc = getOptionalText(field, "doc");
+      JsonNode fieldTypeNode = field.get("type");
+      if (fieldTypeNode == null) {
+        throw new SchemaParseException("No field type: " + field);
+      }
+
+      Schema fieldSchema = null;
+      if (fieldTypeNode.isTextual()) {
+        Schema schemaField = names.get(fieldTypeNode.textValue());
+        if (schemaField == null) {
+          schemaField = names.get(namespace + "." + fieldTypeNode.textValue());
+        }
+        if (schemaField == null) {
+          throw new SchemaParseException(fieldTypeNode + " is not a defined 
name." + " The type of the \"" + fieldName
+              + "\" field must be a defined name or a {\"type\": ...} 
expression.");
+        }
+        fieldSchema = schemaField;
+      } else if (fieldTypeNode.isObject()) {
+        fieldSchema = resolveSchema(fieldTypeNode, names, namespace);
+        if (fieldSchema == null) {
+          fieldSchema = Schema.parseFieldsOnly(fieldTypeNode, names, 
namespace);
+        }
+      } else if (fieldTypeNode.isArray()) {
+        List<Schema> unionTypes = new ArrayList<>();
+
+        fieldTypeNode.forEach((JsonNode node) -> {
+          Schema subSchema = null;
+          if (node.isTextual()) {
+            subSchema = names.get(node.asText());
+            if (subSchema == null) {
+              subSchema = names.get(namespace + "." + node.asText());
+            }
+          } else if (node.isObject()) {
+            subSchema = Schema.parseFieldsOnly(node, names, namespace);
+          } else {
+            throw new SchemaParseException("Illegal type in union : " + node);
+          }
+          if (subSchema == null) {
+            throw new SchemaParseException("Null element in union : " + node);
+          }
+          unionTypes.add(subSchema);
+        });
+
+        fieldSchema = Schema.createUnion(unionTypes);
+      }
+
+      if (fieldSchema == null) {
+        throw new SchemaParseException("Can't find type for field " + 
fieldName);
+      }
+      Field.Order order = Field.Order.ASCENDING;
+      JsonNode orderNode = field.get("order");
+      if (orderNode != null)
+        order = 
Field.Order.valueOf(orderNode.textValue().toUpperCase(Locale.ENGLISH));
+      JsonNode defaultValue = field.get("default");
+
+      if (defaultValue != null && fieldSchema != null

Review Comment:
   ## Useless null check
   
   This check is useless, [fieldSchema](1) cannot be null here, since it is 
guarded by [... == ...](2).
   
   [Show more 
details](https://github.com/apache/avro/security/code-scanning/2773)



##########
lang/java/avro/src/main/java/org/apache/avro/Schema.java:
##########
@@ -1668,78 +1746,38 @@
     }
   }
 
-  /** @see #parse(String) */
-  static Schema parse(JsonNode schema, Names names) {
+  static Schema parseNamesDeclared(JsonNode schema, Names names, String 
nameSpace) {
     if (schema == null) {
-      throw new SchemaParseException("Cannot parse <null> schema");
+      return null;
     }
-    if (schema.isTextual()) { // name
-      Schema result = names.get(schema.textValue());
-      if (result == null)
-        throw new SchemaParseException("Undefined name: " + schema);
-      return result;
-    } else if (schema.isObject()) {
-      Schema result;
-      String type = getRequiredText(schema, "type", "No type");
+    if (schema.isObject()) {
+
+      String type = Schema.getOptionalText(schema, "type");
       Name name = null;
-      String savedSpace = names.space();
+
       String doc = null;
+      Schema result = null;
       final boolean isTypeError = "error".equals(type);
       final boolean isTypeRecord = "record".equals(type);
       final boolean isTypeEnum = "enum".equals(type);
       final boolean isTypeFixed = "fixed".equals(type);
+
       if (isTypeRecord || isTypeError || isTypeEnum || isTypeFixed) {
         String space = getOptionalText(schema, "namespace");
         doc = getOptionalText(schema, "doc");
         if (space == null)
-          space = savedSpace;
+          space = nameSpace;
         name = new Name(getRequiredText(schema, "name", "No name in schema"), 
space);
-        names.space(name.space); // set default namespace
       }
-      if (PRIMITIVES.containsKey(type)) { // primitive
-        result = create(PRIMITIVES.get(type));
-      } else if (isTypeRecord || isTypeError) { // record
-        List<Field> fields = new ArrayList<>();
+      if (isTypeRecord || isTypeError) { // record
         result = new RecordSchema(name, doc, isTypeError);
-        if (name != null)
-          names.add(result);
+        names.add(result);
         JsonNode fieldsNode = schema.get("fields");
+
         if (fieldsNode == null || !fieldsNode.isArray())
           throw new SchemaParseException("Record has no fields: " + schema);
-        for (JsonNode field : fieldsNode) {
-          String fieldName = getRequiredText(field, "name", "No field name");
-          String fieldDoc = getOptionalText(field, "doc");
-          JsonNode fieldTypeNode = field.get("type");
-          if (fieldTypeNode == null)
-            throw new SchemaParseException("No field type: " + field);
-          if (fieldTypeNode.isTextual() && 
names.get(fieldTypeNode.textValue()) == null)
-            throw new SchemaParseException(fieldTypeNode + " is not a defined 
name." + " The type of the \"" + fieldName
-                + "\" field must be a defined name or a {\"type\": ...} 
expression.");
-          Schema fieldSchema = parse(fieldTypeNode, names);
-          Field.Order order = Field.Order.ASCENDING;
-          JsonNode orderNode = field.get("order");
-          if (orderNode != null)
-            order = 
Field.Order.valueOf(orderNode.textValue().toUpperCase(Locale.ENGLISH));
-          JsonNode defaultValue = field.get("default");
-          if (defaultValue != null
-              && (Type.FLOAT.equals(fieldSchema.getType()) || 
Type.DOUBLE.equals(fieldSchema.getType()))
-              && defaultValue.isTextual())
-            defaultValue = new 
DoubleNode(Double.valueOf(defaultValue.textValue()));
-          Field f = new Field(fieldName, fieldSchema, fieldDoc, defaultValue, 
true, order);
-          Iterator<String> i = field.fieldNames();
-          while (i.hasNext()) { // add field props
-            String prop = i.next();
-            if (!FIELD_RESERVED.contains(prop))
-              f.addProp(prop, field.get(prop));
-          }
-          f.aliases = parseAliases(field);
-          fields.add(f);
-          if (fieldSchema.getLogicalType() == null && getOptionalText(field, 
LOGICAL_TYPE_PROP) != null)
-            LOG.warn(
-                "Ignored the {}.{}.logicalType property (\"{}\"). It should 
probably be nested inside the \"type\" for the field.",
-                name, fieldName, getOptionalText(field, "logicalType"));
-        }
-        result.setFields(fields);
+        exploreFields(fieldsNode, names, name.space);

Review Comment:
   ## Dereferenced variable may be null
   
   Variable [name](1) may be null here because of [this](2) assignment.
   
   [Show more 
details](https://github.com/apache/avro/security/code-scanning/2774)



##########
lang/java/avro/src/test/java/org/apache/avro/TestProtocol.java:
##########
@@ -23,10 +23,33 @@
 import static java.util.Collections.singletonMap;
 import static org.junit.Assert.*;
 
+import java.io.File;
+import java.io.IOException;
+
+import org.junit.Assert;
 import org.junit.Test;
 
 public class TestProtocol {
 
+  @Test
+  public void parse() throws IOException {
+    File fic = new File("../../../share/test/schemas/namespace.avpr");
+    Protocol protocol = Protocol.parse(fic);
+    Assert.assertNotNull(protocol);
+    Assert.assertEquals("TestNamespace", protocol.getName());
+  }
+
+  @Test
+  public void testProUnknown() {
+    String userStatus = "{ \"protocol\" : \"p1\", " + "\"types\": ["
+        + "{\"name\": \"User\", \"type\": \"record\", \"fields\": [{\"name\": 
\"current_status\", \"type\": \"Status\"}]},\n"
+        + "\n"
+        + "{\"name\": \"Status\", \"type\": \"record\", \"fields\": 
[{\"name\": \"author\", \"type\": \"User\"}]}"
+        + "]}";
+
+    Protocol protocol = Protocol.parse(userStatus);

Review Comment:
   ## Unread local variable
   
   Variable 'Protocol protocol' is never read.
   
   [Show more 
details](https://github.com/apache/avro/security/code-scanning/2775)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to