Exemplo n.º 1
0
  public Object getDefaultValue() {
    if (_defaultValueData == null) {
      return null;
    }

    final Object result;
    if (_defaultValueData instanceof String) {
      final String defaultValueString = (String) _defaultValueData;
      try {
        if (getType().isArray()) {
          final DataList valueAsDataList = _codec.stringToList(defaultValueString);
          result = DataTemplateUtil.convertDataListToArray(valueAsDataList, getItemType());
        } else if (DataTemplate.class.isAssignableFrom(getType())) {
          final Object input;
          if (AbstractArrayTemplate.class.isAssignableFrom(getType())) {
            input = _codec.stringToList(defaultValueString);
          } else if (AbstractMapTemplate.class.isAssignableFrom(getType())
              || UnionTemplate.class.isAssignableFrom(getType())
              || RecordTemplate.class.isAssignableFrom(getType())) {
            input = _codec.stringToMap(defaultValueString);
          } else {
            input = defaultValueString;
          }

          result = DataTemplateUtil.wrap(input, getType().asSubclass(DataTemplate.class));
          validate((DataTemplate<?>) result, getType());
        } else {
          result = ValueConverter.coerceString(defaultValueString, getType());
        }
      } catch (TemplateOutputCastException e) {
        throw new ResourceConfigException(e.getMessage(), e);
      } catch (IllegalArgumentException e) {
        throw new ResourceConfigException(
            "Default value for parameter of type \""
                + getType().getName()
                + "\" is not supported: "
                + e.getMessage(),
            e);
      } catch (IOException e) {
        throw new ResourceConfigException(
            "Default value for parameter of type \""
                + getType().getName()
                + "\" is not supported: "
                + e.getMessage(),
            e);
      }
    } else {
      result = _defaultValueData;
    }

    return result;
  }
Exemplo n.º 2
0
 static {
   HashMap<java.lang.String, DynamicRecordMetadata> requestMetadataMap =
       new HashMap<java.lang.String, DynamicRecordMetadata>();
   ArrayList<FieldDef<?>> theActionParams = new ArrayList<FieldDef<?>>();
   requestMetadataMap.put("theAction", new DynamicRecordMetadata("theAction", theActionParams));
   HashMap<java.lang.String, DynamicRecordMetadata> responseMetadataMap =
       new HashMap<java.lang.String, DynamicRecordMetadata>();
   responseMetadataMap.put(
       "theAction",
       new DynamicRecordMetadata(
           "theAction",
           Collections.singletonList(
               new FieldDef<java.lang.String>(
                   "value",
                   java.lang.String.class,
                   DataTemplateUtil.getSchema(java.lang.String.class)))));
   HashMap<java.lang.String, com.linkedin.restli.common.CompoundKey.TypeInfo> keyParts =
       new HashMap<java.lang.String, com.linkedin.restli.common.CompoundKey.TypeInfo>();
   _resourceSpec =
       new ResourceSpecImpl(
           EnumSet.of(
               ResourceMethod.GET,
               ResourceMethod.CREATE,
               ResourceMethod.UPDATE,
               ResourceMethod.DELETE),
           requestMetadataMap,
           responseMetadataMap,
           Long.class,
           null,
           null,
           Greeting.class,
           keyParts);
 }
Exemplo n.º 3
0
 /**
  * Effectively a combination of {@link #readMap(com.linkedin.r2.message.rest.RestMessage)} and
  * {@link #convert(DataMap, Class)}.
  *
  * @param message {@link RestMessage}
  * @param recordClass class of the requested type
  * @param <T> requested object type
  * @return a new object of the requested type constructed with DataMap read from message entity
  * @throws IOException on error reading input stream
  */
 public static <T extends RecordTemplate> T read(
     final RestMessage message, final Class<T> recordClass) throws IOException {
   try {
     DataMap dataMap = readMapWithExceptions(message);
     return DataTemplateUtil.wrap(dataMap, recordClass);
   } catch (IllegalArgumentException e) {
     throw new RestLiInternalException(e);
   } catch (SecurityException e) {
     throw new RestLiInternalException(e);
   }
 }
