Exemplo n.º 1
0
  private BatchChangeSetPart createBatchChangeSetPart(
      Edm edm, Map<String, String> contentIdMap, Olingo2BatchChangeRequest batchRequest)
      throws EdmException, URISyntaxException, EntityProviderException, IOException,
          ODataApplicationException {

    // build body string
    String resourcePath = batchRequest.getResourcePath();
    // is it a referenced entity?
    if (resourcePath.startsWith("$")) {
      resourcePath = replaceContentId(edm, resourcePath, contentIdMap);
    }

    final UriInfoWithType uriInfo = parseUri(edm, resourcePath, null);

    // serialize data into ODataResponse object, if set in request and this is not a DELETE request
    final Map<String, String> headers = new HashMap<String, String>();
    byte[] body = null;

    if (batchRequest.getBody() != null && !Operation.DELETE.equals(batchRequest.getOperation())) {

      final ODataResponse response = writeContent(edm, uriInfo, batchRequest.getBody());
      // copy response headers
      for (String header : response.getHeaderNames()) {
        headers.put(header, response.getHeader(header));
      }

      // get (http) entity which is for default Olingo2 implementation an InputStream
      body =
          response.getEntity() instanceof InputStream
              ? EntityProvider.readBinary((InputStream) response.getEntity())
              : null;
      if (body != null) {
        headers.put(HttpHeaders.CONTENT_LENGTH, String.valueOf(body.length));
      }
    }

    // Olingo is sensitive to batch part charset case!!
    headers.put(HttpHeaders.ACCEPT, getResourceContentType(uriInfo).toString().toLowerCase());
    if (!headers.containsKey(HttpHeaders.CONTENT_TYPE)) {
      headers.put(HttpHeaders.CONTENT_TYPE, getContentType());
    }

    // add request headers
    headers.putAll(batchRequest.getHeaders());

    final String contentId = batchRequest.getContentId();
    if (contentId != null) {
      contentIdMap.put("$" + contentId, resourcePath);
    }
    return BatchChangeSetPart.uri(createBatchUri(batchRequest))
        .method(batchRequest.getOperation().getHttpMethod())
        .contentId(contentId)
        .headers(headers)
        .body(body == null ? null : new String(body, Consts.UTF_8))
        .build();
  }
Exemplo n.º 2
0
  @Override
  public ODataResponse deleteEntity(DeleteUriInfo uriInfo, String contentType)
      throws ODataException {
    LOG.debug("Deleting Entity: " + uriInfo);

    if ("Cars".equals(uriInfo.getTargetEntitySet().getName())) {
      int key = getKeyValue(uriInfo.getKeyPredicates().get(0));

      // if there is no entry with this key available, one should return
      // "404 Not Found"
      // return ODataResponse.status(HttpStatusCodes.NOT_FOUND).build();

      // now one can delete the entry with this particular key in the
      // backend...

    } else if ("Manufacturers".equals(uriInfo.getTargetEntitySet().getName())) {
      int key = getKeyValue(uriInfo.getKeyPredicates().get(0));
      // now one can delete the entry with this particular key in the
      // backend...
    }

    // we can return Status Code 204 No Content because the URI Parsing
    // already guarantees that
    // a) only valid URIs are dispatched (also checked against the metadata)
    // b) 404 Not Found is already returned above, when the entry does not
    // exist
    return ODataResponse.status(HttpStatusCodes.NO_CONTENT).build();
  }
Exemplo n.º 3
0
  @Override
  public ODataResponse updateEntity(
      PutMergePatchUriInfo uriInfo,
      InputStream content,
      String requestContentType,
      boolean merge,
      String contentType)
      throws ODataException {
    LOG.debug("Updating Entity: " + uriInfo);

    EntityProviderReadProperties properties =
        EntityProviderReadProperties.init().mergeSemantic(false).build();

    ODataEntry entry =
        EntityProvider.readEntry(
            requestContentType, uriInfo.getTargetEntitySet(), content, properties);
    // if something goes wrong in deserialization this is managed via the
    // ExceptionMapper,
    // no need for an application to do exception handling here an convert
    // the exceptions in HTTP exceptions

    Map<String, Object> data = entry.getProperties();

    if ("Cars".equals(uriInfo.getTargetEntitySet().getName())) {
      int key = getKeyValue(uriInfo.getKeyPredicates().get(0));

      // if there is no entry with this key available, one should return
      // "404 Not Found"
      // return ODataResponse.status(HttpStatusCodes.NOT_FOUND).build();

      // now one can use the data to create the entry in the backend ...
      String model = (String) data.get("Model");
      // ...
    } else if ("Manufacturers".equals(uriInfo.getTargetEntitySet().getName())) {
      int key = getKeyValue(uriInfo.getKeyPredicates().get(0));
      // now one can use the data to create the entry in the backend ...
    }

    // we can return Status Code 204 No Content because the URI Parsing
    // already guarantees that
    // a) only valid URIs are dispatched (also checked against the metadata)
    // b) 404 Not Found is already returned above, when the entry does not
    // exist
    return ODataResponse.status(HttpStatusCodes.NO_CONTENT).build();
  }
