http://git-wip-us.apache.org/repos/asf/camel/blob/e6eded4c/components/camel-olingo4/camel-olingo4-api/src/main/resources/META-INF/LICENSE.txt
----------------------------------------------------------------------
diff --git 
a/components/camel-olingo4/camel-olingo4-api/src/main/resources/META-INF/LICENSE.txt
 
b/components/camel-olingo4/camel-olingo4-api/src/main/resources/META-INF/LICENSE.txt
new file mode 100644
index 0000000..6b0b127
--- /dev/null
+++ 
b/components/camel-olingo4/camel-olingo4-api/src/main/resources/META-INF/LICENSE.txt
@@ -0,0 +1,203 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
+

http://git-wip-us.apache.org/repos/asf/camel/blob/e6eded4c/components/camel-olingo4/camel-olingo4-api/src/main/resources/META-INF/NOTICE.txt
----------------------------------------------------------------------
diff --git 
a/components/camel-olingo4/camel-olingo4-api/src/main/resources/META-INF/NOTICE.txt
 
b/components/camel-olingo4/camel-olingo4-api/src/main/resources/META-INF/NOTICE.txt
new file mode 100644
index 0000000..2e215bf
--- /dev/null
+++ 
b/components/camel-olingo4/camel-olingo4-api/src/main/resources/META-INF/NOTICE.txt
@@ -0,0 +1,11 @@
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Apache Camel distribution.                    ==
+   =========================================================================
+
+   This product includes software developed by
+   The Apache Software Foundation (http://www.apache.org/).
+
+   Please read the different LICENSE files present in the licenses directory of
+   this distribution.

http://git-wip-us.apache.org/repos/asf/camel/blob/e6eded4c/components/camel-olingo4/camel-olingo4-api/src/test/java/org/apache/camel/component/olingo4/Olingo4AppAPITest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-olingo4/camel-olingo4-api/src/test/java/org/apache/camel/component/olingo4/Olingo4AppAPITest.java
 
b/components/camel-olingo4/camel-olingo4-api/src/test/java/org/apache/camel/component/olingo4/Olingo4AppAPITest.java
new file mode 100644
index 0000000..6cfe3e9
--- /dev/null
+++ 
b/components/camel-olingo4/camel-olingo4-api/src/test/java/org/apache/camel/component/olingo4/Olingo4AppAPITest.java
@@ -0,0 +1,543 @@
+/**
+ * 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.camel.component.olingo4;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.component.olingo4.api.Olingo4App;
+import org.apache.camel.component.olingo4.api.Olingo4ResponseHandler;
+import org.apache.camel.component.olingo4.api.batch.Olingo4BatchChangeRequest;
+import org.apache.camel.component.olingo4.api.batch.Olingo4BatchQueryRequest;
+import org.apache.camel.component.olingo4.api.batch.Olingo4BatchRequest;
+import org.apache.camel.component.olingo4.api.batch.Olingo4BatchResponse;
+import org.apache.camel.component.olingo4.api.batch.Operation;
+import org.apache.camel.component.olingo4.api.impl.Olingo4AppImpl;
+import org.apache.http.HttpHost;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.protocol.BasicHttpContext;
+import org.apache.http.protocol.ExecutionContext;
+import org.apache.http.protocol.HttpContext;
+import org.apache.olingo.client.api.ODataClient;
+import org.apache.olingo.client.api.domain.ClientCollectionValue;
+import org.apache.olingo.client.api.domain.ClientComplexValue;
+import org.apache.olingo.client.api.domain.ClientEntity;
+import org.apache.olingo.client.api.domain.ClientEntitySet;
+import org.apache.olingo.client.api.domain.ClientEnumValue;
+import org.apache.olingo.client.api.domain.ClientObjectFactory;
+import org.apache.olingo.client.api.domain.ClientPrimitiveValue;
+import org.apache.olingo.client.api.domain.ClientProperty;
+import org.apache.olingo.client.api.domain.ClientServiceDocument;
+import org.apache.olingo.client.api.domain.ClientValue;
+import org.apache.olingo.client.api.serialization.ODataReader;
+import org.apache.olingo.client.core.ODataClientFactory;
+import org.apache.olingo.commons.api.Constants;
+import org.apache.olingo.commons.api.edm.Edm;
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.server.api.uri.queryoption.SystemQueryOptionKind;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.junit.Assert.*;
+
+/**
+ * Integration test for
+ * {@link org.apache.camel.component.olingo4.api.impl.Olingo4AppImpl} using the
+ * sample OData 4.0 remote TripPin service published on
+ * http://services.odata.org/TripPinRESTierService.
+ */
+public class Olingo4AppAPITest {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(Olingo4AppAPITest.class);
+    private static final long TIMEOUT = 10;
+
+    private static final String PEOPLE = "People";
+    private static final String TEST_PEOPLE = "People('russellwhyte')";
+    private static final String TEST_AIRLINE = "Airlines('FM')";
+    private static final String TRIPS = "Trips";
+    private static final String TEST_CREATE_RESOURCE_CONTENT_ID = "1";
+    private static final String TEST_UPDATE_RESOURCE_CONTENT_ID = "2";
+    private static final String TEST_CREATE_KEY = "'lewisblack'";
+    private static final String TEST_CREATE_PEOPLE = PEOPLE + "(" + 
TEST_CREATE_KEY + ")";
+    private static final String TEST_AIRPORT = "Airports('KSFO')";
+    private static final String TEST_AIRPORTS_SIMPLE_PROPERTY = TEST_AIRPORT + 
"/Name";
+    private static final String TEST_AIRPORTS_COMPLEX_PROPERTY = TEST_AIRPORT 
+ "/Location";
+    private static final String TEST_AIRPORTS_SIMPLE_PROPERTY_VALUE = 
TEST_AIRPORTS_SIMPLE_PROPERTY + "/$value";
+    private static final String COUNT_OPTION = "/$count";
+
+    private static final String TEST_SERVICE_BASE_URL = 
"http://services.odata.org/TripPinRESTierService";;
+    private static final ContentType TEST_FORMAT = 
ContentType.APPLICATION_JSON;
+    private static final String TEST_FORMAT_STRING = TEST_FORMAT.toString();
+
+    private static Olingo4App olingoApp;
+    private static Edm edm;
+    private final ODataClient odataClient = ODataClientFactory.getClient();
+    private final ClientObjectFactory objFactory = 
odataClient.getObjectFactory();
+    private final ODataReader reader = odataClient.getReader();
+
+    @BeforeClass
+    public static void beforeClass() throws Exception {
+        setupClient();
+    }
+
+    @AfterClass
+    public static void afterClass() throws Exception {
+        if (olingoApp != null) {
+            olingoApp.close();
+        }
+    }
+
+    protected static void setupClient() throws Exception {
+        olingoApp = new 
Olingo4AppImpl(getRealServiceUrl(TEST_SERVICE_BASE_URL));
+        olingoApp.setContentType(TEST_FORMAT_STRING);
+
+        LOG.info("Read Edm ");
+        final TestOlingo4ResponseHandler<Edm> responseHandler = new 
TestOlingo4ResponseHandler<Edm>();
+
+        olingoApp.read(null, Constants.METADATA, null, responseHandler);
+
+        edm = responseHandler.await();
+        LOG.info("Read default EntityContainer:  {}", 
responseHandler.await().getEntityContainer().getName());
+    }
+
+    /*
+     * Every request to the demo OData 4.0
+     * (http://services.odata.org/TripPinRESTierService) generates unique
+     * service URL with postfix like (S(tuivu3up5ygvjzo5fszvnwfv)) for each
+     * session This method makes reuest to the base URL and return URL with
+     * generated postfix
+     */
+    @SuppressWarnings("deprecation")
+    protected static String getRealServiceUrl(String baseUrl) throws 
ClientProtocolException, IOException {
+        CloseableHttpClient httpclient = HttpClients.createDefault();
+        HttpGet httpGet = new HttpGet(baseUrl);
+        HttpContext httpContext = new BasicHttpContext();
+        httpclient.execute(httpGet, httpContext);
+        HttpUriRequest currentReq = 
(HttpUriRequest)httpContext.getAttribute(ExecutionContext.HTTP_REQUEST);
+        HttpHost currentHost = 
(HttpHost)httpContext.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
+        String currentUrl = (currentReq.getURI().isAbsolute()) ? 
currentReq.getURI().toString() : (currentHost.toURI() + currentReq.getURI());
+
+        return currentUrl;
+    }
+
+    @Test
+    public void testServiceDocument() throws Exception {
+        final TestOlingo4ResponseHandler<ClientServiceDocument> 
responseHandler = new TestOlingo4ResponseHandler<ClientServiceDocument>();
+
+        olingoApp.read(null, "", null, responseHandler);
+        final ClientServiceDocument serviceDocument = responseHandler.await();
+
+        final Map<String, URI> entitySets = serviceDocument.getEntitySets();
+        assertEquals("Service Entity Sets", 4, entitySets.size());
+        LOG.info("Service Document Entries:  {}", entitySets);
+    }
+
+    @Test
+    public void testReadEntitySet() throws Exception {
+        final TestOlingo4ResponseHandler<ClientEntitySet> responseHandler = 
new TestOlingo4ResponseHandler<ClientEntitySet>();
+
+        olingoApp.read(edm, PEOPLE, null, responseHandler);
+
+        final ClientEntitySet entitySet = responseHandler.await();
+        assertNotNull(entitySet);
+        assertEquals("Entity set count", 20, entitySet.getEntities().size());
+        LOG.info("Entities:  {}", prettyPrint(entitySet));
+    }
+
+    @Test
+    public void testReadUnparsedEntitySet() throws Exception {
+        final TestOlingo4ResponseHandler<InputStream> responseHandler = new 
TestOlingo4ResponseHandler<InputStream>();
+
+        olingoApp.uread(edm, PEOPLE, null, responseHandler);
+
+        final InputStream rawEntitySet = responseHandler.await();
+        assertNotNull("Data entity set", rawEntitySet);
+        final ClientEntitySet entitySet = reader.readEntitySet(rawEntitySet, 
TEST_FORMAT);
+        assertEquals("Entity set count", 20, entitySet.getEntities().size());
+        LOG.info("Entries:  {}", prettyPrint(entitySet));
+    }
+
+    @Test
+    public void testReadEntity() throws Exception {
+        final TestOlingo4ResponseHandler<ClientEntity> responseHandler = new 
TestOlingo4ResponseHandler<ClientEntity>();
+
+        olingoApp.read(edm, TEST_AIRLINE, null, responseHandler);
+        ClientEntity entity = responseHandler.await();
+        assertEquals("Shanghai Airline", 
entity.getProperty("Name").getValue().toString());
+        LOG.info("Single Entity:  {}", prettyPrint(entity));
+
+        responseHandler.reset();
+
+        olingoApp.read(edm, TEST_PEOPLE, null, responseHandler);
+        entity = responseHandler.await();
+        assertEquals("Russell", 
entity.getProperty("FirstName").getValue().toString());
+        LOG.info("Single Entry:  {}", prettyPrint(entity));
+
+        responseHandler.reset();
+        final Map<String, String> queryParams = new HashMap<String, String>();
+        queryParams.put(SystemQueryOptionKind.EXPAND.toString(), TRIPS);
+
+        olingoApp.read(edm, TEST_PEOPLE, queryParams, responseHandler);
+        ClientEntity entityExpanded = responseHandler.await();
+        LOG.info("Single People Entiry with expanded Trips relation:  {}", 
prettyPrint(entityExpanded));
+    }
+
+    @Test
+    public void testReadUnparsedEntity() throws Exception {
+        final TestOlingo4ResponseHandler<InputStream> responseHandler = new 
TestOlingo4ResponseHandler<InputStream>();
+
+        olingoApp.uread(edm, TEST_AIRLINE, null, responseHandler);
+        InputStream rawEntity = responseHandler.await();
+        assertNotNull("Data entity", rawEntity);
+        ClientEntity entity = reader.readEntity(rawEntity, TEST_FORMAT);
+        assertEquals("Shanghai Airline", 
entity.getProperty("Name").getValue().toString());
+        LOG.info("Single Entity:  {}", prettyPrint(entity));
+
+        responseHandler.reset();
+
+        olingoApp.uread(edm, TEST_PEOPLE, null, responseHandler);
+        rawEntity = responseHandler.await();
+        entity = reader.readEntity(rawEntity, TEST_FORMAT);
+        assertEquals("Russell", 
entity.getProperty("FirstName").getValue().toString());
+        LOG.info("Single Entity:  {}", prettyPrint(entity));
+
+        responseHandler.reset();
+        final Map<String, String> queryParams = new HashMap<String, String>();
+        queryParams.put(SystemQueryOptionKind.EXPAND.toString(), TRIPS);
+
+        olingoApp.uread(edm, TEST_PEOPLE, queryParams, responseHandler);
+
+        rawEntity = responseHandler.await();
+        entity = reader.readEntity(rawEntity, TEST_FORMAT);
+        LOG.info("Single People Entiry with expanded Trips relation:  {}", 
prettyPrint(entity));
+    }
+
+    @Test
+    public void testReadUpdateProperties() throws Exception {
+        // test simple property Airports.Name
+        final TestOlingo4ResponseHandler<ClientPrimitiveValue> propertyHandler 
= new TestOlingo4ResponseHandler<ClientPrimitiveValue>();
+
+        olingoApp.read(edm, TEST_AIRPORTS_SIMPLE_PROPERTY, null, 
propertyHandler);
+
+        ClientPrimitiveValue name = 
(ClientPrimitiveValue)propertyHandler.await();
+        assertEquals("San Francisco International Airport", name.toString());
+        LOG.info("Airport name property value {}", 
name.asPrimitive().toString());
+
+        final TestOlingo4ResponseHandler<ClientPrimitiveValue> valueHandler = 
new TestOlingo4ResponseHandler<ClientPrimitiveValue>();
+
+        olingoApp.read(edm, TEST_AIRPORTS_SIMPLE_PROPERTY_VALUE, null, 
valueHandler);
+        ClientPrimitiveValue nameValue = valueHandler.await();
+        assertEquals("San Francisco International Airport", name.toString());
+        LOG.info("Airport name property value {}", nameValue.toString());
+
+        TestOlingo4ResponseHandler<HttpStatusCode> statusHandler = new 
TestOlingo4ResponseHandler<HttpStatusCode>();
+        // All properties updates (simple and complex) are performing through
+        // ClientEntity object
+        ClientEntity clientEntity = objFactory.newEntity(null);
+        
clientEntity.getProperties().add(objFactory.newPrimitiveProperty("MiddleName", 
objFactory.newPrimitiveValueBuilder().buildString("Middle")));
+        olingoApp.update(edm, TEST_PEOPLE, clientEntity, statusHandler);
+        HttpStatusCode statusCode = statusHandler.await();
+        assertEquals(HttpStatusCode.NO_CONTENT, statusCode);
+        LOG.info("Name property updated with status {}", 
statusCode.getStatusCode());
+
+        // Check for updated property by reading entire entity
+        final TestOlingo4ResponseHandler<ClientEntity> responseHandler = new 
TestOlingo4ResponseHandler<ClientEntity>();
+
+        olingoApp.read(edm, TEST_PEOPLE, null, responseHandler);
+        ClientEntity entity = responseHandler.await();
+        assertEquals("Middle", 
entity.getProperty("MiddleName").getValue().toString());
+        LOG.info("Updated Single Entity:  {}", prettyPrint(entity));
+    }
+
+    @Test
+    public void testReadCount() throws Exception {
+        final TestOlingo4ResponseHandler<Long> countHandler = new 
TestOlingo4ResponseHandler<Long>();
+
+        olingoApp.read(edm, PEOPLE + COUNT_OPTION, null, countHandler);
+        Long count = countHandler.await();
+        assertEquals(20, count.intValue());
+        LOG.info("People count: {}", count);
+    }
+
+    @Test
+    public void testCreateUpdateDeleteEntity() throws Exception {
+
+        // create an entity to update
+        final TestOlingo4ResponseHandler<ClientEntity> entryHandler = new 
TestOlingo4ResponseHandler<ClientEntity>();
+
+        olingoApp.create(edm, PEOPLE, createEntity(), entryHandler);
+
+        ClientEntity createdEntity = entryHandler.await();
+        LOG.info("Created Entity:  {}", prettyPrint(createdEntity));
+
+        final TestOlingo4ResponseHandler<HttpStatusCode> statusHandler = new 
TestOlingo4ResponseHandler<HttpStatusCode>();
+        ClientEntity updateEntity = createEntity();
+        
updateEntity.getProperties().add(objFactory.newPrimitiveProperty("MiddleName", 
objFactory.newPrimitiveValueBuilder().buildString("Middle")));
+        olingoApp.update(edm, TEST_CREATE_PEOPLE, updateEntity, statusHandler);
+        statusHandler.await();
+
+        statusHandler.reset();
+        updateEntity = createEntity();
+        
updateEntity.getProperties().add(objFactory.newPrimitiveProperty("MiddleName", 
objFactory.newPrimitiveValueBuilder().buildString("Middle Patched")));
+        olingoApp.patch(edm, TEST_CREATE_PEOPLE, updateEntity, statusHandler);
+        statusHandler.await();
+
+        entryHandler.reset();
+        olingoApp.read(edm, TEST_CREATE_PEOPLE, null, entryHandler);
+        ClientEntity updatedEntity = entryHandler.await();
+        LOG.info("Updated Entity successfully:  {}", 
prettyPrint(updatedEntity));
+
+        statusHandler.reset();
+        olingoApp.delete(TEST_CREATE_PEOPLE, statusHandler);
+        HttpStatusCode statusCode = statusHandler.await();
+        LOG.info("Deletion of Entity was successful:  {}: {}", 
statusCode.getStatusCode(), statusCode.getInfo());
+
+        try {
+            LOG.info("Verify Delete Entity");
+
+            entryHandler.reset();
+            olingoApp.read(edm, TEST_CREATE_PEOPLE, null, entryHandler);
+
+            entryHandler.await();
+            fail("Entity not deleted!");
+        } catch (Exception e) {
+            LOG.info("Deleted entity not found: {}", e.getMessage());
+        }
+    }
+
+    @Test
+    public void testBatchRequest() throws Exception {
+
+        final List<Olingo4BatchRequest> batchParts = new 
ArrayList<Olingo4BatchRequest>();
+
+        // 1. Edm query
+        
batchParts.add(Olingo4BatchQueryRequest.resourcePath(Constants.METADATA).resourceUri(TEST_SERVICE_BASE_URL).build());
+
+        // 2. Query entity set
+        
batchParts.add(Olingo4BatchQueryRequest.resourcePath(PEOPLE).resourceUri(TEST_SERVICE_BASE_URL).build());
+
+        // 3. Read entity
+        
batchParts.add(Olingo4BatchQueryRequest.resourcePath(TEST_PEOPLE).resourceUri(TEST_SERVICE_BASE_URL).build());
+
+        // 4. Read with expand
+        final HashMap<String, String> queryParams = new HashMap<String, 
String>();
+        queryParams.put(SystemQueryOptionKind.EXPAND.toString(), TRIPS);
+        
batchParts.add(Olingo4BatchQueryRequest.resourcePath(TEST_PEOPLE).queryParams(queryParams).resourceUri(TEST_SERVICE_BASE_URL).build());
+
+        // 5. Create entity
+        final ClientEntity clientEntity = createEntity();
+        
batchParts.add(Olingo4BatchChangeRequest.resourcePath(PEOPLE).resourceUri(TEST_SERVICE_BASE_URL).contentId(TEST_CREATE_RESOURCE_CONTENT_ID).operation(Operation.CREATE)
+            .body(clientEntity).build());
+
+        // 6. Update entity
+        
clientEntity.getProperties().add(objFactory.newPrimitiveProperty("MiddleName", 
objFactory.newPrimitiveValueBuilder().buildString("Lewis")));
+        
batchParts.add(Olingo4BatchChangeRequest.resourcePath(TEST_CREATE_PEOPLE).resourceUri(TEST_SERVICE_BASE_URL).contentId(TEST_UPDATE_RESOURCE_CONTENT_ID)
+            .operation(Operation.UPDATE).body(clientEntity).build());
+
+        // 7. Delete entity
+        
batchParts.add(Olingo4BatchChangeRequest.resourcePath(TEST_CREATE_PEOPLE).resourceUri(TEST_SERVICE_BASE_URL).operation(Operation.DELETE).build());
+
+        // 8. Read to verify entity delete
+        
batchParts.add(Olingo4BatchQueryRequest.resourcePath(TEST_CREATE_PEOPLE).resourceUri(TEST_SERVICE_BASE_URL).build());
+
+        final TestOlingo4ResponseHandler<List<Olingo4BatchResponse>> 
responseHandler = new TestOlingo4ResponseHandler<List<Olingo4BatchResponse>>();
+        olingoApp.batch(edm, batchParts, responseHandler);
+
+        final List<Olingo4BatchResponse> responseParts = 
responseHandler.await(15, TimeUnit.MINUTES);
+        assertEquals("Batch responses expected", 8, responseParts.size());
+
+        assertNotNull(responseParts.get(0).getBody());
+
+        final ClientEntitySet clientEntitySet = 
(ClientEntitySet)responseParts.get(1).getBody();
+        assertNotNull(clientEntitySet);
+        LOG.info("Batch entity set:  {}", prettyPrint(clientEntitySet));
+
+        ClientEntity returnClientEntity = 
(ClientEntity)responseParts.get(2).getBody();
+        assertNotNull(returnClientEntity);
+        LOG.info("Batch read entity:  {}", prettyPrint(returnClientEntity));
+
+        returnClientEntity = (ClientEntity)responseParts.get(3).getBody();
+        assertNotNull(returnClientEntity);
+        LOG.info("Batch read entity with expand:  {}", 
prettyPrint(returnClientEntity));
+
+        ClientEntity createdClientEntity = 
(ClientEntity)responseParts.get(4).getBody();
+        assertNotNull(createdClientEntity);
+        assertEquals(TEST_CREATE_RESOURCE_CONTENT_ID, 
responseParts.get(4).getContentId());
+        LOG.info("Batch created entity:  {}", prettyPrint(returnClientEntity));
+
+        assertEquals(HttpStatusCode.NO_CONTENT.getStatusCode(), 
responseParts.get(5).getStatusCode());
+        assertEquals(TEST_UPDATE_RESOURCE_CONTENT_ID, 
responseParts.get(5).getContentId());
+        assertEquals(HttpStatusCode.NO_CONTENT.getStatusCode(), 
responseParts.get(6).getStatusCode());
+        assertEquals(HttpStatusCode.NOT_FOUND.getStatusCode(), 
responseParts.get(7).getStatusCode());
+    }
+
+    private ClientEntity createEntity() {
+        ClientEntity clientEntity = objFactory.newEntity(null);
+
+        
clientEntity.getProperties().add(objFactory.newPrimitiveProperty("UserName", 
objFactory.newPrimitiveValueBuilder().buildString("lewisblack")));
+        
clientEntity.getProperties().add(objFactory.newPrimitiveProperty("FirstName", 
objFactory.newPrimitiveValueBuilder().buildString("Lewis")));
+        
clientEntity.getProperties().add(objFactory.newPrimitiveProperty("LastName", 
objFactory.newPrimitiveValueBuilder().buildString("Black")));
+
+        return clientEntity;
+    }
+
+    private static String prettyPrint(ClientEntitySet entitySet) {
+        StringBuilder builder = new StringBuilder();
+        builder.append("[\n");
+        for (ClientEntity entity : entitySet.getEntities()) {
+            builder.append(prettyPrint(entity.getProperties(), 
1)).append('\n');
+        }
+        builder.append("]\n");
+        return builder.toString();
+    }
+
+    private static String prettyPrint(ClientEntity entity) {
+        return prettyPrint(entity.getProperties(), 0);
+    }
+
+    @SuppressWarnings("unchecked")
+    private static String prettyPrint(Map<String, Object> properties, int 
level) {
+        StringBuilder b = new StringBuilder();
+        Set<Entry<String, Object>> entries = properties.entrySet();
+
+        for (Entry<String, Object> entry : entries) {
+            intend(b, level);
+            b.append(entry.getKey()).append(": ");
+            Object value = entry.getValue();
+            if (value instanceof Map) {
+                value = prettyPrint((Map<String, Object>)value, level + 1);
+            } else if (value instanceof Calendar) {
+                Calendar cal = (Calendar)value;
+                value = SimpleDateFormat.getInstance().format(cal.getTime());
+            }
+            b.append(value).append("\n");
+        }
+        // remove last line break
+        b.deleteCharAt(b.length() - 1);
+        return b.toString();
+    }
+
+    private static String prettyPrint(Collection<ClientProperty> properties, 
int level) {
+        StringBuilder b = new StringBuilder();
+
+        for (Object property : properties) {
+            intend(b, level);
+            if (property instanceof ClientProperty) {
+                ClientProperty entry = (ClientProperty)property;
+                ClientValue value = entry.getValue();
+                if (value.isCollection()) {
+                    ClientCollectionValue cclvalue = value.asCollection();
+                    b.append(entry.getName()).append(": ");
+                    b.append(prettyPrint(cclvalue.asJavaCollection(), level + 
1));
+                } else if (value.isComplex()) {
+                    ClientComplexValue cpxvalue = value.asComplex();
+                    b.append(prettyPrint(cpxvalue.asJavaMap(), level + 1));
+                } else if (value.isEnum()) {
+                    ClientEnumValue cnmvalue = value.asEnum();
+                    b.append(entry.getName()).append(": ");
+                    b.append(cnmvalue.getValue()).append("\n");
+                } else if (value.isPrimitive()) {
+                    b.append(entry.getName()).append(": ");
+                    b.append(entry.getValue()).append("\n");
+                }
+            } else {
+                b.append(property.toString()).append("\n");
+            }
+
+        }
+        return b.toString();
+    }
+
+    private static void intend(StringBuilder builder, int intendLevel) {
+        for (int i = 0; i < intendLevel; i++) {
+            builder.append("  ");
+        }
+    }
+
+    private static final class TestOlingo4ResponseHandler<T> implements 
Olingo4ResponseHandler<T> {
+        private T response;
+        private Exception error;
+        private CountDownLatch latch = new CountDownLatch(1);
+
+        @Override
+        public void onResponse(T response) {
+            this.response = response;
+            if (LOG.isDebugEnabled()) {
+                if (response instanceof ClientEntitySet) {
+                    LOG.debug("Received response: {}", 
prettyPrint((ClientEntitySet)response));
+                } else if (response instanceof ClientEntity) {
+                    LOG.debug("Received response: {}", 
prettyPrint((ClientEntity)response));
+                } else {
+                    LOG.debug("Received response: {}", response);
+                }
+            }
+            latch.countDown();
+        }
+
+        @Override
+        public void onException(Exception ex) {
+            error = ex;
+            latch.countDown();
+        }
+
+        @Override
+        public void onCanceled() {
+            error = new IllegalStateException("Request Canceled");
+            latch.countDown();
+        }
+
+        public T await() throws Exception {
+            return await(TIMEOUT, TimeUnit.SECONDS);
+        }
+
+        public T await(long timeout, TimeUnit unit) throws Exception {
+            assertTrue("Timeout waiting for response", latch.await(timeout, 
unit));
+            if (error != null) {
+                throw error;
+            }
+            assertNotNull("Response", response);
+            return response;
+        }
+
+        public void reset() {
+            latch.countDown();
+            latch = new CountDownLatch(1);
+            response = null;
+            error = null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/e6eded4c/components/camel-olingo4/camel-olingo4-api/src/test/resources/log4j2.properties
----------------------------------------------------------------------
diff --git 
a/components/camel-olingo4/camel-olingo4-api/src/test/resources/log4j2.properties
 
b/components/camel-olingo4/camel-olingo4-api/src/test/resources/log4j2.properties
new file mode 100644
index 0000000..46bf0df
--- /dev/null
+++ 
b/components/camel-olingo4/camel-olingo4-api/src/test/resources/log4j2.properties
@@ -0,0 +1,28 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+appender.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-olingo4-test.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+appender.out.type = Console
+appender.out.name = out
+appender.out.layout.type = PatternLayout
+appender.out.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+rootLogger.level = INFO
+rootLogger.appenderRef.file.ref = file

http://git-wip-us.apache.org/repos/asf/camel/blob/e6eded4c/components/camel-olingo4/camel-olingo4-component/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-olingo4/camel-olingo4-component/pom.xml 
b/components/camel-olingo4/camel-olingo4-component/pom.xml
new file mode 100644
index 0000000..6c9c988
--- /dev/null
+++ b/components/camel-olingo4/camel-olingo4-component/pom.xml
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd"; 
xmlns="http://maven.apache.org/POM/4.0.0";
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>camel-olingo4-parent</artifactId>
+    <version>2.19.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>camel-olingo4</artifactId>
+  <name>Camel :: Olingo4 :: Component</name>
+  <description>Camel Olingo4 component</description>
+  <properties>
+    <componentName>Olingo4</componentName>
+    <schemeName>olingo4</schemeName>
+    <maven.exe.file.extension></maven.exe.file.extension>
+    <camel.osgi.export.pkg>${componentPackage}</camel.osgi.export.pkg>
+    <componentPackage>org.apache.camel.component.olingo4</componentPackage>
+    <outPackage>org.apache.camel.component.olingo4.internal</outPackage>
+    <camel.osgi.private.pkg>${outPackage}</camel.osgi.private.pkg>
+  </properties>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-olingo4-api</artifactId>
+       <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.olingo</groupId>
+      <artifactId>odata-client-api</artifactId>
+      <version>${olingo4-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.olingo</groupId>
+      <artifactId>odata-client-core</artifactId>
+      <version>${olingo4-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.olingo</groupId>
+      <artifactId>odata-commons-api</artifactId>
+      <version>${olingo4-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+      <version>${commons-lang-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>spi-annotations</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-olingo4-api</artifactId>
+      <classifier>javadoc</classifier>
+      <version>${project.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-slf4j-impl</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-test</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+  <repositories>
+    <repository>
+      <id>redhat-ga-repository</id>
+      <url>https://maven.repository.redhat.com/ga</url>
+    </repository>
+  </repositories>
+  <pluginRepositories>
+    <pluginRepository>
+      <id>redhat-ga-repository</id>
+      <url>https://maven.repository.redhat.com/ga</url>
+    </pluginRepository>
+  </pluginRepositories>
+  <build>
+    <defaultGoal>install</defaultGoal>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.camel</groupId>
+          <artifactId>camel-api-component-maven-plugin</artifactId>
+          <configuration>
+            <scheme>${schemeName}</scheme>
+            <componentName>${componentName}</componentName>
+            <componentPackage>${componentPackage}</componentPackage>
+            <outPackage>${outPackage}</outPackage>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-api-component-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>generate-test-component-classes</id>
+            <goals>
+              <goal>fromApis</goal>
+            </goals>
+            <configuration>
+              <apis>
+                <api>
+                  <apiName />
+                  
<proxyClass>org.apache.camel.component.olingo4.api.Olingo4App</proxyClass>
+                  
<fromSignatureFile>src/signatures/olingo-api-signature.txt</fromSignatureFile>
+                  <excludeConfigNames>edm|responseHandler</excludeConfigNames>
+                  <extraOptions>
+                    <extraOption>
+                      <name>keyPredicate</name>
+                      <type>java.lang.String</type>
+                    </extraOption>
+                  </extraOptions>
+                  <nullableOptions>
+                    <nullableOption>queryParams</nullableOption>
+                  </nullableOptions>
+                </api>
+              </apis>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>add-generated-sources</id>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                
<source>${project.build.directory}/generated-sources/camel-component</source>
+              </sources>
+            </configuration>
+          </execution>
+          <execution>
+            <id>add-generated-test-sources</id>
+            <goals>
+              <goal>add-test-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                
<source>${project.build.directory}/generated-test-sources/camel-component</source>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <reporting>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-api-component-maven-plugin</artifactId>
+        <version>${project.version}</version>
+        <configuration>
+          <scheme>${schemeName}</scheme>
+          <componentName>${componentName}</componentName>
+          <componentPackage>${componentPackage}</componentPackage>
+          <outPackage>${outPackage}</outPackage>
+        </configuration>
+      </plugin>
+    </plugins>
+  </reporting>
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/e6eded4c/components/camel-olingo4/camel-olingo4-component/src/main/docs/olingo4-component.adoc
----------------------------------------------------------------------
diff --git 
a/components/camel-olingo4/camel-olingo4-component/src/main/docs/olingo4-component.adoc
 
b/components/camel-olingo4/camel-olingo4-component/src/main/docs/olingo4-component.adoc
new file mode 100644
index 0000000..e9cfb97
--- /dev/null
+++ 
b/components/camel-olingo4/camel-olingo4-component/src/main/docs/olingo4-component.adoc
@@ -0,0 +1,252 @@
+## Olingo4 Component
+
+*Available as of Camel version 2.19.0*
+
+The Olingo2 component utilizes http://olingo.apache.org/[Apache Olingo]
+version 2.0 APIs to interact with OData 2.0 and 3.0 compliant services.
+A number of popular commercial and enterprise vendors and products
+support the OData protocol. A sample list of supporting products can be
+found on the OData http://www.odata.org/ecosystem/[website].
+
+The Olingo2 component supports reading feeds, delta feeds, entities,
+simple and complex properties, links, counts, using custom and OData
+system query parameters. It supports updating entities, properties, and
+association links. It also supports submitting queries and change
+requests as a single OData batch operation. 
+
+The component supports configuring HTTP connection parameters and
+headers for OData service connection. This allows configuring use of
+SSL, OAuth2.0, etc. as required by the target OData service. 
+
+Maven users will need to add the following dependency to their pom.xml
+for this component:
+
+[source,java]
+----------------------------------------------
+    <dependency>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-olingo2</artifactId>
+        <version>${camel-version}</version>
+    </dependency>
+----------------------------------------------
+
+### URI format
+
+[source,java]
+------------------------------------------------
+    olingo2://endpoint/<resource-path>?[options]
+------------------------------------------------
+
+### Olingo2 Options
+
+
+
+
+// component options: START
+The Olingo4 component supports 1 options which are listed below.
+
+
+
+{% raw %}
+[width="100%",cols="2,1,1m,1m,5",options="header"]
+|=======================================================================
+| Name | Group | Default | Java Type | Description
+| configuration | common |  | Olingo4Configuration | To use the shared 
configuration
+|=======================================================================
+{% endraw %}
+// component options: END
+
+
+
+
+
+
+// endpoint options: START
+The Olingo4 component supports 16 endpoint options which are listed below:
+
+{% raw %}
+[width="100%",cols="2,1,1m,1m,5",options="header"]
+|=======================================================================
+| Name | Group | Default | Java Type | Description
+| apiName | common |  | Olingo4ApiName | *Required* What kind of operation to 
perform
+| methodName | common |  | String | *Required* What sub operation to use for 
the selected operation
+| connectTimeout | common | 30000 | int | HTTP connection creation timeout in 
milliseconds defaults to 30000 (30 seconds)
+| contentType | common | application/json;charset=utf-8 | String | 
Content-Type header value can be used to specify JSON or XML message format 
defaults to application/json;charset=utf-8
+| httpAsyncClientBuilder | common |  | HttpAsyncClientBuilder | Custom HTTP 
async client builder for more complex HTTP client configuration overrides 
connectionTimeout socketTimeout proxy and sslContext. Note that a socketTimeout 
MUST be specified in the builder otherwise OData requests could block 
indefinitely
+| httpClientBuilder | common |  | HttpClientBuilder | Custom HTTP client 
builder for more complex HTTP client configuration overrides connectionTimeout 
socketTimeout proxy and sslContext. Note that a socketTimeout MUST be specified 
in the builder otherwise OData requests could block indefinitely
+| httpHeaders | common |  | Map | Custom HTTP headers to inject into every 
request this could include OAuth tokens etc.
+| inBody | common |  | String | Sets the name of a parameter to be passed in 
the exchange In Body
+| proxy | common |  | HttpHost | HTTP proxy server configuration
+| serviceUri | common |  | String | Target OData service base URI e.g. 
http://services.odata.org/OData/OData.svc
+| socketTimeout | common | 30000 | int | HTTP request timeout in milliseconds 
defaults to 30000 (30 seconds)
+| sslContextParameters | common |  | SSLContextParameters | To configure 
security using SSLContextParameters
+| bridgeErrorHandler | consumer | false | boolean | Allows for bridging the 
consumer to the Camel routing Error Handler which mean any exceptions occurred 
while the consumer is trying to pickup incoming messages or the likes will now 
be processed as a message and handled by the routing Error Handler. By default 
the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with 
exceptions that will be logged at WARN or ERROR level and ignored.
+| exceptionHandler | consumer (advanced) |  | ExceptionHandler | To let the 
consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler 
is enabled then this options is not in use. By default the consumer will deal 
with exceptions that will be logged at WARN or ERROR level and ignored.
+| exchangePattern | consumer (advanced) |  | ExchangePattern | Sets the 
exchange pattern when the consumer creates an exchange.
+| synchronous | advanced | false | boolean | Sets whether synchronous 
processing should be strictly used or Camel is allowed to use asynchronous 
processing (if supported).
+|=======================================================================
+{% endraw %}
+// endpoint options: END
+
+
+### Producer Endpoints
+
+Producer endpoints can use endpoint names and options listed
+next. Producer endpoints can also use a special option *`inBody`* that
+in turn should contain the name of the endpoint option whose value will
+be contained in the Camel Exchange In message. The *inBody* option
+defaults to *data* for endpoints that take that option. 
+
+Any of the endpoint options can be provided in either the endpoint URI,
+or dynamically in a message header. The message header name must be of
+the format *`CamelOlingo2.<option>`*. Note that the *`inBody`* option
+overrides message header, i.e. the endpoint
+option *`inBody=option`* would override
+a *`CamelOlingo2.option`* header. In addition, query parameters can be
+specified 
+
+Note that the resourcePath option can either in specified in the URI as
+a part of the URI path, as an endpoint option
+?resourcePath=<resource-path> or as a header value
+CamelOlingo2.resourcePath. The OData entity key predicate can either be
+a part of the resource path, e.g. _Manufacturers('1')_, where _'__1'_ is
+the key predicate, or be specified separately with resource path
+_Manufacturers_ and keyPredicate option _'1'_. 
+
+[width="100%",cols="10%,10%,10%,70%",options="header",]
+|=======================================================================
+|Endpoint |Options |HTTP Method |Result Body Type
+
+|batch |data |POST with multipart/mixed batch request 
|java.util.List<org.apache.camel.component.olingo2.api.batch.Olingo2BatchResponse>
+
+|create |data, resourcePath |POST 
|org.apache.olingo.odata2.api.ep.entry.ODataEntry for new entries
+org.apache.olingo.odata2.api.commons.HttpStatusCodes for other OData resources
+
+|delete |resourcePath |DELETE 
|org.apache.olingo.odata2.api.commons.HttpStatusCodes
+
+|merge |data, resourcePath |MERGE 
|org.apache.olingo.odata2.api.commons.HttpStatusCodes
+
+|patch |data, resourcePath |PATCH 
|org.apache.olingo.odata2.api.commons.HttpStatusCodes
+
+|read |queryParams, resourcePath |GET |Depends on OData resource being queried 
as described next
+
+|update |data, resourcePath |PUT 
|org.apache.olingo.odata2.api.commons.HttpStatusCodes
+|=======================================================================
+
+### OData Resource Type Mapping
+
+The result of *read* endpoint and data type of *data* option depends on
+the OData resource being queried, created or modified. 
+
+[width="100%",cols="10%,10%,80%",options="header",]
+|=======================================================================
+|OData Resource Type |Resource URI from resourcePath and keyPredicate |In or 
Out Body Type
+
+|Entity data model |$metadata |org.apache.olingo.odata2.api.edm.Edm
+
+|Service document |/ 
|org.apache.olingo.odata2.api.servicedocument.ServiceDocument
+
+|OData feed |<entity-set> |org.apache.olingo.odata2.api.ep.feed.ODataFeed
+
+|OData entry |<entity-set>(<key-predicate>) 
|org.apache.olingo.odata2.api.ep.entry.ODataEntry for Out body (response)
+java.util.Map<String, Object> for In body (request)
+
+|Simple property |<entity-set>(<key-predicate>)/<simple-property> |Appropriate 
Java data type as described by Olingo EdmProperty
+
+|Simple property value |<entity-set>(<key-predicate>)/<simple-property>/$value 
|Appropriate Java data type as described by Olingo EdmProperty
+
+|Complex property |<entity-set>(<key-predicate>)/<complex-property> 
|java.util.Map<String, Object>
+
+|Zero or one association link 
|<entity-set>(<key-predicate>/$link/<one-to-one-entity-set-property> |String 
for response
+java.util.Map<String, Object> with key property names and values for request
+
+|Zero or many association links 
|<entity-set>(<key-predicate>/$link/<one-to-many-entity-set-property> 
|java.util.List<String> for response
+java.util.List<java.util.Map<String, Object>> containing list of key property 
names and values for request
+
+|Count |<resource-uri>/$count |java.lang.Long
+|=======================================================================
+
+### Consumer Endpoints
+
+Only the *read* endpoint can be used as a consumer endpoint. Consumer
+endpoints can
+use 
http://camel.apache.org/polling-consumer.html#PollingConsumer-ScheduledPollConsumerOptions[Scheduled
+Poll Consumer Options] with a *`consumer.`* prefix to schedule endpoint
+invocation. By default consumer endpoints that return an array or
+collection will generate one exchange per element, and their routes will
+be executed once for each exchange. This behavior can be disabled by
+setting the endpoint property *consumer.splitResult=false*. 
+
+### Message Headers
+
+Any URI option can be provided in a message header for producer
+endpoints with a *`CamelOlingo2.`* prefix.
+
+### Message Body
+
+All result message bodies utilize objects provided by the underlying
+http://olingo.apache.org/javadoc/odata2/index.html[Apache Olingo 2.0
+API] used by the Olingo2Component. Producer endpoints can specify the
+option name for incoming message body in the *`inBody`* endpoint URI
+parameter. For endpoints that return an array or collection, a consumer
+endpoint will map every element to distinct messages, unless
+*consumer.splitResult* is set to *false*.
+
+### Use cases
+
+The following route reads top 5 entries from the Manufacturer feed
+ordered by ascending Name property. 
+
+ 
+
+[source,java]
+------------------------------------------------------------
+from("direct:...")
+    .setHeader("CamelOlingo2.$top", "5");
+    .to("olingo2://read/Manufacturers?orderBy=Name%20asc");
+------------------------------------------------------------
+
+ 
+
+The following route reads Manufacturer entry using the key property
+value in incoming *id* header. 
+
+ 
+
+[source,java]
+------------------------------------------------------------
+from("direct:...")
+    .setHeader("CamelOlingo2.keyPredicate", header("id"))
+    .to("olingo2://read/Manufacturers");
+------------------------------------------------------------
+
+ 
+
+The following route creates Manufacturer entry using the
+*java.util.Map<String, Object>* in body message. 
+
+ 
+
+[source,java]
+------------------------------------------------------------
+from("direct:...")
+    .to("olingo2://create/Manufacturers");
+------------------------------------------------------------
+
+ 
+
+The following route polls Manufacturer
+http://olingo.apache.org/doc/tutorials/deltaClient.html[delta
+feed] every 30 seconds. The bean *blah* updates the bean *paramsBean* to
+add an updated *!deltatoken* property with the value returned in the
+*ODataDeltaFeed* result. Since the initial delta token is not known, the
+consumer endpoint will produce an *ODataFeed* value the first time, and
+*ODataDeltaFeed* on subsequent polls. 
+
+ 
+
+[source,java]
+---------------------------------------------------------------------------------------------------------
+from("olingo2://read/Manufacturers?queryParams=#paramsBean&consumer.timeUnit=SECONDS&consumer.delay=30")
+    .to("bean:blah");
+---------------------------------------------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/camel/blob/e6eded4c/components/camel-olingo4/camel-olingo4-component/src/main/java/META-INF/MANIFEST.MF
----------------------------------------------------------------------
diff --git 
a/components/camel-olingo4/camel-olingo4-component/src/main/java/META-INF/MANIFEST.MF
 
b/components/camel-olingo4/camel-olingo4-component/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..5e94951
--- /dev/null
+++ 
b/components/camel-olingo4/camel-olingo4-component/src/main/java/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path: 
+

http://git-wip-us.apache.org/repos/asf/camel/blob/e6eded4c/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4AppWrapper.java
----------------------------------------------------------------------
diff --git 
a/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4AppWrapper.java
 
b/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4AppWrapper.java
new file mode 100644
index 0000000..1ed09a1
--- /dev/null
+++ 
b/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4AppWrapper.java
@@ -0,0 +1,108 @@
+/**
+ * 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.camel.component.olingo4;
+
+import java.util.concurrent.CountDownLatch;
+
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.olingo4.api.Olingo4App;
+import org.apache.camel.component.olingo4.api.Olingo4ResponseHandler;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.olingo.commons.api.Constants;
+import org.apache.olingo.commons.api.edm.Edm;
+
+/**
+ * Holder class for {@link org.apache.camel.component.olingo4.api.Olingo4App}
+ * and its lazily read {@link org.apache.olingo.commons.api.edm.Edm}.
+ */
+public class Olingo4AppWrapper {
+
+    private final Olingo4App olingo4App;
+    private volatile Edm edm;
+
+    public Olingo4AppWrapper(Olingo4App olingo4App) {
+        ObjectHelper.notNull(olingo4App, "olingo4App");
+        this.olingo4App = olingo4App;
+    }
+
+    public Olingo4App getOlingo4App() {
+        return olingo4App;
+    }
+
+    public void close() {
+        olingo4App.close();
+    }
+
+    // double checked locking based singleton Edm reader
+    public Edm getEdm() throws RuntimeCamelException {
+        Edm localEdm = edm;
+        if (localEdm == null) {
+
+            synchronized (this) {
+
+                localEdm = edm;
+                if (localEdm == null) {
+
+                    final CountDownLatch latch = new CountDownLatch(1);
+                    final Exception[] error = new Exception[1];
+                    olingo4App.read(null, Constants.METADATA, null, new 
Olingo4ResponseHandler<Edm>() {
+
+                        @Override
+                        public void onResponse(Edm response) {
+                            edm = response;
+                            latch.countDown();
+                        }
+
+                        @Override
+                        public void onException(Exception ex) {
+                            error[0] = ex;
+                            latch.countDown();
+                        }
+
+                        @Override
+                        public void onCanceled() {
+                            error[0] = new RuntimeCamelException("OData HTTP 
request cancelled!");
+                            latch.countDown();
+                        }
+                    });
+
+                    try {
+                        // wait until response or timeout
+                        latch.await();
+
+                        final Exception ex = error[0];
+                        if (ex != null) {
+                            if (ex instanceof RuntimeCamelException) {
+                                throw (RuntimeCamelException)ex;
+                            } else {
+                                final String message = ex.getMessage() != null 
? ex.getMessage() : ex.getClass().getName();
+                                throw new RuntimeCamelException("Error reading 
EDM: " + message, ex);
+                            }
+                        }
+
+                    } catch (InterruptedException e) {
+                        throw new RuntimeCamelException(e.getMessage(), e);
+                    }
+
+                    localEdm = edm;
+                }
+            }
+        }
+
+        return localEdm;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/e6eded4c/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Component.java
----------------------------------------------------------------------
diff --git 
a/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Component.java
 
b/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Component.java
new file mode 100644
index 0000000..ee5fd2c
--- /dev/null
+++ 
b/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Component.java
@@ -0,0 +1,184 @@
+/**
+ * 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.camel.component.olingo4;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Endpoint;
+import org.apache.camel.component.olingo4.api.impl.Olingo4AppImpl;
+import org.apache.camel.component.olingo4.internal.Olingo4ApiCollection;
+import org.apache.camel.component.olingo4.internal.Olingo4ApiName;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.component.AbstractApiComponent;
+import org.apache.camel.util.jsse.SSLContextParameters;
+import org.apache.http.HttpHost;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
+
+/**
+ * Represents the component that manages {@link Olingo4Endpoint}.
+ */
+public class Olingo4Component extends AbstractApiComponent<Olingo4ApiName, 
Olingo4Configuration, Olingo4ApiCollection> {
+
+    // component level shared proxy
+    private Olingo4AppWrapper apiProxy;
+
+    public Olingo4Component() {
+        super(Olingo4Endpoint.class, Olingo4ApiName.class, 
Olingo4ApiCollection.getCollection());
+    }
+
+    public Olingo4Component(CamelContext context) {
+        super(context, Olingo4Endpoint.class, Olingo4ApiName.class, 
Olingo4ApiCollection.getCollection());
+    }
+
+    @Override
+    protected Olingo4ApiName getApiName(String apiNameStr) throws 
IllegalArgumentException {
+        return Olingo4ApiName.fromValue(apiNameStr);
+    }
+
+    @Override
+    protected Endpoint createEndpoint(String uri, String remaining, 
Map<String, Object> parameters) throws Exception {
+        // parse remaining to extract resourcePath and queryParams
+        final String[] pathSegments = remaining.split("/", -1);
+        final String methodName = pathSegments[0];
+
+        if (pathSegments.length > 1) {
+            final StringBuilder resourcePath = new StringBuilder();
+            for (int i = 1; i < pathSegments.length; i++) {
+                resourcePath.append(pathSegments[i]);
+                if (i < (pathSegments.length - 1)) {
+                    resourcePath.append('/');
+                }
+            }
+            // This will override any URI supplied ?resourcePath=... param
+            parameters.put(Olingo4Endpoint.RESOURCE_PATH_PROPERTY, 
resourcePath.toString());
+        }
+
+        final Olingo4Configuration endpointConfiguration = 
createEndpointConfiguration(Olingo4ApiName.DEFAULT);
+        final Endpoint endpoint = createEndpoint(uri, methodName, 
Olingo4ApiName.DEFAULT, endpointConfiguration);
+
+        // set endpoint property inBody
+        setProperties(endpoint, parameters);
+
+        // configure endpoint properties and initialize state
+        endpoint.configureProperties(parameters);
+
+        return endpoint;
+    }
+
+    @Override
+    protected Endpoint createEndpoint(String uri, String methodName, 
Olingo4ApiName apiName, Olingo4Configuration endpointConfiguration) {
+        endpointConfiguration.setApiName(apiName);
+        endpointConfiguration.setMethodName(methodName);
+        return new Olingo4Endpoint(uri, this, apiName, methodName, 
endpointConfiguration);
+    }
+
+    /**
+     * To use the shared configuration
+     */
+    @Override
+    public void setConfiguration(Olingo4Configuration configuration) {
+        super.setConfiguration(configuration);
+    }
+
+    /**
+     * To use the shared configuration
+     */
+    @Override
+    public Olingo4Configuration getConfiguration() {
+        return super.getConfiguration();
+    }
+
+    public Olingo4AppWrapper createApiProxy(Olingo4Configuration 
endpointConfiguration) {
+        final Olingo4AppWrapper result;
+        if (endpointConfiguration.equals(this.configuration)) {
+            synchronized (this) {
+                if (apiProxy == null) {
+                    apiProxy = createOlingo4App(this.configuration);
+                }
+            }
+            result = apiProxy;
+        } else {
+            result = createOlingo4App(endpointConfiguration);
+        }
+        return result;
+    }
+
+    private Olingo4AppWrapper createOlingo4App(Olingo4Configuration 
configuration) {
+
+        Object clientBuilder = configuration.getHttpAsyncClientBuilder();
+        if (clientBuilder == null) {
+            HttpAsyncClientBuilder asyncClientBuilder = 
HttpAsyncClientBuilder.create();
+
+            // apply simple configuration properties
+            final RequestConfig.Builder requestConfigBuilder = 
RequestConfig.custom();
+            
requestConfigBuilder.setConnectTimeout(configuration.getConnectTimeout());
+            
requestConfigBuilder.setSocketTimeout(configuration.getSocketTimeout());
+
+            final HttpHost proxy = configuration.getProxy();
+            if (proxy != null) {
+                requestConfigBuilder.setProxy(proxy);
+            }
+
+            // set default request config
+            
asyncClientBuilder.setDefaultRequestConfig(requestConfigBuilder.build());
+
+            SSLContextParameters sslContextParameters = 
configuration.getSslContextParameters();
+            if (sslContextParameters == null) {
+                // use defaults if not specified
+                sslContextParameters = new SSLContextParameters();
+            }
+            try {
+                
asyncClientBuilder.setSSLContext(sslContextParameters.createSSLContext(getCamelContext()));
+            } catch (GeneralSecurityException e) {
+                throw ObjectHelper.wrapRuntimeCamelException(e);
+            } catch (IOException e) {
+                throw ObjectHelper.wrapRuntimeCamelException(e);
+            }
+        }
+
+        Olingo4AppImpl olingo4App;
+        if (clientBuilder == null || clientBuilder instanceof 
HttpAsyncClientBuilder) {
+            olingo4App = new Olingo4AppImpl(configuration.getServiceUri(), 
(HttpAsyncClientBuilder)clientBuilder);
+        } else {
+            olingo4App = new Olingo4AppImpl(configuration.getServiceUri(), 
(HttpClientBuilder)clientBuilder);
+        }
+        apiProxy = new Olingo4AppWrapper(olingo4App);
+        
apiProxy.getOlingo4App().setContentType(configuration.getContentType());
+        
apiProxy.getOlingo4App().setHttpHeaders(configuration.getHttpHeaders());
+
+        return apiProxy;
+    }
+
+    public void closeApiProxy(Olingo4AppWrapper apiProxy) {
+        if (this.apiProxy != apiProxy) {
+            // not a shared proxy
+            apiProxy.close();
+        }
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        if (apiProxy != null) {
+            apiProxy.close();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/e6eded4c/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Configuration.java
----------------------------------------------------------------------
diff --git 
a/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Configuration.java
 
b/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Configuration.java
new file mode 100644
index 0000000..68672ba
--- /dev/null
+++ 
b/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Configuration.java
@@ -0,0 +1,221 @@
+/**
+ * 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.camel.component.olingo4;
+
+import java.util.Map;
+
+import org.apache.camel.component.olingo4.internal.Olingo4ApiName;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriParams;
+import org.apache.camel.spi.UriPath;
+import org.apache.camel.util.jsse.SSLContextParameters;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.http.HttpHost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
+
+/**
+ * Component configuration for Olingo4 component.
+ */
+@UriParams
+public class Olingo4Configuration {
+
+    private static final String DEFAULT_CONTENT_TYPE = 
ContentType.APPLICATION_JSON.toString();
+    private static final int DEFAULT_TIMEOUT = 30 * 1000;
+
+    @UriPath
+    @Metadata(required = "true")
+    private Olingo4ApiName apiName;
+    @UriPath @Metadata(required = "true")
+    private String methodName;
+    @UriParam
+    private String serviceUri;
+    @UriParam(defaultValue = "application/json;charset=utf-8")
+    private String contentType = DEFAULT_CONTENT_TYPE;
+    @UriParam
+    private Map<String, String> httpHeaders;
+    @UriParam(defaultValue = "" + DEFAULT_TIMEOUT)
+    private int connectTimeout = DEFAULT_TIMEOUT;
+    @UriParam(defaultValue = "" + DEFAULT_TIMEOUT)
+    private int socketTimeout = DEFAULT_TIMEOUT;
+    @UriParam
+    private HttpHost proxy;
+    @UriParam
+    private SSLContextParameters sslContextParameters;
+    @UriParam
+    private HttpAsyncClientBuilder httpAsyncClientBuilder;
+    @UriParam
+    private HttpClientBuilder httpClientBuilder;
+
+    public Olingo4ApiName getApiName() {
+        return apiName;
+    }
+
+    /**
+     * What kind of operation to perform
+     */
+    public void setApiName(Olingo4ApiName apiName) {
+        this.apiName = apiName;
+    }
+
+    public String getMethodName() {
+        return methodName;
+    }
+
+    /**
+     * What sub operation to use for the selected operation
+     */
+    public void setMethodName(String methodName) {
+        this.methodName = methodName;
+    }
+
+    public String getServiceUri() {
+        return serviceUri;
+    }
+
+    /**
+     * Target OData service base URI, e.g. 
http://services.odata.org/OData/OData.svc
+     */
+    public void setServiceUri(String serviceUri) {
+        this.serviceUri = serviceUri;
+    }
+
+    public String getContentType() {
+        return contentType;
+    }
+
+    /**
+     * Content-Type header value can be used to specify JSON or XML message 
format, defaults to application/json;charset=utf-8
+     */
+    public void setContentType(String contentType) {
+        this.contentType = contentType;
+    }
+
+    public Map<String, String> getHttpHeaders() {
+        return httpHeaders;
+    }
+
+    /**
+     * Custom HTTP headers to inject into every request, this could include 
OAuth tokens, etc.
+     */
+    public void setHttpHeaders(Map<String, String> httpHeaders) {
+        this.httpHeaders = httpHeaders;
+    }
+
+    public int getConnectTimeout() {
+        return connectTimeout;
+    }
+
+    /**
+     * HTTP connection creation timeout in milliseconds, defaults to 30,000 
(30 seconds)
+     */
+    public void setConnectTimeout(int connectTimeout) {
+        this.connectTimeout = connectTimeout;
+    }
+
+    public int getSocketTimeout() {
+        return socketTimeout;
+    }
+
+    /**
+     * HTTP request timeout in milliseconds, defaults to 30,000 (30 seconds)
+     */
+    public void setSocketTimeout(int socketTimeout) {
+        this.socketTimeout = socketTimeout;
+    }
+
+    public HttpHost getProxy() {
+        return proxy;
+    }
+
+    /**
+     * HTTP proxy server configuration
+     */
+    public void setProxy(HttpHost proxy) {
+        this.proxy = proxy;
+    }
+
+    public SSLContextParameters getSslContextParameters() {
+        return sslContextParameters;
+    }
+
+    /**
+     * To configure security using SSLContextParameters
+     */
+    public void setSslContextParameters(SSLContextParameters 
sslContextParameters) {
+        this.sslContextParameters = sslContextParameters;
+    }
+
+    public HttpAsyncClientBuilder getHttpAsyncClientBuilder() {
+        return httpAsyncClientBuilder;
+    }
+
+    /**
+     * Custom HTTP async client builder for more complex HTTP client 
configuration, overrides connectionTimeout, socketTimeout, proxy and sslContext.
+     * Note that a socketTimeout MUST be specified in the builder, otherwise 
OData requests could block indefinitely
+     */
+    public void setHttpAsyncClientBuilder(HttpAsyncClientBuilder 
httpAsyncClientBuilder) {
+        this.httpAsyncClientBuilder = httpAsyncClientBuilder;
+    }
+
+    public HttpClientBuilder getHttpClientBuilder() {
+        return httpClientBuilder;
+    }
+
+    /**
+     * Custom HTTP client builder for more complex HTTP client configuration, 
overrides connectionTimeout, socketTimeout, proxy and sslContext.
+     * Note that a socketTimeout MUST be specified in the builder, otherwise 
OData requests could block indefinitely
+     */
+    public void setHttpClientBuilder(HttpClientBuilder httpClientBuilder) {
+        this.httpClientBuilder = httpClientBuilder;
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder()
+            .append(serviceUri)
+            .append(contentType)
+            .append(httpHeaders)
+            .append(connectTimeout)
+            .append(socketTimeout)
+            .append(proxy)
+            .append(sslContextParameters)
+            .append(httpAsyncClientBuilder)
+            .append(httpClientBuilder)
+            .hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof Olingo4Configuration) {
+            Olingo4Configuration other = (Olingo4Configuration) obj;
+            return serviceUri == null ? other.serviceUri == null : 
serviceUri.equals(other.serviceUri)
+                && contentType == null ? other.contentType == null : 
contentType.equals(other.contentType)
+                && httpHeaders == null ? other.httpHeaders == null : 
httpHeaders.equals(other.httpHeaders)
+                && connectTimeout == other.connectTimeout
+                && socketTimeout == other.socketTimeout
+                && proxy == null ? other.proxy == null : 
proxy.equals(other.proxy)
+                && sslContextParameters == null ? other.sslContextParameters 
== null : sslContextParameters.equals(other.sslContextParameters)
+                && httpAsyncClientBuilder == null ? 
other.httpAsyncClientBuilder == null
+                : httpAsyncClientBuilder.equals(other.httpAsyncClientBuilder)
+                && httpClientBuilder == null ? other.httpClientBuilder == null 
: httpClientBuilder.equals(other.httpClientBuilder);
+        }
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/e6eded4c/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Consumer.java
----------------------------------------------------------------------
diff --git 
a/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Consumer.java
 
b/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Consumer.java
new file mode 100644
index 0000000..02465c5
--- /dev/null
+++ 
b/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Consumer.java
@@ -0,0 +1,92 @@
+/**
+ * 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.camel.component.olingo4;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+
+import org.apache.camel.Processor;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.olingo4.api.Olingo4ResponseHandler;
+import org.apache.camel.component.olingo4.internal.Olingo4ApiName;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.component.AbstractApiConsumer;
+import org.apache.camel.util.component.ApiConsumerHelper;
+
+/**
+ * The Olingo4 consumer.
+ */
+public class Olingo4Consumer extends AbstractApiConsumer<Olingo4ApiName, 
Olingo4Configuration> {
+
+    public Olingo4Consumer(Olingo4Endpoint endpoint, Processor processor) {
+        super(endpoint, processor);
+    }
+
+    @Override
+    protected int poll() throws Exception {
+        // invoke the consumer method
+        final Map<String, Object> args = new HashMap<String, Object>();
+        args.putAll(endpoint.getEndpointProperties());
+
+        // let the endpoint and the Consumer intercept properties
+        endpoint.interceptProperties(args);
+        interceptProperties(args);
+
+        try {
+            // create responseHandler
+            final CountDownLatch latch = new CountDownLatch(1);
+            final Object[] result = new Object[1];
+            final Exception[] error = new Exception[1];
+
+            args.put(Olingo4Endpoint.RESPONSE_HANDLER_PROPERTY, new 
Olingo4ResponseHandler<Object>() {
+                @Override
+                public void onResponse(Object response) {
+                    result[0] = response;
+                    latch.countDown();
+                }
+
+                @Override
+                public void onException(Exception ex) {
+                    error[0] = ex;
+                    latch.countDown();
+                }
+
+                @Override
+                public void onCanceled() {
+                    error[0] = new RuntimeCamelException("OData HTTP Request 
cancelled");
+                    latch.countDown();
+                }
+            });
+
+            doInvokeMethod(args);
+
+            // guaranteed to return, since an exception on timeout is
+            // expected!!!
+            latch.await();
+
+            if (error[0] != null) {
+                throw error[0];
+            }
+
+            return ApiConsumerHelper.getResultsProcessed(this, result[0], 
isSplitResult());
+
+        } catch (Throwable t) {
+            throw ObjectHelper.wrapRuntimeCamelException(t);
+        }
+    }
+}

Reply via email to