예제 #1
0
 private static void validate(DataTemplate<?> data, Class<?> clazz) {
   final ValidationResult valResult =
       ValidateDataAgainstSchema.validate(data.data(), data.schema(), _defaultValOptions);
   if (!valResult.isValid()) {
     throw new IllegalArgumentException(
         "Coercing String \""
             + data.data()
             + "\" to type "
             + clazz.getName()
             + " failed due to schema validation: "
             + valResult.getMessages());
   }
 }
예제 #2
0
  private static DataTemplate<?> buildDataTemplateArgument(
      final ResourceContext context, final Parameter<?> param) {
    Object paramValue = context.getStructuredParameter(param.getName());
    DataTemplate<?> paramRecordTemplate;

    if (paramValue == null) {
      return null;
    } else {
      @SuppressWarnings("unchecked")
      final Class<? extends RecordTemplate> paramType =
          (Class<? extends RecordTemplate>) param.getType();
      /**
       * It is possible for the paramValue provided by ResourceContext to be coerced to the wrong
       * type. If a query param is a single value param for example www.domain.com/resource?foo=1.
       * Then ResourceContext will parse foo as a String with value = 1. However if a query param
       * contains many values for example www.domain.com/resource?foo=1&foo=2&foo=3 Then
       * ResourceContext will parse foo as an DataList with value [1,2,3]
       *
       * <p>So this means if the 'final' type of a query param is an Array and the paramValue we
       * received from ResourceContext is not a DataList we will have to wrap the paramValue inside
       * a DataList
       */
      if (AbstractArrayTemplate.class.isAssignableFrom(paramType)
          && paramValue.getClass() != DataList.class) {
        paramRecordTemplate =
            DataTemplateUtil.wrap(new DataList(Arrays.asList(paramValue)), paramType);
      } else {
        paramRecordTemplate = DataTemplateUtil.wrap(paramValue, paramType);
      }

      // Validate against the class schema with FixupMode.STRING_TO_PRIMITIVE to parse the
      // strings into the corresponding primitive types.
      ValidateDataAgainstSchema.validate(
          paramRecordTemplate.data(),
          paramRecordTemplate.schema(),
          new ValidationOptions(
              RequiredMode.CAN_BE_ABSENT_IF_HAS_DEFAULT, CoercionMode.STRING_TO_PRIMITIVE));
      return paramRecordTemplate;
    }
  }
예제 #3
0
  /**
   * Build a method argument from a request parameter that is an array
   *
   * @param context {@link ResourceContext}
   * @param param {@link Parameter}
   * @return argument value in the correct type
   */
  private static Object buildArrayArgument(
      final ResourceContext context, final Parameter<?> param) {
    final Object convertedValue;
    if (DataTemplate.class.isAssignableFrom(param.getItemType())) {
      final DataList itemsList = (DataList) context.getStructuredParameter(param.getName());
      convertedValue = Array.newInstance(param.getItemType(), itemsList.size());
      int j = 0;
      for (Object paramData : itemsList) {
        final DataTemplate<?> itemsElem =
            DataTemplateUtil.wrap(paramData, param.getItemType().asSubclass(DataTemplate.class));

        ValidateDataAgainstSchema.validate(
            itemsElem.data(),
            itemsElem.schema(),
            new ValidationOptions(
                RequiredMode.CAN_BE_ABSENT_IF_HAS_DEFAULT, CoercionMode.STRING_TO_PRIMITIVE));

        Array.set(convertedValue, j++, itemsElem);
      }
    } else {
      final List<String> itemStringValues = context.getParameterValues(param.getName());
      ArrayDataSchema parameterSchema = null;
      if (param.getDataSchema() instanceof ArrayDataSchema) {
        parameterSchema = (ArrayDataSchema) param.getDataSchema();
      } else {
        throw new RoutingException(
            "An array schema is expected.", HttpStatus.S_400_BAD_REQUEST.getCode());
      }

      convertedValue = Array.newInstance(param.getItemType(), itemStringValues.size());
      int j = 0;
      for (String itemStringValue : itemStringValues) {
        if (itemStringValue == null) {
          throw new RoutingException(
              "Parameter '" + param.getName() + "' cannot contain null values",
              HttpStatus.S_400_BAD_REQUEST.getCode());
        }
        try {
          Array.set(
              convertedValue,
              j++,
              ArgumentUtils.convertSimpleValue(
                  itemStringValue, parameterSchema.getItems(), param.getItemType()));
        } catch (NumberFormatException e) {
          Class<?> targetClass =
              DataSchemaUtil.dataSchemaTypeToPrimitiveDataSchemaClass(
                  parameterSchema.getItems().getDereferencedType());
          // thrown from Integer.valueOf or Long.valueOf
          throw new RoutingException(
              String.format(
                  "Array parameter '%s' value '%s' must be of type '%s'",
                  param.getName(), itemStringValue, targetClass.getName()),
              HttpStatus.S_400_BAD_REQUEST.getCode());
        } catch (IllegalArgumentException e) {
          // thrown from Enum.valueOf
          throw new RoutingException(
              String.format(
                  "Array parameter '%s' value '%s' is invalid", param.getName(), itemStringValue),
              HttpStatus.S_400_BAD_REQUEST.getCode());
        } catch (TemplateRuntimeException e) {
          // thrown from DataTemplateUtil.coerceOutput
          throw new RoutingException(
              String.format(
                  "Array parameter '%s' value '%s' is invalid. Reason: %s",
                  param.getName(), itemStringValue, e.getMessage()),
              HttpStatus.S_400_BAD_REQUEST.getCode());
        }
      }
    }

    return convertedValue;
  }