Exemplo n.º 4
0
  private ODataResponse parseBatchRequest(final Edm edm, final List<Olingo2BatchRequest> batchParts)
      throws IOException, EntityProviderException, ODataApplicationException, EdmException,
          URISyntaxException {

    // create Batch request from parts
    final ArrayList<BatchPart> parts = new ArrayList<BatchPart>();
    final ArrayList<BatchChangeSetPart> changeSetParts = new ArrayList<BatchChangeSetPart>();

    final Map<String, String> contentIdMap = new HashMap<String, String>();

    for (Olingo2BatchRequest batchPart : batchParts) {

      if (batchPart instanceof Olingo2BatchQueryRequest) {

        // need to add change set parts collected so far??
        if (!changeSetParts.isEmpty()) {
          addChangeSetParts(parts, changeSetParts);
          changeSetParts.clear();
          contentIdMap.clear();
        }

        // add to request parts
        final UriInfoWithType uriInfo = parseUri(edm, batchPart.getResourcePath(), null);
        parts.add(createBatchQueryPart(uriInfo, (Olingo2BatchQueryRequest) batchPart));

      } else {

        // add to change set parts
        final BatchChangeSetPart changeSetPart =
            createBatchChangeSetPart(edm, contentIdMap, (Olingo2BatchChangeRequest) batchPart);
        changeSetParts.add(changeSetPart);
      }
    }

    // add any remaining change set parts
    if (!changeSetParts.isEmpty()) {
      addChangeSetParts(parts, changeSetParts);
    }

    final String boundary = BOUNDARY_PREFIX + UUID.randomUUID();
    InputStream batchRequest = EntityProvider.writeBatchRequest(parts, boundary);
    // two blank lines are already added. No need to add extra blank lines
    final String contentHeader = BATCH_CONTENT_TYPE + BOUNDARY_PARAMETER + boundary;
    return ODataResponse.entity(batchRequest).contentHeader(contentHeader).build();
  }