Exemplo n.º 4
0
 /**
  * Effectively a combination of {@link #readMap(InputStream)} and {@link #convert(DataMap,
  * Class)}.
  *
  * @param stream input stream
  * @param recordClass class of the requested type
  * @param <T> requested object type
  * @return a new object of the requested type constructed with DataMap read from input stream
  * @throws IOException on error reading input stream
  */
 public static <T extends RecordTemplate> T read(
     final InputStream stream, final Class<T> recordClass) throws IOException {
   try {
     DataMap dataMap = CODEC.readMap(stream);
     return DataTemplateUtil.wrap(dataMap, recordClass);
   } catch (IllegalArgumentException e) {
     throw new RestLiInternalException(e);
   } catch (SecurityException e) {
     throw new RestLiInternalException(e);
   }
 }
Exemplo n.º 5
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;
    }
  }
Exemplo n.º 6
0
  /**
   * Convert a DataMap representation of a BatchRequest (string->record) into a Java Map appropriate
   * for passing into application code. Note that compound/complex keys are represented as their
   * string encoding in the DataMap. Since we have already parsed these keys, we simply try to match
   * the string representations, rather than re-parsing.
   *
   * @param data - the input DataMap to be converted
   * @param valueClass - the RecordTemplate type of the values
   * @param ids - the parsed batch ids from the request URI
   * @return a map using appropriate key and value classes, or null if ids is null
   */
  public static <R extends RecordTemplate> Map<Object, R> buildBatchRequestMap(
      final DataMap data,
      final Class<R> valueClass,
      final Set<?> ids,
      final ProtocolVersion version) {
    if (ids == null) {
      return null;
    }

    BatchRequest<R> batchRequest = new BatchRequest<R>(data, new TypeSpec<R>(valueClass));

    Map<String, Object> parsedKeyMap = new HashMap<String, Object>();
    for (Object o : ids) {
      parsedKeyMap.put(URIParamUtils.encodeKeyForBody(o, true, version), o);
    }

    Map<Object, R> result =
        new HashMap<Object, R>(
            CollectionUtils.getMapInitialCapacity(batchRequest.getEntities().size(), 0.75f), 0.75f);
    for (Map.Entry<String, R> entry : batchRequest.getEntities().entrySet()) {
      Object key = parsedKeyMap.get(entry.getKey());
      if (key == null) {
        throw new RoutingException(
            String.format(
                "Batch request mismatch, URI keys: '%s'  Entity keys: '%s'",
                ids.toString(), batchRequest.getEntities().keySet().toString()),
            HttpStatus.S_400_BAD_REQUEST.getCode());
      }
      R value = DataTemplateUtil.wrap(entry.getValue().data(), valueClass);
      result.put(key, value);
    }
    if (!ids.equals(result.keySet())) {
      throw new RoutingException(
          String.format(
              "Batch request mismatch, URI keys: '%s'  Entity keys: '%s'",
              ids.toString(), result.keySet().toString()),
          HttpStatus.S_400_BAD_REQUEST.getCode());
    }
    return result;
  }
Exemplo n.º 7
0
 private static Object paramToDataObject(
     Object param, Class<?> paramClass, ProtocolVersion version) {
   if (param == null) {
     return null;
   } else if (param instanceof ComplexResourceKey) {
     return ((ComplexResourceKey) param).toDataMap();
   } else if (version.compareTo(AllProtocolVersions.RESTLI_PROTOCOL_2_0_0.getProtocolVersion())
           >= 0
       && param instanceof CompoundKey) {
     return URIParamUtils.compoundKeyToDataMap((CompoundKey) param);
   } else if (param instanceof DataTemplate) {
     @SuppressWarnings("rawtypes")
     final DataTemplate dataTemplate = (DataTemplate) param;
     return dataTemplate.data();
   } else if (param instanceof DataComplex) {
     return param;
   } else if (param instanceof List) {
     return coerceList((List) param, paramClass, version);
   } else {
     return DataTemplateUtil.stringify(param, paramClass);
   }
 }
Exemplo n.º 8
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;
  }