| /******************************************************************************* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| ******************************************************************************/ |
| package org.apache.olingo.odata2.core.batch; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.assertArrayEquals; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.olingo.odata2.api.batch.BatchException; |
| import org.apache.olingo.odata2.api.batch.BatchRequestPart; |
| import org.apache.olingo.odata2.api.client.batch.BatchChangeSet; |
| import org.apache.olingo.odata2.api.client.batch.BatchChangeSetPart; |
| import org.apache.olingo.odata2.api.client.batch.BatchPart; |
| import org.apache.olingo.odata2.api.client.batch.BatchQueryPart; |
| import org.apache.olingo.odata2.api.ep.EntityProviderBatchProperties; |
| import org.apache.olingo.odata2.core.PathInfoImpl; |
| import org.apache.olingo.odata2.core.batch.v2.BatchParser; |
| import org.apache.olingo.odata2.testutil.helper.StringHelper; |
| import org.junit.Test; |
| |
| /** |
| * Test creation of a batch request with BatchRequestWriter and |
| * then parsing this request again with BatchRequestParser. |
| */ |
| public class BatchRequestTest { |
| |
| private static final String POST = "POST"; |
| private static final String GET = "GET"; |
| private static final String PUT = "PUT"; |
| private static final String BOUNDARY = "batch_123"; |
| private static final String SERVICE_ROOT = "http://localhost/odata/"; |
| |
| private EntityProviderBatchProperties parseProperties; |
| |
| public BatchRequestTest() throws URISyntaxException { |
| PathInfoImpl pathInfo = new PathInfoImpl(); |
| pathInfo.setServiceRoot(new URI(SERVICE_ROOT)); |
| parseProperties = EntityProviderBatchProperties.init().pathInfo(pathInfo).build(); |
| } |
| |
| private void checkMimeHeaders(final String requestBody) { |
| assertTrue(requestBody.contains("Content-Type: application/http")); |
| assertTrue(requestBody.contains("Content-Transfer-Encoding: binary")); |
| } |
| |
| @Test |
| public void testBatchQueryPart() throws BatchException, IOException { |
| List<BatchPart> batch = new ArrayList<BatchPart>(); |
| Map<String, String> headers = new HashMap<String, String>(); |
| headers.put("Accept", "application/json"); |
| BatchPart request = BatchQueryPart.method(GET).uri("Employees").headers(headers).build(); |
| batch.add(request); |
| |
| BatchRequestWriter writer = new BatchRequestWriter(); |
| InputStream batchRequest = writer.writeBatchRequest(batch, BOUNDARY); |
| assertNotNull(batchRequest); |
| |
| StringHelper.Stream batchRequestStream = StringHelper.toStream(batchRequest); |
| String requestBody = batchRequestStream.asString(); |
| checkMimeHeaders(requestBody); |
| |
| assertTrue(requestBody.contains("--batch_")); |
| assertTrue(requestBody.contains("GET Employees HTTP/1.1")); |
| checkHeaders(headers, requestBody); |
| |
| String contentType = "multipart/mixed; boundary=" + BOUNDARY; |
| BatchParser parser = new BatchParser(contentType, parseProperties, true); |
| List<BatchRequestPart> parseResult = parser.parseBatchRequest(batchRequestStream.asStream()); |
| assertEquals(1, parseResult.size()); |
| } |
| |
| @Test |
| public void testBatchChangeSet() throws IOException, BatchException { |
| List<BatchPart> batch = new ArrayList<BatchPart>(); |
| Map<String, String> headers = new HashMap<String, String>(); |
| headers.put("content-type", "application/json"); |
| BatchChangeSetPart request = BatchChangeSetPart.method(PUT) |
| .uri("Employees('2')") |
| .body("{\"Возраст\":40}") |
| .headers(headers) |
| .contentId("111") |
| .build(); |
| BatchChangeSet changeSet = BatchChangeSet.newBuilder().build(); |
| changeSet.add(request); |
| batch.add(changeSet); |
| |
| BatchRequestWriter writer = new BatchRequestWriter(); |
| InputStream batchRequest = writer.writeBatchRequest(batch, BOUNDARY); |
| assertNotNull(batchRequest); |
| |
| StringHelper.Stream batchRequestStream = StringHelper.toStream(batchRequest); |
| String requestBody = batchRequestStream.asString(); |
| checkMimeHeaders(requestBody); |
| checkHeaders(headers, requestBody); |
| |
| assertTrue(requestBody.contains("--batch_")); |
| assertTrue(requestBody.contains("--changeset_")); |
| assertTrue(requestBody.contains("PUT Employees('2') HTTP/1.1")); |
| assertTrue(requestBody.contains("{\"Возраст\":40}")); |
| assertEquals(15, batchRequestStream.linesCount()); |
| |
| String contentType = "multipart/mixed; boundary=" + BOUNDARY; |
| BatchParser parser = new BatchParser(contentType, parseProperties, true); |
| List<BatchRequestPart> parseResult = parser.parseBatchRequest(batchRequestStream.asStream()); |
| assertEquals(1, parseResult.size()); |
| } |
| |
| @Test |
| public void testBatchChangeSetIso() throws IOException, BatchException { |
| List<BatchPart> batch = new ArrayList<BatchPart>(); |
| Map<String, String> headers = new HashMap<String, String>(); |
| headers.put("Content-type", "application/json; charset=iso-8859-1"); |
| BatchChangeSetPart request = BatchChangeSetPart.method(PUT) |
| .uri("Employees('2')") |
| .body("{\"Name\":Wälter}") |
| .headers(headers) |
| .contentId("111") |
| .build(); |
| BatchChangeSet changeSet = BatchChangeSet.newBuilder().build(); |
| changeSet.add(request); |
| batch.add(changeSet); |
| |
| BatchRequestWriter writer = new BatchRequestWriter(); |
| InputStream batchRequest = writer.writeBatchRequest(batch, BOUNDARY); |
| assertNotNull(batchRequest); |
| |
| StringHelper.Stream batchRequestStream = StringHelper.toStream(batchRequest); |
| String requestBody = batchRequestStream.asString("iso-8859-1"); |
| checkMimeHeaders(requestBody); |
| checkHeaders(headers, requestBody); |
| |
| assertTrue(requestBody.contains("--batch_")); |
| assertTrue(requestBody.contains("--changeset_")); |
| assertTrue(requestBody.contains("PUT Employees('2') HTTP/1.1")); |
| assertTrue(requestBody.contains("Content-Length: 15")); |
| assertTrue(requestBody.contains("{\"Name\":Wälter}")); |
| assertEquals(15, batchRequestStream.linesCount()); |
| |
| String contentType = "multipart/mixed; boundary=" + BOUNDARY; |
| BatchParser parser = new BatchParser(contentType, parseProperties, true); |
| List<BatchRequestPart> parseResult = parser.parseBatchRequest(batchRequestStream.asStream()); |
| assertEquals(1, parseResult.size()); |
| } |
| |
| |
| @Test |
| public void testBatchWithGetAndPost() throws BatchException, IOException { |
| List<BatchPart> batch = new ArrayList<BatchPart>(); |
| Map<String, String> headers = new HashMap<String, String>(); |
| headers.put("Accept", "application/json"); |
| BatchPart request = BatchQueryPart.method(GET).uri("Employees").headers(headers).contentId("000").build(); |
| batch.add(request); |
| |
| Map<String, String> changeSetHeaders = new HashMap<String, String>(); |
| changeSetHeaders.put("content-type", "application/json"); |
| String body = "/9j/4AAQSkZJRgABAQEBLAEsAAD/4RM0RXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEA"; |
| BatchChangeSetPart changeRequest = BatchChangeSetPart.method(POST) |
| .uri("Employees") |
| .body(body) |
| .headers(changeSetHeaders) |
| .contentId("111") |
| .build(); |
| BatchChangeSet changeSet = BatchChangeSet.newBuilder().build(); |
| changeSet.add(changeRequest); |
| batch.add(changeSet); |
| BatchRequestWriter writer = new BatchRequestWriter(); |
| InputStream batchRequest = writer.writeBatchRequest(batch, BOUNDARY); |
| assertNotNull(batchRequest); |
| StringHelper.Stream batchRequestStream = StringHelper.toStream(batchRequest); |
| String requestBody = batchRequestStream.asString(); |
| checkMimeHeaders(requestBody); |
| |
| checkHeaders(headers, requestBody); |
| checkHeaders(changeSetHeaders, requestBody); |
| assertTrue(requestBody.contains("GET Employees HTTP/1.1")); |
| assertTrue(requestBody.contains("POST Employees HTTP/1.1")); |
| assertTrue(requestBody.contains(body)); |
| assertEquals(24, batchRequestStream.linesCount()); |
| |
| String contentType = "multipart/mixed; boundary=" + BOUNDARY; |
| BatchParser parser = new BatchParser(contentType, parseProperties, true); |
| List<BatchRequestPart> parseResult = parser.parseBatchRequest(batchRequestStream.asStream()); |
| assertEquals(2, parseResult.size()); |
| } |
| |
| @Test |
| public void testChangeSetWithContentIdReferencing() throws BatchException, IOException { |
| List<BatchPart> batch = new ArrayList<BatchPart>(); |
| |
| Map<String, String> changeSetHeaders = new HashMap<String, String>(); |
| changeSetHeaders.put("content-type", "application/json"); |
| String body = "/9j/4AAQSkZJRgABAQEBLAEsAAD/4RM0RXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEA"; |
| BatchChangeSetPart changeRequest = BatchChangeSetPart.method(POST) |
| .uri("Employees('2')") |
| .body(body) |
| .headers(changeSetHeaders) |
| .contentId("1") |
| .build(); |
| BatchChangeSet changeSet = BatchChangeSet.newBuilder().build(); |
| changeSet.add(changeRequest); |
| |
| changeSetHeaders = new HashMap<String, String>(); |
| changeSetHeaders.put("content-type", "application/json;odata=verbose"); |
| BatchChangeSetPart changeRequest2 = BatchChangeSetPart.method(PUT) |
| .uri("$/ManagerId") |
| .body("{\"ManagerId\":1}") |
| .headers(changeSetHeaders) |
| .contentId("2") |
| .build(); |
| changeSet.add(changeRequest2); |
| batch.add(changeSet); |
| |
| BatchRequestWriter writer = new BatchRequestWriter(); |
| InputStream batchRequest = writer.writeBatchRequest(batch, BOUNDARY); |
| assertNotNull(batchRequest); |
| |
| StringHelper.Stream batchRequestStream = StringHelper.toStream(batchRequest); |
| String requestBody = batchRequestStream.asString(); |
| checkMimeHeaders(requestBody); |
| |
| assertTrue(requestBody.contains("POST Employees('2') HTTP/1.1")); |
| assertTrue(requestBody.contains("PUT $/ManagerId HTTP/1.1")); |
| assertTrue(requestBody.contains(BatchHelper.HTTP_CONTENT_ID + ": 1")); |
| assertTrue(requestBody.contains(BatchHelper.HTTP_CONTENT_ID + ": 2")); |
| assertTrue(requestBody.contains(body)); |
| |
| String contentType = "multipart/mixed; boundary=" + BOUNDARY; |
| BatchParser parser = new BatchParser(contentType, parseProperties, true); |
| List<BatchRequestPart> parseResult = parser.parseBatchRequest(batchRequestStream.asStream()); |
| assertEquals(1, parseResult.size()); |
| } |
| |
| @Test |
| public void testBatchWithTwoChangeSets() throws BatchException, IOException { |
| List<BatchPart> batch = new ArrayList<BatchPart>(); |
| |
| Map<String, String> changeSetHeaders = new HashMap<String, String>(); |
| changeSetHeaders.put("content-type", "application/json"); |
| changeSetHeaders.put("content-Id", "111"); |
| String body = "/9j/4AAQSkZJRgABAQEBLAEsAAD/4RM0RXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEA"; |
| BatchChangeSetPart changeRequest = BatchChangeSetPart.method(POST) |
| .uri("Employees") |
| .contentId("111request") |
| .body(body) |
| .headers(changeSetHeaders) |
| .build(); |
| BatchChangeSet changeSet = BatchChangeSet.newBuilder().build(); |
| changeSet.add(changeRequest); |
| batch.add(changeSet); |
| |
| Map<String, String> changeSetHeaders2 = new HashMap<String, String>(); |
| changeSetHeaders2.put("content-type", "application/json;odata=verbose"); |
| changeSetHeaders2.put("content-Id", "222"); |
| BatchChangeSetPart changeRequest2 = BatchChangeSetPart.method(PUT) |
| .uri("Employees('2')/ManagerId") |
| .contentId("222request") |
| .body("{\"ManagerId\":1}") |
| .headers(changeSetHeaders2) |
| .build(); |
| BatchChangeSet changeSet2 = BatchChangeSet.newBuilder().build(); |
| changeSet2.add(changeRequest2); |
| batch.add(changeSet2); |
| |
| BatchRequestWriter writer = new BatchRequestWriter(); |
| InputStream batchRequest = writer.writeBatchRequest(batch, BOUNDARY); |
| assertNotNull(batchRequest); |
| |
| StringHelper.Stream batchRequestStream = StringHelper.toStream(batchRequest); |
| String requestBody = batchRequestStream.asString(); |
| checkMimeHeaders(requestBody); |
| |
| assertTrue(requestBody.contains("POST Employees HTTP/1.1")); |
| assertTrue(requestBody.contains("PUT Employees('2')/ManagerId HTTP/1.1")); |
| |
| assertTrue(requestBody.contains(body)); |
| |
| String contentType = "multipart/mixed; boundary=" + BOUNDARY; |
| BatchParser parser = new BatchParser(contentType, parseProperties, true); |
| List<BatchRequestPart> parseResult = parser.parseBatchRequest(batchRequestStream.asStream()); |
| assertEquals(2, parseResult.size()); |
| } |
| |
| private void checkHeaders(final Map<String, String> headers, final String requestBody) { |
| for (Map.Entry<String, String> header : headers.entrySet()) { |
| assertTrue(requestBody.contains(header.getKey() + ": " + header.getValue())); |
| } |
| } |
| |
| @Test(expected = IllegalArgumentException.class) |
| public void testBatchQueryPartWithInvalidMethod() throws BatchException, IOException { |
| BatchQueryPart.method(PUT).uri("Employees").build(); |
| |
| } |
| |
| @Test(expected = IllegalArgumentException.class) |
| public void testBatchChangeSetPartWithInvalidMethod() throws BatchException, IOException { |
| BatchChangeSetPart.method(GET).uri("Employees('2')").build(); |
| |
| } |
| |
| @Test |
| public void testBatchChangeSetRawBytes() throws IOException, BatchException { |
| List<BatchPart> batch = new ArrayList<BatchPart>(); |
| Map<String, String> headers = new HashMap<String, String>(); |
| headers.put("content-type", "application/octect-stream"); |
| byte[] data = getRawBytes(); |
| BatchChangeSetPart request = BatchChangeSetPart.method(PUT) |
| .uri("Employees('2')/$value") |
| .body(data) |
| .headers(headers) |
| .build(); |
| BatchChangeSet changeSet = BatchChangeSet.newBuilder().build(); |
| changeSet.add(request); |
| batch.add(changeSet); |
| |
| BatchRequestWriter writer = new BatchRequestWriter(); |
| InputStream batchRequest = writer.writeBatchRequest(batch, BOUNDARY); |
| assertNotNull(batchRequest); |
| |
| StringHelper.Stream batchRequestStream = StringHelper.toStream(batchRequest); |
| String requestBody = batchRequestStream.asString("ISO-8859-1"); |
| checkMimeHeaders(requestBody); |
| checkHeaders(headers, requestBody); |
| |
| assertTrue(requestBody.contains("--batch_")); |
| assertTrue(requestBody.contains("--changeset_")); |
| assertTrue(requestBody.contains("PUT Employees('2')/$value HTTP/1.1")); |
| |
| String contentType = "multipart/mixed; boundary=" + BOUNDARY; |
| BatchParser parser = new BatchParser(contentType, parseProperties, true); |
| List<BatchRequestPart> parseResult = parser.parseBatchRequest(batchRequestStream.asStream()); |
| assertEquals(1, parseResult.size()); |
| InputStream in = parseResult.get(0).getRequests().get(0).getBody(); |
| StringHelper.Stream parsedReqStream = StringHelper.toStream(in); |
| String parsedReqData = parsedReqStream.asString("ISO-8859-1"); |
| assertArrayEquals(data, parsedReqData.getBytes("ISO-8859-1")); |
| } |
| |
| private byte[] getRawBytes() { |
| byte[] data = new byte[Byte.MAX_VALUE - Byte.MIN_VALUE + 1]; |
| // binary content, not a valid UTF-8 representation of a string |
| for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) { |
| data[i - Byte.MIN_VALUE] = (byte) i; |
| } |
| return data; |
| } |
| } |