Exemplo n.º 5
0
  private ODataResponse writeContent(Edm edm, UriInfoWithType uriInfo, Object content)
      throws ODataApplicationException, EdmException, EntityProviderException, URISyntaxException,
          IOException {

    String responseContentType = getContentType();
    ODataResponse response;

    switch (uriInfo.getUriType()) {
      case URI4:
      case URI5:
        // simple property
        final List<EdmProperty> simplePropertyPath = uriInfo.getPropertyPath();
        final EdmProperty simpleProperty = simplePropertyPath.get(simplePropertyPath.size() - 1);
        responseContentType = simpleProperty.getMimeType();
        if (uriInfo.isValue()) {
          response = EntityProvider.writePropertyValue(simpleProperty, content);
          responseContentType = TEXT_PLAIN_WITH_CS_UTF_8.toString();
        } else {
          response = EntityProvider.writeProperty(getContentType(), simpleProperty, content);
        }
        break;

      case URI3:
        // complex property
        final List<EdmProperty> complexPropertyPath = uriInfo.getPropertyPath();
        final EdmProperty complexProperty = complexPropertyPath.get(complexPropertyPath.size() - 1);
        response = EntityProvider.writeProperty(responseContentType, complexProperty, content);
        break;

      case URI7A:
        // $links with 0..1 cardinality property
        final EdmEntitySet targetLinkEntitySet = uriInfo.getTargetEntitySet();
        EntityProviderWriteProperties linkProperties =
            EntityProviderWriteProperties.serviceRoot(new URI(serviceUri + SEPARATOR)).build();
        @SuppressWarnings("unchecked")
        final Map<String, Object> linkMap = (Map<String, Object>) content;
        response =
            EntityProvider.writeLink(
                responseContentType, targetLinkEntitySet, linkMap, linkProperties);
        break;

      case URI7B:
        // $links with * cardinality property
        final EdmEntitySet targetLinksEntitySet = uriInfo.getTargetEntitySet();
        EntityProviderWriteProperties linksProperties =
            EntityProviderWriteProperties.serviceRoot(new URI(serviceUri + SEPARATOR)).build();
        @SuppressWarnings("unchecked")
        final List<Map<String, Object>> linksMap = (List<Map<String, Object>>) content;
        response =
            EntityProvider.writeLinks(
                responseContentType, targetLinksEntitySet, linksMap, linksProperties);
        break;

      case URI1:
      case URI2:
      case URI6A:
      case URI6B:
        // Entity
        final EdmEntitySet targetEntitySet = uriInfo.getTargetEntitySet();
        EntityProviderWriteProperties properties =
            EntityProviderWriteProperties.serviceRoot(new URI(serviceUri + SEPARATOR)).build();
        @SuppressWarnings("unchecked")
        final Map<String, Object> objectMap = (Map<String, Object>) content;
        response =
            EntityProvider.writeEntry(responseContentType, targetEntitySet, objectMap, properties);
        break;

      case URI9:
        // $batch
        @SuppressWarnings("unchecked")
        final List<Olingo2BatchRequest> batchParts = (List<Olingo2BatchRequest>) content;
        response = parseBatchRequest(edm, batchParts);
        break;

      default:
        // notify exception and return!!!
        throw new ODataApplicationException(
            "Unsupported resource type " + uriInfo.getTargetType(), Locale.ENGLISH);
    }

    return response.getContentHeader() != null
        ? response
        : ODataResponse.fromResponse(response).contentHeader(responseContentType).build();
  }
