You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2013/06/05 17:12:55 UTC
[11/11] git commit: CAMEL-6428: camel-salesforce component. Thanks to
Dhiraj Bokde for the contribution.
CAMEL-6428: camel-salesforce component. Thanks to Dhiraj Bokde for the contribution.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/0c401b9f
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/0c401b9f
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/0c401b9f
Branch: refs/heads/master
Commit: 0c401b9fba53837bdea3dc486880dd0e0c6e2d6f
Parents: 469e0e3
Author: Claus Ibsen <da...@apache.org>
Authored: Wed Jun 5 16:55:52 2013 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Wed Jun 5 17:12:31 2013 +0200
----------------------------------------------------------------------
.gitignore | 1 +
apache-camel/pom.xml | 4 +
apache-camel/src/main/descriptors/common-bin.xml | 1 +
.../camel-salesforce-component/README.md | 68 ++
.../camel-salesforce-component/pom.xml | 121 +++
.../component/salesforce/SalesforceComponent.java | 233 +++++
.../component/salesforce/SalesforceConsumer.java | 215 +++++
.../component/salesforce/SalesforceEndpoint.java | 96 ++
.../salesforce/SalesforceEndpointConfig.java | 292 +++++++
.../salesforce/SalesforceLoginConfig.java | 99 +++
.../component/salesforce/SalesforceProducer.java | 102 +++
.../salesforce/api/JodaTimeConverter.java | 64 ++
.../salesforce/api/PicklistEnumConverter.java | 80 ++
.../salesforce/api/SalesforceException.java | 104 +++
.../salesforce/api/dto/AbstractDTOBase.java | 40 +
.../api/dto/AbstractQueryRecordsBase.java | 72 ++
.../salesforce/api/dto/AbstractSObjectBase.java | 172 ++++
.../component/salesforce/api/dto/Attributes.java | 38 +
.../salesforce/api/dto/ChildRelationShip.java | 74 ++
.../salesforce/api/dto/CreateSObjectResult.java | 57 ++
.../salesforce/api/dto/GlobalObjects.java | 57 ++
.../salesforce/api/dto/PickListValue.java | 70 ++
.../component/salesforce/api/dto/RecentItem.java | 56 ++
.../salesforce/api/dto/RecordTypeInfo.java | 56 ++
.../component/salesforce/api/dto/RestError.java | 68 ++
.../salesforce/api/dto/RestResources.java | 100 +++
.../component/salesforce/api/dto/SObject.java | 237 +++++
.../salesforce/api/dto/SObjectBasicInfo.java | 46 +
.../salesforce/api/dto/SObjectDescription.java | 67 ++
.../salesforce/api/dto/SObjectDescriptionUrls.java | 47 +
.../component/salesforce/api/dto/SObjectField.java | 414 +++++++++
.../component/salesforce/api/dto/SObjectUrls.java | 56 ++
.../component/salesforce/api/dto/SearchResult.java | 49 ++
.../salesforce/api/dto/SearchResults.java | 41 +
.../component/salesforce/api/dto/Version.java | 52 ++
.../component/salesforce/api/dto/Versions.java | 40 +
.../salesforce/api/dto/bulk/BatchInfo.java | 342 ++++++++
.../salesforce/api/dto/bulk/BatchInfoList.java | 82 ++
.../salesforce/api/dto/bulk/BatchResult.java | 82 ++
.../salesforce/api/dto/bulk/BatchStateEnum.java | 75 ++
.../api/dto/bulk/ConcurrencyModeEnum.java | 66 ++
.../salesforce/api/dto/bulk/ContentType.java | 57 ++
.../component/salesforce/api/dto/bulk/Error.java | 105 +++
.../component/salesforce/api/dto/bulk/JobInfo.java | 673 +++++++++++++++
.../salesforce/api/dto/bulk/JobStateEnum.java | 72 ++
.../salesforce/api/dto/bulk/ObjectFactory.java | 200 +++++
.../salesforce/api/dto/bulk/OperationEnum.java | 78 ++
.../salesforce/api/dto/bulk/QueryResult.java | 84 ++
.../salesforce/api/dto/bulk/QueryResultList.java | 82 ++
.../component/salesforce/api/dto/bulk/Result.java | 147 ++++
.../salesforce/api/dto/bulk/ResultError.java | 140 +++
.../component/salesforce/api/dto/bulk/SObject.java | 138 +++
.../salesforce/api/dto/bulk/StatusCode.java | 395 +++++++++
.../salesforce/api/dto/bulk/package-info.java | 18 +
.../salesforce/internal/OperationName.java | 71 ++
.../salesforce/internal/PayloadFormat.java | 22 +
.../salesforce/internal/SalesforceSession.java | 336 +++++++
.../internal/client/AbstractClientBase.java | 196 +++++
.../salesforce/internal/client/BulkApiClient.java | 92 ++
.../internal/client/DefaultBulkApiClient.java | 481 +++++++++++
.../internal/client/DefaultRestClient.java | 364 ++++++++
.../salesforce/internal/client/RestClient.java | 177 ++++
.../internal/client/SalesforceExchange.java | 36 +
.../client/SalesforceSecurityListener.java | 162 ++++
.../internal/client/SyncResponseCallback.java | 57 ++
.../salesforce/internal/dto/LoginError.java | 47 +
.../salesforce/internal/dto/LoginToken.java | 81 ++
.../internal/dto/NotifyForFieldsEnum.java | 53 ++
.../internal/dto/NotifyForOperationsEnum.java | 52 ++
.../salesforce/internal/dto/PushTopic.java | 100 +++
.../internal/dto/QueryRecordsPushTopic.java | 38 +
.../salesforce/internal/dto/RestErrors.java | 41 +
.../internal/processor/AbstractRestProcessor.java | 538 ++++++++++++
.../processor/AbstractSalesforceProcessor.java | 84 ++
.../internal/processor/BulkApiProcessor.java | 377 ++++++++
.../internal/processor/JsonRestProcessor.java | 180 ++++
.../internal/processor/SalesforceProcessor.java | 27 +
.../internal/processor/XmlRestProcessor.java | 240 +++++
.../internal/streaming/PushTopicHelper.java | 222 +++++
.../internal/streaming/SubscriptionHelper.java | 372 ++++++++
.../services/org/apache/camel/component/salesforce | 1 +
.../salesforce/AbstractBulkApiTestBase.java | 105 +++
.../salesforce/AbstractSalesforceTestBase.java | 60 ++
.../salesforce/BulkApiBatchIntegrationTest.java | 109 +++
.../salesforce/BulkApiJobIntegrationTest.java | 111 +++
.../salesforce/BulkApiQueryIntegrationTest.java | 85 ++
.../component/salesforce/LoginConfigHelper.java | 59 ++
.../salesforce/RestApiIntegrationTest.java | 408 +++++++++
.../salesforce/StreamingApiIntegrationTest.java | 109 +++
.../camel/component/salesforce/dto/Document.java | 201 +++++
.../component/salesforce/dto/Line_Item__c.java | 74 ++
.../component/salesforce/dto/Merchandise__c.java | 61 ++
.../salesforce/dto/QueryRecordsLine_Item__c.java | 35 +
.../internal/SessionIntegrationTest.java | 79 ++
.../src/test/resources/log4j.properties | 18 +
.../src/test/resources/test-request.csv | 3 +
.../src/test/resources/test-request.xml | 15 +
.../camel-salesforce-maven-plugin/README.md | 26 +
.../camel-salesforce-maven-plugin/pom.xml | 78 ++
.../apache/camel/maven/CamelSalesforceMojo.java | 570 ++++++++++++
.../src/main/resources/sobject-picklist.vm | 52 ++
.../src/main/resources/sobject-pojo.vm | 60 ++
.../src/main/resources/sobject-query-records.vm | 29 +
.../maven/CamelSalesforceMojoIntegrationTest.java | 85 ++
.../src/test/resources/log4j.properties | 19 +
components/camel-salesforce/pom.xml | 38 +
components/pom.xml | 1 +
parent/pom.xml | 6 +
.../karaf/features/src/main/resources/features.xml | 16 +
109 files changed, 13184 insertions(+), 0 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/0c401b9f/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index 394c174..b74e107 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,4 +9,5 @@ target
.settings
.checkstyle
*.log
+test-salesforce-login.properties
dependency-reduced-pom.xml
http://git-wip-us.apache.org/repos/asf/camel/blob/0c401b9f/apache-camel/pom.xml
----------------------------------------------------------------------
diff --git a/apache-camel/pom.xml b/apache-camel/pom.xml
index 0aeafe4..af957dd 100644
--- a/apache-camel/pom.xml
+++ b/apache-camel/pom.xml
@@ -436,6 +436,10 @@
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
+ <artifactId>camel-salesforce</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
<artifactId>camel-sap-netweaver</artifactId>
</dependency>
<dependency>
http://git-wip-us.apache.org/repos/asf/camel/blob/0c401b9f/apache-camel/src/main/descriptors/common-bin.xml
----------------------------------------------------------------------
diff --git a/apache-camel/src/main/descriptors/common-bin.xml b/apache-camel/src/main/descriptors/common-bin.xml
index 3d08587..8e28551 100644
--- a/apache-camel/src/main/descriptors/common-bin.xml
+++ b/apache-camel/src/main/descriptors/common-bin.xml
@@ -120,6 +120,7 @@
<include>org.apache.camel:camel-rss</include>
<include>org.apache.camel:camel-ruby</include>
<include>org.apache.camel:camel-rx</include>
+ <include>org.apache.camel:camel-salesforce</include>
<include>org.apache.camel:camel-sap-netweaver</include>
<include>org.apache.camel:camel-saxon</include>
<include>org.apache.camel:camel-scala</include>
http://git-wip-us.apache.org/repos/asf/camel/blob/0c401b9f/components/camel-salesforce/camel-salesforce-component/README.md
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/README.md b/components/camel-salesforce/camel-salesforce-component/README.md
new file mode 100644
index 0000000..9bf9845
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/README.md
@@ -0,0 +1,68 @@
+# Camel Salesforce component #
+
+This component supports producer and consumer endpoints to communicate with Salesforce using Java DTOs.
+There is a companion maven plugin [camel-salesforce-plugin](https://github.com/dhirajsb/camel-salesforce-maven-plugin) that generates these DTOs.
+
+The component supports the following Salesforce APIs
+
+## REST API ##
+
+Producer endpoints can use the following APIs. Most of the APIs process one record at a time, the Query API can retrieve multiple Records.
+
+* getVersions - Gets supported Salesforce REST API versions
+* getResources - Gets available Salesforce REST Resource endpoints
+* getGlobalObjects - Gets metadata for all available SObject types
+* getBasicInfo - Gets basic metadata for a specific SObject type
+* getDescription - Gets comprehensive metadata for a specific SObject type
+* getSObject - Gets an SObject using its Salesforce Id
+* createSObject - Creates an SObject
+* updateSObject - Updates an SObject using Id
+* deleteSObject - Deletes an SObject using Id
+* getSObjectWithId - Gets an SObject using an external (user defined) id field
+* upsertSObject - Updates or inserts an SObject using an external id
+* deleteSObjectWithId - Deletes an SObject using an external id
+* query - Runs a Salesforce SOQL query
+* queryMore - Retrieves more results (in case of large number of results) using result link returned from the 'query' API
+* search - Runs a Salesforce SOSL query
+
+For example, the following producer endpoint uses the upsertSObject API, with the sObjectIdName parameter specifying 'Name' as the external id field.
+The request message body should be an SObject DTO generated using the maven plugin.
+The response message will either be NULL if an existing record was updated, or [CreateSObjectResult] with an id of the new record, or a list of errors while creating the new object.
+
+ ...to("force:upsertSObject?sObjectIdName=Name")...
+
+## Bulk API ##
+
+Producer endpoints can use the following APIs. All Job data formats, i.e. xml, csv, zip/xml, and zip/csv are supported.
+The request and response have to be marshalled/unmarshalled by the route. Usually the request will be some stream source like a CSV file,
+and the response may also be saved to a file to be correlated with the request.
+
+* createJob - Creates a Salesforce Bulk Job
+* getJob - Gets a Job using its Salesforce Id
+* closeJob - Closes a Job
+* abortJob - Aborts a Job
+* createBatch - Submits a Batch within a Bulk Job
+* getBatch - Gets a Batch using Id
+* getAllBatches - Gets all Batches for a Bulk Job Id
+* getRequest - Gets Request data (XML/CSV) for a Batch
+* getResults - Gets the results of the Batch when its complete
+* createBatchQuery - Creates a Batch from an SOQL query
+* getQueryResultIds - Gets a list of Result Ids for a Batch Query
+* getQueryResult - Gets results for a Result Id
+
+For example, the following producer endpoint uses the createBatch API to create a Job Batch.
+The in message must contain a body that can be converted into an InputStream (usually UTF-8 CSV or XML content from a file, etc.) and header fields 'jobId' for the Job and 'contentType' for the Job content type, which can be XML, CSV, ZIP\_XML or ZIP\_CSV. The put message body will contain [BatchInfo] on success, or throw a [SalesforceException] on error.
+
+ ...to("force:createBatchJob")..
+
+## Streaming API ##
+
+Consumer endpoints can use the following sytax for streaming endpoints to receive Salesforce notifications on create/update.
+
+To create and subscribe to a topic
+
+ from("force:CamelTestTopic?notifyForFields=ALL¬ifyForOperations=ALL&sObjectName=Merchandise__c&updateTopic=true&sObjectQuery=SELECT Id, Name FROM Merchandise__c")...
+
+To subscribe to an existing topic
+
+ from("force:CamelTestTopic&sObjectName=Merchandise__c")...
http://git-wip-us.apache.org/repos/asf/camel/blob/0c401b9f/components/camel-salesforce/camel-salesforce-component/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/pom.xml b/components/camel-salesforce/camel-salesforce-component/pom.xml
new file mode 100644
index 0000000..03db485
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/pom.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-salesforce-parent</artifactId>
+ <version>2.12-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>camel-salesforce</artifactId>
+ <packaging>bundle</packaging>
+ <name>Camel :: Salesforce</name>
+ <description>Camel Salesforce support</description>
+
+ <properties>
+ <camel.osgi.export.pkg/>
+ <camel.osgi.export>
+ org.apache.camel.component.salesforce;version=${project.version},
+ org.apache.camel.component.salesforce.api.*;version=${project.version}
+ </camel.osgi.export>
+ <camel.osgi.private.pkg>org.apache.camel.component.salesforce.internal.*</camel.osgi.private.pkg>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-client</artifactId>
+ <version>${jetty-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-util</artifactId>
+ <version>${jetty-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-io</artifactId>
+ <version>${jetty-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-mapper-asl</artifactId>
+ <version>${jackson-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.thoughtworks.xstream</groupId>
+ <artifactId>xstream</artifactId>
+ <version>${xstream-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.cometd.java</groupId>
+ <artifactId>cometd-java-client</artifactId>
+ <version>${cometd-java-client-version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-util</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-io</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>joda-time</groupId>
+ <artifactId>joda-time</artifactId>
+ <version>${jodatime2-bundle-version}</version>
+ </dependency>
+ <!-- logging -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j-api-version}</version>
+ </dependency>
+
+ <!-- testing -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>${slf4j-api-version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>${log4j-version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-test</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+</project>
http://git-wip-us.apache.org/repos/asf/camel/blob/0c401b9f/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java
new file mode 100644
index 0000000..a48502a
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java
@@ -0,0 +1,233 @@
+/**
+ * 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.salesforce;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.impl.DefaultComponent;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.ServiceHelper;
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.RedirectListener;
+import org.apache.camel.component.salesforce.api.SalesforceException;
+import org.apache.camel.component.salesforce.api.dto.AbstractSObjectBase;
+import org.apache.camel.component.salesforce.internal.OperationName;
+import org.apache.camel.component.salesforce.internal.SalesforceSession;
+import org.apache.camel.component.salesforce.internal.streaming.SubscriptionHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Represents the component that manages {@link SalesforceEndpoint}.
+ */
+public class SalesforceComponent extends DefaultComponent {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SalesforceComponent.class);
+
+ private static final int MAX_CONNECTIONS_PER_ADDRESS = 20;
+ private static final int CONNECTION_TIMEOUT = 60000;
+ private static final int RESPONSE_TIMEOUT = 60000;
+
+ private SalesforceLoginConfig loginConfig;
+ private SalesforceEndpointConfig config;
+ private String[] packages;
+
+ // component state
+ private HttpClient httpClient;
+ private SalesforceSession session;
+ private Map<String, Class<?>> classMap;
+
+ // Lazily created helper for consumer endpoints
+ private SubscriptionHelper subscriptionHelper;
+
+ protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
+ // get Operation from remaining URI
+ OperationName operationName = null;
+ String topicName = null;
+ try {
+ LOG.debug("Creating endpoint for ", remaining);
+ operationName = OperationName.fromValue(remaining);
+ } catch (IllegalArgumentException ex) {
+ // if its not an operation name, treat is as topic name for consumer endpoints
+ topicName = remaining;
+ }
+
+ // create endpoint config
+ if (config == null) {
+ config = new SalesforceEndpointConfig();
+ }
+ if (config.getHttpClient() == null) {
+ // set the component's httpClient as default
+ config.setHttpClient(httpClient);
+ }
+
+ // create a deep copy and map parameters
+ final SalesforceEndpointConfig copy = config.copy();
+ setProperties(copy, parameters);
+
+ final SalesforceEndpoint endpoint = new SalesforceEndpoint(uri, this, copy,
+ operationName, topicName);
+
+ // map remaining parameters to endpoint (specifically, synchronous)
+ setProperties(endpoint, parameters);
+
+ return endpoint;
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ super.doStart();
+
+ // validate properties
+ ObjectHelper.notNull(loginConfig, "loginConfig");
+
+ // create a Jetty HttpClient if not already set
+ if (null == httpClient) {
+ if (config != null && config.getHttpClient() != null) {
+ httpClient = config.getHttpClient();
+ } else {
+ httpClient = new HttpClient();
+ httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
+ httpClient.setMaxConnectionsPerAddress(MAX_CONNECTIONS_PER_ADDRESS);
+ httpClient.setConnectTimeout(CONNECTION_TIMEOUT);
+ httpClient.setTimeout(RESPONSE_TIMEOUT);
+ }
+ }
+
+ // add redirect listener to handle Salesforce redirects
+ // this is ok to do since the RedirectListener is in the same classloader as Jetty client
+ String listenerClass = RedirectListener.class.getName();
+ if (httpClient.getRegisteredListeners() == null ||
+ !httpClient.getRegisteredListeners().contains(listenerClass)) {
+ httpClient.registerListener(listenerClass);
+ }
+ // SalesforceSecurityListener can't be registered the same way
+ // since Jetty HttpClient's Class.forName() can't see it
+
+ // start the Jetty client to initialize thread pool, etc.
+ httpClient.start();
+
+ // support restarts
+ if (null == this.session) {
+ this.session = new SalesforceSession(httpClient, loginConfig);
+ }
+
+ // login at startup if lazyLogin is disabled
+ if (!loginConfig.isLazyLogin()) {
+ ServiceHelper.startService(session);
+ }
+
+ if (packages != null && packages.length > 0) {
+ // parse the packages to create SObject name to class map
+ classMap = parsePackages();
+ } else {
+ // use an empty map to avoid NPEs later
+ LOG.warn("Missing property packages, getSObject* operations will NOT work");
+ classMap = Collections.unmodifiableMap(new HashMap<String, Class<?>>());
+ }
+
+ if (subscriptionHelper != null) {
+ ServiceHelper.startService(subscriptionHelper);
+ }
+ }
+
+ private Map<String, Class<?>> parsePackages() {
+ Map<String, Class<?>> result = new HashMap<String, Class<?>>();
+ Set<Class<?>> classes = getCamelContext().getPackageScanClassResolver().findImplementations(AbstractSObjectBase.class, packages);
+ for (Class<?> aClass : classes) {
+ // findImplementations also returns AbstractSObjectBase for some reason!!!
+ if (AbstractSObjectBase.class != aClass) {
+ result.put(aClass.getSimpleName(), aClass);
+ }
+ }
+
+ return Collections.unmodifiableMap(result);
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ super.doStop();
+
+ try {
+ if (subscriptionHelper != null) {
+ // shutdown all streaming connections
+ // note that this is done in the component, and not in consumer
+ ServiceHelper.stopService(subscriptionHelper);
+ }
+ if (session != null && session.getAccessToken() != null) {
+ try {
+ // logout of Salesforce
+ ServiceHelper.stopService(session);
+ } catch (SalesforceException ignored) {
+ }
+ }
+ } finally {
+ if (httpClient != null) {
+ // shutdown http client connections
+ httpClient.stop();
+ }
+ }
+ }
+
+ public SubscriptionHelper getSubscriptionHelper() throws Exception {
+ if (subscriptionHelper == null) {
+ // lazily create subscription helper
+ subscriptionHelper = new SubscriptionHelper(this);
+
+ // also start the helper to connect to Salesforce
+ ServiceHelper.startService(subscriptionHelper);
+ }
+ return subscriptionHelper;
+ }
+
+ public SalesforceLoginConfig getLoginConfig() {
+ return loginConfig;
+ }
+
+ public void setLoginConfig(SalesforceLoginConfig loginConfig) {
+ this.loginConfig = loginConfig;
+ }
+
+ public SalesforceEndpointConfig getConfig() {
+ return config;
+ }
+
+ public void setConfig(SalesforceEndpointConfig config) {
+ this.config = config;
+ }
+
+ public String[] getPackages() {
+ return packages;
+ }
+
+ public void setPackages(String[] packages) {
+ this.packages = packages;
+ }
+
+ public SalesforceSession getSession() {
+ return session;
+ }
+
+ public Map<String, Class<?>> getClassMap() {
+ return classMap;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0c401b9f/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceConsumer.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceConsumer.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceConsumer.java
new file mode 100644
index 0000000..9fa1b91
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceConsumer.java
@@ -0,0 +1,215 @@
+/**
+ * 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.salesforce;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.impl.DefaultConsumer;
+import org.apache.camel.util.ServiceHelper;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.cometd.bayeux.Message;
+import org.cometd.bayeux.client.ClientSessionChannel;
+import org.apache.camel.component.salesforce.internal.client.DefaultRestClient;
+import org.apache.camel.component.salesforce.internal.streaming.PushTopicHelper;
+import org.apache.camel.component.salesforce.internal.client.RestClient;
+import org.apache.camel.component.salesforce.internal.streaming.SubscriptionHelper;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The Salesforce consumer.
+ */
+public class SalesforceConsumer extends DefaultConsumer {
+
+ private static final ObjectMapper objectMapper = new ObjectMapper();
+ private static final String EVENT_PROPERTY = "event";
+ private static final String TYPE_PROPERTY = "type";
+ private static final String CREATED_DATE_PROPERTY = "createdDate";
+ private static final String SOBJECT_PROPERTY = "sobject";
+ private static final double MINIMUM_VERSION = 24.0;
+
+ private final SalesforceEndpoint endpoint;
+ public final SubscriptionHelper subscriptionHelper;
+
+ private final String topicName;
+ private final Class<?> sObjectClass;
+ private boolean subscribed;
+
+ public SalesforceConsumer(SalesforceEndpoint endpoint, Processor processor, SubscriptionHelper helper) {
+ super(endpoint, processor);
+ this.endpoint = endpoint;
+
+ // check minimum supported API version
+ if (Double.valueOf(endpoint.getConfiguration().getApiVersion()) < MINIMUM_VERSION) {
+ throw new IllegalArgumentException("Minimum supported API version for consumer endpoints is " + 24.0);
+ }
+
+ this.topicName = endpoint.getTopicName();
+ this.subscriptionHelper = helper;
+
+ // get sObjectClass to convert to
+ final String sObjectName = endpoint.getConfiguration().getSObjectName();
+ if (sObjectName != null) {
+ sObjectClass = endpoint.getComponent().getClassMap().get(sObjectName);
+ if (sObjectClass == null) {
+ throw new IllegalArgumentException(String.format("SObject Class not found for %s", sObjectName));
+ }
+ } else {
+ final String className = endpoint.getConfiguration().getSObjectClass();
+ if (className != null) {
+ sObjectClass = endpoint.getComponent().getCamelContext().getClassResolver().resolveClass(className);
+ if (sObjectClass == null) {
+ throw new IllegalArgumentException(String.format("SObject Class not found %s", className));
+ }
+ } else {
+ log.warn("Property sObjectName or sObjectClass NOT set, messages will be of type java.lang.Map");
+ sObjectClass = null;
+ }
+ }
+
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ super.doStart();
+
+ final SalesforceEndpointConfig config = endpoint.getConfiguration();
+
+ // is a query configured in the endpoint?
+ if (config.getSObjectQuery() != null) {
+ // Note that we don't lookup topic if the query is not specified
+ // create REST client for PushTopic operations
+ SalesforceComponent component = endpoint.getComponent();
+ RestClient restClient = new DefaultRestClient(component.getConfig().getHttpClient(),
+ endpoint.getConfiguration().getApiVersion(), "json", component.getSession());
+ // don't forget to start the client
+ ServiceHelper.startService(restClient);
+
+ try {
+ PushTopicHelper helper = new PushTopicHelper(config, topicName, restClient);
+ helper.createOrUpdateTopic();
+ } finally {
+ // don't forget to stop the client
+ ServiceHelper.stopService(restClient);
+ }
+ }
+
+ // subscribe to topic
+ subscriptionHelper.subscribe(topicName, this);
+ subscribed = true;
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ super.doStop();
+
+ if (subscribed) {
+ subscribed = false;
+ // unsubscribe from topic
+ subscriptionHelper.unsubscribe(topicName, this);
+ }
+ }
+
+ public void processMessage(ClientSessionChannel channel, Message message) {
+ final Exchange exchange = endpoint.createExchange();
+ org.apache.camel.Message in = exchange.getIn();
+ setHeaders(in, message);
+
+ // get event data
+ // TODO do we need to add NPE checks for message/data.get***???
+ Map<String, Object> data = message.getDataAsMap();
+
+ @SuppressWarnings("unchecked") final
+ Map<String, Object> event = (Map<String, Object>) data.get(EVENT_PROPERTY);
+ final Object eventType = event.get(TYPE_PROPERTY);
+ Object createdDate = event.get(CREATED_DATE_PROPERTY);
+ if (log.isDebugEnabled()) {
+ log.debug(String.format("Received event %s on channel %s created on %s",
+ eventType, channel.getChannelId(), createdDate));
+ }
+
+ in.setHeader("CamelSalesforceEventType", eventType);
+ in.setHeader("CamelSalesforceCreatedDate", createdDate);
+
+ // get SObject
+ @SuppressWarnings("unchecked")
+ final Map<String, Object> sObject = (Map<String, Object>) data.get(SOBJECT_PROPERTY);
+ try {
+
+ final String sObjectString = objectMapper.writeValueAsString(sObject);
+ log.debug("Received SObject: {}", sObjectString);
+
+ if (sObjectClass == null) {
+ // return sobject map as exchange body
+ in.setBody(sObject);
+ } else {
+ // create the expected SObject
+ in.setBody(objectMapper.readValue(
+ new StringReader(sObjectString), sObjectClass));
+ }
+ } catch (IOException e) {
+ final String msg = String.format("Error parsing message [%s] from Topic %s: %s",
+ message, topicName, e.getMessage());
+ handleException(msg, new RuntimeCamelException(msg, e));
+ }
+
+ try {
+ getAsyncProcessor().process(exchange, new AsyncCallback() {
+ public void done(boolean doneSync) {
+ // noop
+ if (log.isTraceEnabled()) {
+ log.trace("Done processing event: {} {}", eventType.toString(),
+ doneSync ? "synchronously" : "asynchronously");
+ }
+ }
+ });
+ } catch (Exception e) {
+ handleException(String.format("Error processing %s: %s", exchange, e.getMessage()), e);
+ } finally {
+ Exception ex = exchange.getException();
+ if (ex != null) {
+ handleException(String.format("Unhandled exception: %s", ex.getMessage()), ex);
+ }
+ }
+ }
+
+ private void setHeaders(org.apache.camel.Message in, Message message) {
+ Map<String, Object> headers = new HashMap<String, Object>();
+ // set topic name
+ headers.put("CamelSalesforceTopicName", topicName);
+ // set message properties as headers
+ headers.put("CamelSalesforceChannel", message.getChannel());
+ headers.put("CamelSalesforceClientId", message.getClientId());
+
+ in.setHeaders(headers);
+ }
+
+ @Override
+ public void handleException(String message, Throwable t) {
+ super.handleException(message, t);
+ }
+
+ public String getTopicName() {
+ return topicName;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0c401b9f/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpoint.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpoint.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpoint.java
new file mode 100644
index 0000000..24874bb
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpoint.java
@@ -0,0 +1,96 @@
+/**
+ * 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.salesforce;
+
+import org.apache.camel.Consumer;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.impl.DefaultEndpoint;
+import org.apache.camel.impl.SynchronousDelegateProducer;
+import org.apache.camel.component.salesforce.internal.OperationName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Represents a Salesforce endpoint.
+ */
+public class SalesforceEndpoint extends DefaultEndpoint {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SalesforceEndpoint.class);
+
+ private final SalesforceEndpointConfig config;
+ private final OperationName operationName;
+ private final String topicName;
+
+ public SalesforceEndpoint(String uri, SalesforceComponent salesforceComponent,
+ SalesforceEndpointConfig config, OperationName operationName, String topicName) {
+ super(uri, salesforceComponent);
+
+ this.config = config;
+ this.operationName = operationName;
+ this.topicName = topicName;
+ }
+
+ public Producer createProducer() throws Exception {
+ // producer requires an operation, topicName must be the invalid operation name
+ if (operationName == null) {
+ throw new IllegalArgumentException(String.format("Invalid Operation %s", topicName));
+ }
+
+ SalesforceProducer producer = new SalesforceProducer(this);
+ if (isSynchronous()) {
+ return new SynchronousDelegateProducer(producer);
+ } else {
+ return producer;
+ }
+ }
+
+ public Consumer createConsumer(Processor processor) throws Exception {
+ // consumer requires a topicName, operation name must be the invalid topic name
+ if (topicName == null) {
+ throw new IllegalArgumentException(String.format("Invalid topic name %s, matches a producer operation name",
+ operationName.value()));
+ }
+
+ return new SalesforceConsumer(this, processor,
+ getComponent().getSubscriptionHelper());
+ }
+
+ @Override
+ public SalesforceComponent getComponent() {
+ return (SalesforceComponent) super.getComponent();
+ }
+
+ public boolean isSingleton() {
+ // re-use endpoint instance across multiple threads
+ // the description of this method is a little confusing
+ return true;
+ }
+
+ public SalesforceEndpointConfig getConfiguration() {
+ return config;
+ }
+
+ public OperationName getOperationName() {
+ return operationName;
+ }
+
+ public String getTopicName() {
+ return topicName;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0c401b9f/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java
new file mode 100644
index 0000000..817871b
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java
@@ -0,0 +1,292 @@
+/**
+ * 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.salesforce;
+
+import org.apache.camel.RuntimeCamelException;
+import org.eclipse.jetty.client.HttpClient;
+import org.apache.camel.component.salesforce.api.dto.bulk.ContentType;
+import org.apache.camel.component.salesforce.api.dto.bulk.OperationEnum;
+import org.apache.camel.component.salesforce.internal.PayloadFormat;
+import org.apache.camel.component.salesforce.internal.dto.NotifyForFieldsEnum;
+import org.apache.camel.component.salesforce.internal.dto.NotifyForOperationsEnum;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class SalesforceEndpointConfig implements Cloneable {
+
+ // default API version
+ static final String DEFAULT_VERSION = "27.0";
+
+ // general parameter
+ public static final String API_VERSION = "apiVersion";
+
+ // parameters for Rest API
+ public static final String FORMAT = "format";
+ public static final String SOBJECT_NAME = "sObjectName";
+ public static final String SOBJECT_ID = "sObjectId";
+ public static final String SOBJECT_FIELDS = "sObjectFields";
+ public static final String SOBJECT_EXT_ID_NAME = "sObjectIdName";
+ public static final String SOBJECT_EXT_ID_VALUE = "sObjectIdValue";
+ public static final String SOBJECT_BLOB_FIELD_NAME = "sObjectBlobFieldName";
+ public static final String SOBJECT_CLASS = "sObjectClass";
+ public static final String SOBJECT_QUERY = "sObjectQuery";
+ public static final String SOBJECT_SEARCH = "sObjectSearch";
+
+ // parameters for Bulk API
+ public static final String BULK_OPERATION = "bulkOperation";
+ public static final String CONTENT_TYPE = "contentType";
+ public static final String JOB_ID = "jobId";
+ public static final String BATCH_ID = "batchId";
+ public static final String RESULT_ID = "resultId";
+
+ // parameters for Streaming API
+ public static final String UPDATE_TOPIC = "updateTopic";
+
+ // general properties
+ private String apiVersion = DEFAULT_VERSION;
+
+ // Rest API properties
+ private PayloadFormat format = PayloadFormat.JSON;
+ private String sObjectName;
+ private String sObjectId;
+ private String sObjectFields;
+ private String sObjectIdName;
+ private String sObjectIdValue;
+ private String sObjectBlobFieldName;
+ private String sObjectClass;
+ private String sObjectQuery;
+ private String sObjectSearch;
+
+ // Bulk API properties
+ private OperationEnum bulkOperation;
+ private ContentType contentType;
+ private String jobId;
+ private String batchId;
+ private String resultId;
+
+ // Streaming API properties
+ private boolean updateTopic;
+ private NotifyForFieldsEnum notifyForFields;
+ private NotifyForOperationsEnum notifyForOperations;
+
+ // Jetty HttpClient, set using reference
+ private HttpClient httpClient;
+
+ public SalesforceEndpointConfig copy() {
+ try {
+ final SalesforceEndpointConfig copy = (SalesforceEndpointConfig) super.clone();
+ // nothing to deep copy
+ return copy;
+ } catch (CloneNotSupportedException ex) {
+ throw new RuntimeCamelException(ex);
+ }
+ }
+
+ public PayloadFormat getPayloadFormat() {
+ return format;
+ }
+
+ public void setFormat(String format) {
+ this.format = PayloadFormat.valueOf(format.toUpperCase());
+ }
+
+ public String getApiVersion() {
+ return apiVersion;
+ }
+
+ public void setApiVersion(String apiVersion) {
+ this.apiVersion = apiVersion;
+ }
+
+ public String getSObjectName() {
+ return sObjectName;
+ }
+
+ public void setSObjectName(String sObjectName) {
+ this.sObjectName = sObjectName;
+ }
+
+ public String getSObjectId() {
+ return sObjectId;
+ }
+
+ public void setSObjectId(String sObjectId) {
+ this.sObjectId = sObjectId;
+ }
+
+ public String getSObjectFields() {
+ return sObjectFields;
+ }
+
+ public void setSObjectFields(String sObjectFields) {
+ this.sObjectFields = sObjectFields;
+ }
+
+ public String getSObjectIdName() {
+ return sObjectIdName;
+ }
+
+ public void setSObjectIdName(String sObjectIdName) {
+ this.sObjectIdName = sObjectIdName;
+ }
+
+ public String getSObjectIdValue() {
+ return sObjectIdValue;
+ }
+
+ public void setSObjectIdValue(String sObjectIdValue) {
+ this.sObjectIdValue = sObjectIdValue;
+ }
+
+ public String getSObjectBlobFieldName() {
+ return sObjectBlobFieldName;
+ }
+
+ public void setSObjectBlobFieldName(String sObjectBlobFieldName) {
+ this.sObjectBlobFieldName = sObjectBlobFieldName;
+ }
+
+ public String getSObjectClass() {
+ return sObjectClass;
+ }
+
+ public void setSObjectClass(String sObjectClass) {
+ this.sObjectClass = sObjectClass;
+ }
+
+ public String getSObjectQuery() {
+ return sObjectQuery;
+ }
+
+ public void setSObjectQuery(String sObjectQuery) {
+ this.sObjectQuery = sObjectQuery;
+ }
+
+ public String getSObjectSearch() {
+ return sObjectSearch;
+ }
+
+ public void setSObjectSearch(String sObjectSearch) {
+ this.sObjectSearch = sObjectSearch;
+ }
+
+ public OperationEnum getBulkOperation() {
+ return bulkOperation;
+ }
+
+ public void setBulkOperation(OperationEnum bulkOperation) {
+ this.bulkOperation = bulkOperation;
+ }
+
+ public ContentType getContentType() {
+ return contentType;
+ }
+
+ public void setContentType(ContentType contentType) {
+ this.contentType = contentType;
+ }
+
+ public String getJobId() {
+ return jobId;
+ }
+
+ public void setJobId(String jobId) {
+ this.jobId = jobId;
+ }
+
+ public String getBatchId() {
+ return batchId;
+ }
+
+ public void setBatchId(String batchId) {
+ this.batchId = batchId;
+ }
+
+ public String getResultId() {
+ return resultId;
+ }
+
+ public void setResultId(String resultId) {
+ this.resultId = resultId;
+ }
+
+ public boolean isUpdateTopic() {
+ return updateTopic;
+ }
+
+ public void setUpdateTopic(boolean updateTopic) {
+ this.updateTopic = updateTopic;
+ }
+
+ public NotifyForFieldsEnum getNotifyForFields() {
+ return notifyForFields;
+ }
+
+ public void setNotifyForFields(NotifyForFieldsEnum notifyForFields) {
+ this.notifyForFields = notifyForFields;
+ }
+
+ public NotifyForOperationsEnum getNotifyForOperations() {
+ return notifyForOperations;
+ }
+
+ public void setNotifyForOperations(NotifyForOperationsEnum notifyForOperations) {
+ this.notifyForOperations = notifyForOperations;
+ }
+
+ public void setHttpClient(HttpClient httpClient) {
+ this.httpClient = httpClient;
+ }
+
+ public HttpClient getHttpClient() {
+ return httpClient;
+ }
+
+ public Map<String, String> toValueMap() {
+
+ final Map<String, String> valueMap = new HashMap<String, String>();
+ valueMap.put(FORMAT, format.toString().toLowerCase());
+ valueMap.put(API_VERSION, apiVersion);
+
+ valueMap.put(SOBJECT_NAME, sObjectName);
+ valueMap.put(SOBJECT_ID, sObjectId);
+ valueMap.put(SOBJECT_FIELDS, sObjectFields);
+ valueMap.put(SOBJECT_EXT_ID_NAME, sObjectIdName);
+ valueMap.put(SOBJECT_BLOB_FIELD_NAME, sObjectBlobFieldName);
+ valueMap.put(SOBJECT_EXT_ID_VALUE, sObjectIdValue);
+ valueMap.put(SOBJECT_CLASS, sObjectClass);
+ valueMap.put(SOBJECT_QUERY, sObjectQuery);
+ valueMap.put(SOBJECT_SEARCH, sObjectSearch);
+
+ // add bulk API properties
+ if (bulkOperation != null) {
+ valueMap.put(BULK_OPERATION, bulkOperation.value());
+ }
+ if (contentType != null) {
+ valueMap.put(CONTENT_TYPE, contentType.value());
+ }
+ valueMap.put(JOB_ID, jobId);
+ valueMap.put(BATCH_ID, batchId);
+ valueMap.put(RESULT_ID, resultId);
+
+ valueMap.put(UPDATE_TOPIC, String.valueOf(updateTopic));
+
+ return Collections.unmodifiableMap(valueMap);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/camel/blob/0c401b9f/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceLoginConfig.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceLoginConfig.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceLoginConfig.java
new file mode 100644
index 0000000..a6a097f
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceLoginConfig.java
@@ -0,0 +1,99 @@
+/**
+ * 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.salesforce;
+
+/**
+ * Configuration object for Salesforce login properties
+ */
+public class SalesforceLoginConfig {
+
+ public static final String DEFAULT_LOGIN_URL = "https://login.salesforce.com";
+
+ private String loginUrl;
+ private String clientId;
+ private String clientSecret;
+ private String userName;
+ private String password;
+ // allow lazy login into Salesforce
+ // note that login issues may not surface until a message needs to be processed
+ private boolean lazyLogin;
+
+ public SalesforceLoginConfig() {
+ loginUrl = DEFAULT_LOGIN_URL;
+ lazyLogin = false;
+ }
+
+ public SalesforceLoginConfig(String loginUrl,
+ String clientId, String clientSecret,
+ String userName, String password, boolean lazyLogin) {
+ this.loginUrl = loginUrl;
+ this.clientId = clientId;
+ this.clientSecret = clientSecret;
+ this.userName = userName;
+ this.password = password;
+ this.lazyLogin = lazyLogin;
+ }
+
+ public String getLoginUrl() {
+ return loginUrl;
+ }
+
+ public void setLoginUrl(String loginUrl) {
+ this.loginUrl = loginUrl;
+ }
+
+ public String getClientId() {
+ return clientId;
+ }
+
+ public void setClientId(String clientId) {
+ this.clientId = clientId;
+ }
+
+ public String getClientSecret() {
+ return clientSecret;
+ }
+
+ public void setClientSecret(String clientSecret) {
+ this.clientSecret = clientSecret;
+ }
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public boolean isLazyLogin() {
+ return lazyLogin;
+ }
+
+ public void setLazyLogin(boolean lazyLogin) {
+ this.lazyLogin = lazyLogin;
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/camel/blob/0c401b9f/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceProducer.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceProducer.java
new file mode 100644
index 0000000..5cc4547
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceProducer.java
@@ -0,0 +1,102 @@
+/**
+ * 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.salesforce;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.Exchange;
+import org.apache.camel.impl.DefaultAsyncProducer;
+import org.apache.camel.util.ServiceHelper;
+import org.apache.camel.component.salesforce.api.SalesforceException;
+import org.apache.camel.component.salesforce.internal.OperationName;
+import org.apache.camel.component.salesforce.internal.PayloadFormat;
+import org.apache.camel.component.salesforce.internal.processor.BulkApiProcessor;
+import org.apache.camel.component.salesforce.internal.processor.JsonRestProcessor;
+import org.apache.camel.component.salesforce.internal.processor.SalesforceProcessor;
+import org.apache.camel.component.salesforce.internal.processor.XmlRestProcessor;
+
+/**
+ * The Salesforce producer.
+ */
+public class SalesforceProducer extends DefaultAsyncProducer {
+
+ private final SalesforceProcessor processor;
+
+ public SalesforceProducer(SalesforceEndpoint endpoint) throws SalesforceException {
+ super(endpoint);
+
+ final SalesforceEndpointConfig endpointConfig = endpoint.getConfiguration();
+ final PayloadFormat payloadFormat = endpointConfig.getPayloadFormat();
+
+ // check if its a Bulk Operation
+ if (isBulkOperation(endpoint.getOperationName())) {
+ processor = new BulkApiProcessor(endpoint);
+ } else {
+ // create an appropriate processor
+ if (payloadFormat == PayloadFormat.JSON) {
+ // create a JSON exchange processor
+ processor = new JsonRestProcessor(endpoint);
+ } else {
+ processor = new XmlRestProcessor(endpoint);
+ }
+ }
+ }
+
+ private boolean isBulkOperation(OperationName operationName) {
+ switch (operationName) {
+ case CREATE_JOB:
+ case GET_JOB:
+ case CLOSE_JOB:
+ case ABORT_JOB:
+ case CREATE_BATCH:
+ case GET_BATCH:
+ case GET_ALL_BATCHES:
+ case GET_REQUEST:
+ case GET_RESULTS:
+ case CREATE_BATCH_QUERY:
+ case GET_QUERY_RESULT_IDS:
+ case GET_QUERY_RESULT:
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public boolean process(Exchange exchange, AsyncCallback callback) {
+ log.debug("Processing {}",
+ ((SalesforceEndpoint) getEndpoint()).getOperationName());
+ return processor.process(exchange, callback);
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ super.doStart();
+
+ // start Salesforce processor
+ ServiceHelper.startService(processor);
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ // stop Salesforce processor
+ ServiceHelper.stopService(processor);
+
+ super.doStop();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0c401b9f/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/JodaTimeConverter.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/JodaTimeConverter.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/JodaTimeConverter.java
new file mode 100644
index 0000000..372e7a4
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/JodaTimeConverter.java
@@ -0,0 +1,64 @@
+/**
+ * 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.salesforce.api;
+
+import com.thoughtworks.xstream.converters.Converter;
+import com.thoughtworks.xstream.converters.MarshallingContext;
+import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.joda.time.format.DateTimeFormatter;
+import org.joda.time.format.ISODateTimeFormat;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Constructor;
+
+public class JodaTimeConverter implements Converter {
+ private static final Logger LOG = LoggerFactory.getLogger(JodaTimeConverter.class);
+ private final DateTimeFormatter formatter = ISODateTimeFormat.dateTime();
+
+ @Override
+ public void marshal(Object o, HierarchicalStreamWriter writer, MarshallingContext context) {
+ DateTime dateTime = (DateTime) o;
+ writer.setValue(formatter.print(dateTime));
+ }
+
+ @Override
+ public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
+ String dateTimeStr = reader.getValue();
+ Class<?> requiredType = context.getRequiredType();
+ try {
+ Constructor<?> constructor = requiredType.getConstructor(Object.class, DateTimeZone.class);
+ // normalize date time to UTC
+ return constructor.newInstance(dateTimeStr, DateTimeZone.UTC);
+ } catch (Exception e) {
+ throw new IllegalArgumentException(
+ String.format("Error reading Joda DateTime from value %s: %s",
+ dateTimeStr, e.getMessage()),
+ e);
+ }
+ }
+
+ @Override
+ public boolean canConvert(Class aClass) {
+ return DateTime.class.isAssignableFrom(aClass);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0c401b9f/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/PicklistEnumConverter.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/PicklistEnumConverter.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/PicklistEnumConverter.java
new file mode 100644
index 0000000..06d0ca5
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/PicklistEnumConverter.java
@@ -0,0 +1,80 @@
+/**
+ * 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.salesforce.api;
+
+import com.thoughtworks.xstream.converters.Converter;
+import com.thoughtworks.xstream.converters.MarshallingContext;
+import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Method;
+
+public class PicklistEnumConverter implements Converter {
+ private static final Logger LOG = LoggerFactory.getLogger(PicklistEnumConverter.class);
+ private static final String FACTORY_METHOD = "fromValue";
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void marshal(Object o, HierarchicalStreamWriter writer, MarshallingContext context) {
+ Class<?> aClass = o.getClass();
+ try {
+ Method getterMethod = aClass.getMethod("value");
+ writer.setValue((String) getterMethod.invoke(o));
+ } catch (ReflectiveOperationException e) {
+ throw new IllegalArgumentException(
+ String.format("Exception writing pick list value %s of type %s: %s",
+ o, o.getClass().getName(), e.getMessage()),
+ e);
+ }
+ }
+
+ @Override
+ public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
+ String value = reader.getValue();
+ Class<?> requiredType = context.getRequiredType();
+ try {
+ Method factoryMethod = requiredType.getMethod(FACTORY_METHOD, String.class);
+ // use factory method to create object
+ return factoryMethod.invoke(null, value);
+ } catch (ReflectiveOperationException e) {
+ throw new IllegalArgumentException(
+ String.format("Exception reading pick list value %s of type %s: %s",
+ value, context.getRequiredType().getName(), e.getMessage()),
+ e);
+ } catch (SecurityException e) {
+ throw new IllegalArgumentException(
+ String.format("Security Exception reading pick list value %s of type %s: %s",
+ value, context.getRequiredType().getName(), e.getMessage()),
+ e);
+ }
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public boolean canConvert(Class aClass) {
+ try {
+ return Enum.class.isAssignableFrom(aClass) &&
+ aClass.getMethod(FACTORY_METHOD, String.class) != null;
+ } catch (NoSuchMethodException e) {
+ return false;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0c401b9f/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceException.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceException.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceException.java
new file mode 100644
index 0000000..760eebe
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceException.java
@@ -0,0 +1,104 @@
+/**
+ * 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.salesforce.api;
+
+import org.apache.camel.CamelException;
+import org.apache.camel.component.salesforce.api.dto.RestError;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class SalesforceException extends CamelException {
+
+ private List<RestError> errors;
+ private int statusCode;
+
+ public SalesforceException(List<RestError> errors, int statusCode) {
+ this(toErrorMessage(errors, statusCode), statusCode);
+
+ this.errors = errors;
+ }
+
+ public SalesforceException(String message, int statusCode) {
+ super(message);
+
+ this.statusCode = statusCode;
+ }
+
+ public SalesforceException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public SalesforceException(Throwable cause) {
+ super(cause);
+ }
+
+ public List<RestError> getErrors() {
+ return Collections.unmodifiableList(errors);
+ }
+
+ public void setErrors(List<RestError> errors) {
+ if (this.errors != null) {
+ this.errors.clear();
+ } else {
+ this.errors = new ArrayList<RestError>();
+ }
+ this.errors.addAll(errors);
+ }
+
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ public void setStatusCode(int statusCode) {
+ this.statusCode = statusCode;
+ }
+
+ @Override
+ public String toString() {
+ if (errors != null) {
+ return toErrorMessage(errors, statusCode);
+ } else {
+ // make sure we include the custom message
+ final StringBuilder builder = new StringBuilder("{ ");
+ builder.append(getMessage());
+ builder.append(", statusCode: ");
+ builder.append(statusCode);
+ builder.append("}");
+
+ return builder.toString();
+ }
+ }
+
+ private static String toErrorMessage(List<RestError> errors, int statusCode) {
+ StringBuilder builder = new StringBuilder("{ ");
+ if (errors != null) {
+ builder.append(" errors: [");
+ for (RestError error : errors) {
+ builder.append(error.toString());
+ }
+ builder.append("], ");
+ }
+ builder.append("statusCode: ");
+ builder.append(statusCode);
+ builder.append("}");
+
+ return builder.toString();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0c401b9f/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/AbstractDTOBase.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/AbstractDTOBase.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/AbstractDTOBase.java
new file mode 100644
index 0000000..e4723ae
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/AbstractDTOBase.java
@@ -0,0 +1,40 @@
+/**
+ * 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.salesforce.api.dto;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+
+import java.io.IOException;
+import java.io.StringWriter;
+
+// disable null values in json output
+@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
+public abstract class AbstractDTOBase {
+ private final static ObjectMapper mapper = new ObjectMapper();
+
+ @Override
+ public String toString() {
+ try {
+ StringWriter writer = new StringWriter();
+ mapper.writeValue(writer, this);
+ return writer.toString();
+ } catch (IOException e) {
+ return "Error in toString " + e.getMessage();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0c401b9f/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/AbstractQueryRecordsBase.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/AbstractQueryRecordsBase.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/AbstractQueryRecordsBase.java
new file mode 100644
index 0000000..ddfa6bf
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/AbstractQueryRecordsBase.java
@@ -0,0 +1,72 @@
+/**
+ * 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.salesforce.api.dto;
+
+/**
+ * Abstract base DTO for Salesforce SOQL Query records.
+ * <p>
+ * Derived classes must follow the template below:
+ * </p>
+ * <pre>
+ * {@code
+ * public class QueryResultMySObject extends AbstractQueryRecordsBase {
+ * @XStreamImplicit
+ * private List<MySObject> records;
+ *
+ * public List<MySObject> getRecords() {
+ * return records;
+ * }
+ *
+ * public void setRecords(List<MySObject> records) {
+ * this.records = records;
+ * }
+ *
+ * }
+ * }
+ * </pre>
+ */
+public abstract class AbstractQueryRecordsBase extends AbstractDTOBase {
+
+ private Boolean done;
+ private int totalSize;
+ private String nextRecordsUrl;
+
+ public Boolean getDone() {
+ return done;
+ }
+
+ public void setDone(Boolean done) {
+ this.done = done;
+ }
+
+ public int getTotalSize() {
+ return totalSize;
+ }
+
+ public void setTotalSize(int totalSize) {
+ this.totalSize = totalSize;
+ }
+
+ public String getNextRecordsUrl() {
+ return nextRecordsUrl;
+ }
+
+ public void setNextRecordsUrl(String nextRecordsUrl) {
+ this.nextRecordsUrl = nextRecordsUrl;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0c401b9f/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/AbstractSObjectBase.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/AbstractSObjectBase.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/AbstractSObjectBase.java
new file mode 100644
index 0000000..c236872
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/AbstractSObjectBase.java
@@ -0,0 +1,172 @@
+/**
+ * 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.salesforce.api.dto;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.joda.time.DateTime;
+
+public class AbstractSObjectBase extends AbstractDTOBase {
+
+ private Attributes attributes;
+
+ private String Id;
+
+ private String OwnerId;
+
+ private Boolean IsDeleted;
+
+ private String Name;
+
+ private DateTime CreatedDate;
+
+ private String CreatedById;
+
+ private DateTime LastModifiedDate;
+
+ private String LastModifiedById;
+
+ private DateTime SystemModstamp;
+
+ private String LastActivityDate;
+
+ /**
+ * Utility method to clear all {@link AbstractSObjectBase} fields.
+ * <p>Used when reusing a DTO for a new record.</p>
+ */
+ public final void clearBaseFields() {
+ attributes = null;
+ Id = null;
+ OwnerId = null;
+ IsDeleted = null;
+ Name = null;
+ CreatedDate = null;
+ CreatedById = null;
+ LastModifiedDate = null;
+ LastModifiedById = null;
+ SystemModstamp = null;
+ LastActivityDate = null;
+ }
+
+ public Attributes getAttributes() {
+ return attributes;
+ }
+
+ public void setAttributes(Attributes attributes) {
+ this.attributes = attributes;
+ }
+
+ @JsonProperty("Id")
+ public String getId() {
+ return Id;
+ }
+
+ @JsonProperty("Id")
+ public void setId(String id) {
+ Id = id;
+ }
+
+ @JsonProperty("OwnerId")
+ public String getOwnerId() {
+ return OwnerId;
+ }
+
+ @JsonProperty("OwnerId")
+ public void setOwnerId(String ownerId) {
+ OwnerId = ownerId;
+ }
+
+ @JsonProperty("IsDeleted")
+ public Boolean isIsDeleted() {
+ return IsDeleted;
+ }
+
+ @JsonProperty("IsDeleted")
+ public void setIsDeleted(Boolean isDeleted) {
+ IsDeleted = isDeleted;
+ }
+
+ @JsonProperty("Name")
+ public String getName() {
+ return Name;
+ }
+
+ @JsonProperty("Name")
+ public void setName(String name) {
+ Name = name;
+ }
+
+ @JsonProperty("CreatedDate")
+ public DateTime getCreatedDate() {
+ return CreatedDate;
+ }
+
+ @JsonProperty("CreatedDate")
+ public void setCreatedDate(DateTime createdDate) {
+ CreatedDate = createdDate;
+ }
+
+ @JsonProperty("CreatedById")
+ public String getCreatedById() {
+ return CreatedById;
+ }
+
+ @JsonProperty("CreatedById")
+ public void setCreatedById(String createdById) {
+ CreatedById = createdById;
+ }
+
+ @JsonProperty("LastModifiedDate")
+ public DateTime getLastModifiedDate() {
+ return LastModifiedDate;
+ }
+
+ @JsonProperty("LastModifiedDate")
+ public void setLastModifiedDate(DateTime lastModifiedDate) {
+ LastModifiedDate = lastModifiedDate;
+ }
+
+ @JsonProperty("LastModifiedById")
+ public String getLastModifiedById() {
+ return LastModifiedById;
+ }
+
+ @JsonProperty("LastModifiedById")
+ public void setLastModifiedById(String lastModifiedById) {
+ LastModifiedById = lastModifiedById;
+ }
+
+ @JsonProperty("SystemModstamp")
+ public DateTime getSystemModstamp() {
+ return SystemModstamp;
+ }
+
+ @JsonProperty("SystemModstamp")
+ public void setSystemModstamp(DateTime systemModstamp) {
+ SystemModstamp = systemModstamp;
+ }
+
+ @JsonProperty("LastActivityDate")
+ public String getLastActivityDate() {
+ return LastActivityDate;
+ }
+
+ @JsonProperty("LastActivityDate")
+ public void setLastActivityDate(String lastActivityDate) {
+ LastActivityDate = lastActivityDate;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0c401b9f/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/Attributes.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/Attributes.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/Attributes.java
new file mode 100644
index 0000000..439f4c3
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/Attributes.java
@@ -0,0 +1,38 @@
+/**
+ * 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.salesforce.api.dto;
+
+public class Attributes extends AbstractDTOBase {
+ private String type;
+ private String url;
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0c401b9f/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/ChildRelationShip.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/ChildRelationShip.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/ChildRelationShip.java
new file mode 100644
index 0000000..4c2d58e
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/ChildRelationShip.java
@@ -0,0 +1,74 @@
+/**
+ * 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.salesforce.api.dto;
+
+public class ChildRelationShip extends AbstractDTOBase {
+ private String field;
+ private Boolean deprecatedAndHidden;
+ private String relationshipName;
+ private Boolean cascadeDelete;
+ private Boolean restrictedDelete;
+ private String childSObject;
+
+ public String getField() {
+ return field;
+ }
+
+ public void setField(String field) {
+ this.field = field;
+ }
+
+ public Boolean isDeprecatedAndHidden() {
+ return deprecatedAndHidden;
+ }
+
+ public void setDeprecatedAndHidden(Boolean deprecatedAndHidden) {
+ this.deprecatedAndHidden = deprecatedAndHidden;
+ }
+
+ public String getRelationshipName() {
+ return relationshipName;
+ }
+
+ public void setRelationshipName(String relationshipName) {
+ this.relationshipName = relationshipName;
+ }
+
+ public Boolean isCascadeDelete() {
+ return cascadeDelete;
+ }
+
+ public void setCascadeDelete(Boolean cascadeDelete) {
+ this.cascadeDelete = cascadeDelete;
+ }
+
+ public Boolean isRestrictedDelete() {
+ return restrictedDelete;
+ }
+
+ public void setRestrictedDelete(Boolean restrictedDelete) {
+ this.restrictedDelete = restrictedDelete;
+ }
+
+ public String getChildSObject() {
+ return childSObject;
+ }
+
+ public void setChildSObject(String childSObject) {
+ this.childSObject = childSObject;
+ }
+}