Exemplo n.º 6
0
  private <T> void writeContent(
      final Edm edm,
      HttpEntityEnclosingRequestBase httpEntityRequest,
      final UriInfoWithType uriInfo,
      final Object content,
      final Olingo2ResponseHandler<T> responseHandler) {

    try {
      // process resource by UriType
      final ODataResponse response = writeContent(edm, uriInfo, content);

      // copy all response headers
      for (String header : response.getHeaderNames()) {
        httpEntityRequest.setHeader(header, response.getHeader(header));
      }

      // get (http) entity which is for default Olingo2 implementation an InputStream
      if (response.getEntity() instanceof InputStream) {
        httpEntityRequest.setEntity(new InputStreamEntity((InputStream) response.getEntity()));
        /*
                        // avoid sending it without a header field set
                        if (!httpEntityRequest.containsHeader(HttpHeaders.CONTENT_TYPE)) {
                            httpEntityRequest.addHeader(HttpHeaders.CONTENT_TYPE, getContentType());
                        }
        */
      }

      // execute HTTP request
      final Header requestContentTypeHeader =
          httpEntityRequest.getFirstHeader(HttpHeaders.CONTENT_TYPE);
      final ContentType requestContentType =
          requestContentTypeHeader != null
              ? ContentType.parse(requestContentTypeHeader.getValue())
              : contentType;
      execute(
          httpEntityRequest,
          requestContentType,
          new AbstractFutureCallback<T>(responseHandler) {
            @SuppressWarnings("unchecked")
            @Override
            public void onCompleted(HttpResponse result)
                throws IOException, EntityProviderException, BatchException,
                    ODataApplicationException {

              // if a entity is created (via POST request) the response body contains the new
              // created entity
              HttpStatusCodes statusCode =
                  HttpStatusCodes.fromStatusCode(result.getStatusLine().getStatusCode());

              // look for no content, or no response body!!!
              final boolean noEntity =
                  result.getEntity() == null || result.getEntity().getContentLength() == 0;
              if (statusCode == HttpStatusCodes.NO_CONTENT || noEntity) {
                responseHandler.onResponse(
                    (T) HttpStatusCodes.fromStatusCode(result.getStatusLine().getStatusCode()));
              } else {

                switch (uriInfo.getUriType()) {
                  case URI9:
                    // $batch
                    final List<BatchSingleResponse> singleResponses =
                        EntityProvider.parseBatchResponse(
                            result.getEntity().getContent(),
                            result.getFirstHeader(HttpHeaders.CONTENT_TYPE).getValue());

                    // parse batch response bodies
                    final List<Olingo2BatchResponse> responses =
                        new ArrayList<Olingo2BatchResponse>();
                    Map<String, String> contentIdLocationMap = new HashMap<String, String>();

                    final List<Olingo2BatchRequest> batchRequests =
                        (List<Olingo2BatchRequest>) content;
                    final Iterator<Olingo2BatchRequest> iterator = batchRequests.iterator();

                    for (BatchSingleResponse response : singleResponses) {
                      final Olingo2BatchRequest request = iterator.next();

                      if (request instanceof Olingo2BatchChangeRequest
                          && ((Olingo2BatchChangeRequest) request).getContentId() != null) {

                        contentIdLocationMap.put(
                            "$" + ((Olingo2BatchChangeRequest) request).getContentId(),
                            response.getHeader(HttpHeaders.LOCATION));
                      }

                      try {
                        responses.add(parseResponse(edm, contentIdLocationMap, request, response));
                      } catch (Exception e) {
                        // report any parsing errors as error response
                        responses.add(
                            new Olingo2BatchResponse(
                                Integer.parseInt(response.getStatusCode()),
                                response.getStatusInfo(),
                                response.getContentId(),
                                response.getHeaders(),
                                new ODataApplicationException(
                                    "Error parsing response for " + request + ": " + e.getMessage(),
                                    Locale.ENGLISH,
                                    e)));
                      }
                    }
                    responseHandler.onResponse((T) responses);
                    break;

                  case URI4:
                  case URI5:
                    // simple property
                    // get the response content as Object for $value or Map<String, Object>
                    // otherwise
                    final List<EdmProperty> simplePropertyPath = uriInfo.getPropertyPath();
                    final EdmProperty simpleProperty =
                        simplePropertyPath.get(simplePropertyPath.size() - 1);
                    if (uriInfo.isValue()) {
                      responseHandler.onResponse(
                          (T)
                              EntityProvider.readPropertyValue(
                                  simpleProperty, result.getEntity().getContent()));
                    } else {
                      responseHandler.onResponse(
                          (T)
                              EntityProvider.readProperty(
                                  getContentType(),
                                  simpleProperty,
                                  result.getEntity().getContent(),
                                  EntityProviderReadProperties.init().build()));
                    }
                    break;

                  case URI3:
                    // complex property
                    // get the response content as Map<String, Object>
                    final List<EdmProperty> complexPropertyPath = uriInfo.getPropertyPath();
                    final EdmProperty complexProperty =
                        complexPropertyPath.get(complexPropertyPath.size() - 1);
                    responseHandler.onResponse(
                        (T)
                            EntityProvider.readProperty(
                                getContentType(),
                                complexProperty,
                                result.getEntity().getContent(),
                                EntityProviderReadProperties.init().build()));
                    break;

                  case URI7A:
                    // $links with 0..1 cardinality property
                    // get the response content as String
                    final EdmEntitySet targetLinkEntitySet = uriInfo.getTargetEntitySet();
                    responseHandler.onResponse(
                        (T)
                            EntityProvider.readLink(
                                getContentType(),
                                targetLinkEntitySet,
                                result.getEntity().getContent()));
                    break;

                  case URI7B:
                    // $links with * cardinality property
                    // get the response content as java.util.List<String>
                    final EdmEntitySet targetLinksEntitySet = uriInfo.getTargetEntitySet();
                    responseHandler.onResponse(
                        (T)
                            EntityProvider.readLinks(
                                getContentType(),
                                targetLinksEntitySet,
                                result.getEntity().getContent()));
                    break;

                  case URI1:
                  case URI2:
                  case URI6A:
                  case URI6B:
                    // Entity
                    // get the response content as an ODataEntry object
                    responseHandler.onResponse(
                        (T)
                            EntityProvider.readEntry(
                                response.getContentHeader(),
                                uriInfo.getTargetEntitySet(),
                                result.getEntity().getContent(),
                                EntityProviderReadProperties.init().build()));
                    break;

                  default:
                    throw new ODataApplicationException(
                        "Unsupported resource type " + uriInfo.getTargetType(), Locale.ENGLISH);
                }
              }
            }
          });
    } catch (ODataException e) {
      responseHandler.onException(e);
    } catch (URISyntaxException e) {
      responseHandler.onException(e);
    } catch (UnsupportedEncodingException e) {
      responseHandler.onException(e);
    } catch (IOException e) {
      responseHandler.onException(e);
    }
  }