CAMEL-10357: camel-servicenow: add per release model
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/f655c941 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/f655c941 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/f655c941 Branch: refs/heads/camel-2.18.x Commit: f655c94110ae14a3db5b2ce6409684deaa619846 Parents: 9916ee4 Author: lburgazzoli <lburgazz...@gmail.com> Authored: Thu Sep 29 19:25:18 2016 +0200 Committer: lburgazzoli <lburgazz...@gmail.com> Committed: Tue Oct 11 11:25:05 2016 +0200 ---------------------------------------------------------------------- .../src/main/docs/servicenow-component.adoc | 242 ++++++++++++----- .../servicenow/AbstractServiceNowProcessor.java | 265 +++++++++++++++++++ .../servicenow/AbstractServiceNowProducer.java | 40 +++ .../component/servicenow/ServiceNowClient.java | 140 ++++++++++ .../servicenow/ServiceNowComponent.java | 10 +- .../servicenow/ServiceNowConfiguration.java | 217 +++++++++++++++ .../servicenow/ServiceNowConstants.java | 88 +++--- .../servicenow/ServiceNowDispatcher.java | 55 ++++ .../servicenow/ServiceNowEndpoint.java | 46 +--- .../servicenow/ServiceNowExceptionMapper.java | 23 +- .../component/servicenow/ServiceNowParam.java | 28 ++ .../component/servicenow/ServiceNowParams.java | 123 +++++++++ .../servicenow/ServiceNowProducer.java | 86 +----- .../servicenow/ServiceNowProducerProcessor.java | 139 ---------- .../servicenow/ServiceNowProducerSupplier.java | 22 ++ .../component/servicenow/ServiceNowRelease.java | 41 +++ .../auth/AuthenticationRequestFilter.java | 4 +- .../component/servicenow/auth/OAuthToken.java | 8 +- .../servicenow/model/ServiceNowAggregate.java | 50 ---- .../model/ServiceNowAggregateProcessor.java | 68 ----- .../servicenow/model/ServiceNowImportSet.java | 48 ---- .../model/ServiceNowImportSetProcessor.java | 79 ------ .../servicenow/model/ServiceNowTable.java | 108 -------- .../model/ServiceNowTableProcessor.java | 169 ------------ .../fuji/FujiServiceNowAggregateProcessor.java | 68 +++++ .../fuji/FujiServiceNowImportSetProcessor.java | 77 ++++++ .../releases/fuji/FujiServiceNowProcessor.java | 55 ++++ .../releases/fuji/FujiServiceNowProducer.java | 36 +++ .../fuji/FujiServiceNowTableProcessor.java | 163 ++++++++++++ .../HelsinkiServiceNowAggregateProcessor.java | 74 ++++++ .../HelsinkiServiceNowAttachmentProcessor.java | 168 ++++++++++++ .../HelsinkiServiceNowImportSetProcessor.java | 82 ++++++ .../HelsinkiServiceNowMiscProcessor.java | 89 +++++++ .../helsinki/HelsinkiServiceNowProducer.java | 42 +++ .../HelsinkiServiceNowScorecardProcessor.java | 84 ++++++ ...iServiceNowServiceCatalogCartsProcessor.java | 200 ++++++++++++++ ...iceNowServiceCatalogCategoriesProcessor.java | 66 +++++ ...iServiceNowServiceCatalogItemsProcessor.java | 199 ++++++++++++++ ...lsinkiServiceNowServiceCatalogProcessor.java | 110 ++++++++ .../HelsinkiServiceNowTableProcessor.java | 191 +++++++++++++ .../servicenow/ServiceNowAttachmentTest.java | 133 ++++++++++ .../servicenow/ServiceNowScorecardTest.java | 67 +++++ .../ServiceNowServiceCatalogTest.java | 97 +++++++ .../servicenow/ServiceNowTableTest.java | 57 ++-- .../component/servicenow/ServiceNowTest.java | 10 +- .../servicenow/ServiceNowTestSupport.java | 7 +- .../servicenow/model/AttachmentMeta.java | 92 +++++++ .../component/servicenow/model/Incident.java | 1 + .../component/servicenow/model/Scorecard.java | 46 ++++ .../src/test/resources/my-content.txt | 16 ++ 50 files changed, 3411 insertions(+), 918 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/f655c941/components/camel-servicenow/src/main/docs/servicenow-component.adoc ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/docs/servicenow-component.adoc b/components/camel-servicenow/src/main/docs/servicenow-component.adoc index d4537fb..5869258 100644 --- a/components/camel-servicenow/src/main/docs/servicenow-component.adoc +++ b/components/camel-servicenow/src/main/docs/servicenow-component.adoc @@ -4,9 +4,10 @@ ServiceNow Component *Available as of Camel 2.18* -The ServiceNow component provides access to all of ServiceNow -https://developer.servicenow.com/app.do#!/rest_api_doc?v=fuji[REST -API]. +The ServiceNow component provides access to ServiceNow platform through their REST API. + +NOTE: From Camel 2.18.1 the component supports multiple version of ServiceNow platform with default to Helsinki. Supported version are <<ServiceNow-Fuji>> and <<ServiceNow-Helsinki>> + Maven users will need to add the following dependency to their pom.xml for this component: @@ -39,23 +40,36 @@ The ServiceNow component has no options. // component options: END - - // endpoint options: START -The ServiceNow component supports 16 endpoint options which are listed below: +The ServiceNow component supports 31 endpoint options which are listed below: {% raw %} [width="100%",cols="2,1,1m,1m,5",options="header"] |======================================================================= | Name | Group | Default | Java Type | Description | instanceName | producer | | String | *Required* The ServiceNow instance name +| display | producer | true | String | Set this parameter to true to return only scorecards where the indicator Display field is selected. Set this parameter to all to return scorecards with any Display field value. This parameter is true by default. | displayValue | producer | false | String | Return the display value (true) actual value (false) or both (all) for reference fields (default: false) | excludeReferenceLink | producer | | Boolean | True to exclude Table API links for reference fields (default: false) +| favorites | producer | | Boolean | Set this parameter to true to return only scorecards that are favorites of the querying user. +| includeAggregates | producer | | Boolean | Set this parameter to true to always return all available aggregates for an indicator including when an aggregate has already been applied. If a value is not specified this parameter defaults to false and returns no aggregates. +| includeAvailableAggregates | producer | | Boolean | Set this parameter to true to return all available aggregates for an indicator when no aggregate has been applied. If a value is not specified this parameter defaults to false and returns no aggregates. +| includeAvailableBreakdowns | producer | | Boolean | Set this parameter to true to return all available breakdowns for an indicator. If a value is not specified this parameter defaults to false and returns no breakdowns. +| includeScoreNotes | producer | | Boolean | Set this parameter to true to return all notes associated with the score. The note element contains the note text as well as the author and timestamp when the note was added. +| includeScores | producer | | Boolean | Set this parameter to true to return all scores for a scorecard. If a value is not specified this parameter defaults to false and returns only the most recent score value. | inputDisplayValue | producer | | Boolean | True to set raw value of input fields (default: false) +| key | producer | | Boolean | Set this parameter to true to return only scorecards for key indicators. | models | producer | | String | Defines the default model to use for a table +| perPage | producer | 10 | Integer | Enter the maximum number of scorecards each query can return. By default this value is 10 and the maximum is 100. +| release | producer | HELSINKI | ServiceNowRelease | The ServiceNow release to target default to Helsinki See https://docs.servicenow.com | resource | producer | | String | The default resource can be overridden by header CamelServiceNowResource +| sortBy | producer | | String | Specify the value to use when sorting results. By default queries sort records by value. +| sortDir | producer | | String | Specify the sort direction ascending or descending. By default queries sort records in descending order. Use sysparm_sortdir=asc to sort in ascending order. | suppressAutoSysField | producer | | Boolean | True to suppress auto generation of system fields (default: false) +| suppressPaginationHeader | producer | | Boolean | Set this value to true to remove the Link header from the response. The Link header allows you to request additional pages of data when the number of records matching your query exceeds the query limit | table | producer | | String | The default table can be overridden by header CamelServiceNowTable +| target | producer | | Boolean | Set this parameter to true to return only scorecards that have a target. +| topLevelOnly | producer | | Boolean | Gets only those categories whose parent is a catalog. | mapper | advanced | | ObjectMapper | Sets Jackson's ObjectMapper to use for request/reply | synchronous | advanced | false | boolean | Sets whether synchronous processing should be strictly used or Camel is allowed to use asynchronous processing (if supported). | apiUrl | security | | String | The ServiceNow REST API url @@ -74,67 +88,160 @@ The ServiceNow component supports 16 endpoint options which are listed below: Headers ^^^^^^^ -[width="100%",cols="10%,10%,80%",options="header",] -|======================================================================= -|Name |Type |Description - -|CamelServiceNowResource |String |The resource to access TABLE, AGGREGATE, IMPORT - -|CamelServiceNowTable |String |The table to access - -|CamelServiceNowAction |String |The action to perform RETRIEVE, CREATE, MODIFY, DELETE, UPDATE - -|CamelServiceNowModel |Class |The data model - -|CamelServiceNowSysId |String |ServiceNow sysy_id - -|CamelServiceNowQuery |String |An encoded query - -|CamelServiceNowDisplayValue |String |Return the display value (true), actual value (false), or both (all) for -reference fields (default: false) - -|CamelServiceNowInputDisplayValue |Boolean |True to set raw value of input fields - -|CamelServiceNowExcludeReferenceLink |Boolean |True to exclude Table API links for reference fields - -|CamelServiceNowFields |String |Comma-separated field names to return in the response - -|CamelServiceNowMinFields |String |A comma-separated list of fields for which to calculate the minimum -value - -|CamelServiceNowMaxFields |String |A comma-separated list of fields for which to calculate the maximum -value - -|CamelServiceNowSumFields |String |A comma-separated list of fields for which to calculate the sum of the -values - -|CamelServiceNowLimit |Integer |Limit to be applied on pagination - -|CamelServiceNowView |String |UI view to determine fields returned in the response. - -|CamelServiceNowSuppressAutoSysField |Boolean |True to suppress auto generation of system fields - -|CamelServiceNowAvgFields |String |A comma-separated list of fields for which to calculate the average -value - -|CamelServiceNowCount |Boolean |A boolean flag. You can set this parameter to *true* for the number of -records returned by the query - -|CamelServiceGroupBy |String |The fields to group the returned data by - -|CamelServiceOrderBy |String |A list of values to order grouped results by - -|CamelServiceHaving |String |An additional query allowing you to filter the data based on an -aggregate operation -|======================================================================= +[width="100%",cols="10%,10%,10%,10%,60%",options="header",] +|=== +|Name |Type |ServiceNow API Parameter |Endpoint option |Description +|CamelServiceNowResource |String | - | - | The resource to access +|CamelServiceNowAction |String | - | - | The action to perform +|CamelServiceNowActionSubject | - | - | String |The subject to which the action should be applied +|CamelServiceNowModel |Class | - | - | The data model +|CamelServiceNowOffsetNext | - | - | - | - +|CamelServiceNowOffsetPrev | - | - | - | - +|CamelServiceNowOffsetFirst | - | - | - | - +|CamelServiceNowOffsetLast | - | - | - | - +|CamelServiceNowContentType | - | - | - | - +|CamelServiceNowContentEncoding | - | - | - | - +|CamelServiceNowContentMeta | - | - | - | - +|CamelServiceNowSysId |String | sys_id | - | - +|CamelServiceNowUserSysId |String | user_sysid | - | - +|CamelServiceNowUserId |String | user_id | - | - +|CamelServiceNowCartItemId |String | cart_item_id | - | - +|CamelServiceNowFileName |String | file_name | - | - +|CamelServiceNowTable |String | table_name | - | - +|CamelServiceNowTableSysId |String | table_sys_id | - | - +|CamelServiceNowEncryptionContext | String | encryption_context | - | - +|CamelServiceNowCategory | String | sysparm_category | - | - +|CamelServiceNowType |String | sysparm_type | - | - +|CamelServiceNowCatalog | String | sysparm_catalog | - | - +|CamelServiceNowQuery |String | sysparm_query | - | - +|CamelServiceNowDisplayValue |String | sysparm_display_value | displayValue | - +|CamelServiceNowInputDisplayValue |Boolean | sysparm_input_display_value | inputDisplayValue | - +|CamelServiceNowExcludeReferenceLink |Boolean | sysparm_exclude_reference_link | excludeReferenceLink | - +|CamelServiceNowFields |String | sysparm_fields | - | - +|CamelServiceNowLimit |Integer | sysparm_limit | - | - +|CamelServiceNowText | String | sysparm_text | - | - +|CamelServiceNowOffset | Integer | sysparm_offset | - | - +|CamelServiceNowView |String | sysparm_view | - | - +|CamelServiceNowSuppressAutoSysField |Boolean | sysparm_suppress_auto_sys_field | suppressAutoSysField | - +|CamelServiceNowSuppressPaginationHeader | Booleab | sysparm_suppress_pagination_header | suppressPaginationHeader | - +|CamelServiceNowMinFields |String | sysparm_min_fields | - | - +|CamelServiceNowMaxFields |String | sysparm_max_fields | - | - +|CamelServiceNowSumFields |String | sysparm_sum_fields | - | - +|CamelServiceNowAvgFields |String | sysparm_avg_fields | - | - +|CamelServiceNowCount |Boolean | sysparm_count | - | - +|CamelServiceGroupBy |String | sysparm_group_by | - | - +|CamelServiceOrderBy |String | sysparm_order_by | - | - +|CamelServiceHaving |String | sysparm_having | - | - +|CamelServiceNowUUID |String | sysparm_uuid | - | - +|CamelServiceNowBreakdown| String| sysparm_breakdown | - | - +|CamelServiceNowIncludeScores| Boolean | sysparm_include_scores | includeScores | - +|CamelServiceNowIncludeScoreNotes | Boolean | sysparm_include_score_notes | includeScoreNotes | - +|CamelServiceNowIncludeAggregates | Boolean | sysparm_include_aggregates | includeAggregates | - +|CamelServiceNowIncludeAvailableBreakdowns | Boolean | sysparm_include_available_breakdowns | includeAvailableBreakdowns | - +|CamelServiceNowIncludeAvailableAggregates | Boolean | sysparm_include_available_aggregates | includeAvailableAggregates | - +|CamelServiceNowFavorites | Boolean | sysparm_favorites | favorites | - +|CamelServiceNowKey | Boolean | sysparm_key | key | - +|CamelServiceNowTarget | Boolean | sysparm_target | target | - +|CamelServiceNowDisplay | String | sysparm_display | display | - +|CamelServiceNowPerPage | Integer | sysparm_per_page | perPage | - +|CamelServiceNowSortBy | String | sysparm_sortby | sortBy | - +|CamelServiceNowSortDir | String | sysparm_sortdit | sortDir | - +|CamelServiceNowContains | String | sysparm_contains | - | - +|CamelServiceNowTags | String | sysparm_tags | - | - +|CamelServiceNowPage | String | sysparm_page | - | - +|CamelServiceNowElementsFilter | String | sysparm_elements_filter | - | - +|CamelServiceNowBreakdownRelation | String | sysparm_breakdown_relation | - | - +|CamelServiceNowDataSource | String | sysparm_data_source | - | - +|CamelServiceNowTopLevelOnly | Boolean | sysparm_top_level_only | topLevelOnly | - +|=== + +[[ServiceNow-Fuji]] +[cols="10%a,10%a,10%a,70%a", options="header"] +.API Mapping +|=== +| CamelServiceNowResource | CamelServiceNowAction | Method | API URI +1.5+<.^|TABLE +| RETRIEVE | GET | /api/now/v1/table/{table_name}/{sys_id} +| CREATE | POST | /api/now/v1/table/{table_name} +| MODIFY | PUT | /api/now/v1/table/{table_name}/{sys_id} +| DELETE | DELETE | /api/now/v1/table/{table_name}/{sys_id} +| UPDATE | PATCH | /api/now/v1/table/{table_name}/{sys_id} + +| AGGREGATE +| RETRIEVE | GET | /api/now/v1/stats/{table_name} + +1.2+<.^|IMPORT +| RETRIEVE | GET | /api/now/import/{table_name}/{sys_id} +| CREATE | POST | /api/now/import/{table_name} +|=== + +NOTE: link:http://wiki.servicenow.com/index.php?title=REST_API#Available_APIs[Fuji REST API Documentation] + +[[ServiceNow-Helsinki]] +[cols="10%a,10%a,10%a,10%a,60%a", options="header"] +.API Mapping +|=== +| CamelServiceNowResource | CamelServiceNowAction | CamelServiceNowActionSubject | Method | API URI +1.5+<.^|TABLE +| RETRIEVE | | GET | /api/now/v1/table/{table_name}/{sys_id} +| CREATE | | POST | /api/now/v1/table/{table_name} +| MODIFY | | PUT | /api/now/v1/table/{table_name}/{sys_id} +| DELETE | | DELETE | /api/now/v1/table/{table_name}/{sys_id} +| UPDATE | | PATCH | /api/now/v1/table/{table_name}/{sys_id} + +| AGGREGATE +| RETRIEVE | | GET | /api/now/v1/stats/{table_name} + +1.2+<.^|IMPORT +| RETRIEVE | | GET | /api/now/import/{table_name}/{sys_id} +| CREATE | | POST | /api/now/import/{table_name} + +1.4+<.^|ATTACHMENT +| RETRIEVE | | GET | /api/now/api/now/attachment/{sys_id} +| CONTENT | | GET | /api/now/attachment/{sys_id}/file +| UPLOAD | | POST | /api/now/api/now/attachment/file +| DELETE | | DELETE | /api/now/attachment/{sys_id} + +| SCORECARDS +| RETRIEVE | PERFORMANCE_ANALYTICS | GET | /api/now/pa/scorecards + +1.2+<.^|MISC +| RETRIEVE | USER_ROLE_INHERITANCE | GET | /api/global/user_role_inheritance +| CREATE | IDENTIFY_RECONCILE | POST | /api/now/identifyreconcile + +1.2+<.^|SERVICE_CATALOG +| RETRIEVE | | GET | /sn_sc/servicecatalog/catalogs/{sys_id} +| RETRIEVE | CATEGORIES | GET | /sn_sc/servicecatalog/catalogs/{sys_id}/categories + +1.5+<.^|SERVICE_CATALOG_ITEMS +| RETRIEVE | | GET | /sn_sc/servicecatalog/items/{sys_id} +| RETRIEVE | SUBMIT_GUIDE | POST | /sn_sc/servicecatalog/items/{sys_id}/submit_guide +| RETRIEVE | CHECKOUT_GUIDE | POST | /sn_sc/servicecatalog/items/{sys_id}/checkout_guide +| CREATE | SUBJECT_CART | POST | /sn_sc/servicecatalog/items/{sys_id}/add_to_cart +| CREATE | SUBJECT_PRODUCER | POST | /sn_sc/servicecatalog/items/{sys_id}/submit_producer + +1.6+<.^|SERVICE_CATALOG_CARTS +| RETRIEVE | | GET | /sn_sc/servicecatalog/cart +| RETRIEVE | DELIVERY_ADDRESS | GET | /sn_sc/servicecatalog/cart/delivery_address/{user_id} +| RETRIEVE | CHECKOUT | POST | /sn_sc/servicecatalog/cart/checkout +| UPDATE | | POST | /sn_sc/servicecatalog/cart/{cart_item_id} +| UPDATE | CHECKOUT | POST | /sn_sc/servicecatalog/cart/submit_order +| DELETE | | DELETE | /sn_sc/servicecatalog/cart/{sys_id}/empty + +| SERVICE_CATALOG_CATEGORIES +| RETRIEVE | | GET | /sn_sc/servicecatalog/categories/{sys_id} + +|=== + +NOTE: https://docs.servicenow.com/bundle/helsinki-servicenow-platform/page/integrate/inbound-rest/reference/r_RESTResources.html[Helsinki REST API Documentation] [[ServiceNow-Usageexamples]] Usage examples: ^^^^^^^^^^^^^^^ -  {% raw %} [source,java] +.Retrieve 10 Incidents ------------------------------------------------------------------------------------------------------------------- context.addRoutes(new RouteBuilder() { public void configure() { @@ -144,12 +251,17 @@ context.addRoutes(new RouteBuilder() { + "&password={{env:SERVICENOW_PASSWORD}}" + "&oauthClientId={{env:SERVICENOW_OAUTH2_CLIENT_ID}}" + "&oauthClientSecret={{env:SERVICENOW_OAUTH2_CLIENT_SECRET}}" - + "&model.incident=org.apache.camel.component.servicenow.model.Incident") .to("mock:servicenow"); } -}); Map<String, Object> headers = new HashMap<>();headers.put(ServiceNowConstants.RESOURCE, "table"); -headers.put(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE); -headers.put(ServiceNowConstants.SYSPARM_LIMIT, "10"); -headers.put(ServiceNowConstants.TABLE, "incident");template.sendBodyAndHeaders("direct:servicenow", null, headers); +}); + +FluentProducerTemplate.on(context) + .withHeader(ServiceNowConstants.RESOURCE, "table") + .withHeader(ServiceNowConstants.ACTION, ServiceNowConstants.ACTION_RETRIEVE) + .withHeader(ServiceNowConstants.SYSPARM_LIMIT.getId(), "10") + .withHeader(ServiceNowConstants.TABLE, "incident") + .withHeader(ServiceNowConstants.MODEL, Incident.class) + .to("direct:servicenow") + .send(); ------------------------------------------------------------------------------------------------------------------- {% endraw %} http://git-wip-us.apache.org/repos/asf/camel/blob/f655c941/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java new file mode 100644 index 0000000..56183b4 --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProcessor.java @@ -0,0 +1,265 @@ +/** + * 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.servicenow; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.Response; + +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.Processor; +import org.apache.camel.util.ObjectHelper; +import org.apache.camel.util.StringHelper; +import org.apache.camel.util.URISupport; + +public abstract class AbstractServiceNowProcessor implements Processor { + + protected final ServiceNowEndpoint endpoint; + protected final ServiceNowConfiguration config; + protected final ObjectMapper mapper; + protected final ServiceNowClient client; + + // Cache for JavaTypes + private final JavaTypeCache javaTypeCache; + private final List<ServiceNowDispatcher> dispatchers; + + protected AbstractServiceNowProcessor(ServiceNowEndpoint endpoint) throws Exception { + this.javaTypeCache = new JavaTypeCache(); + this.endpoint = endpoint; + this.config = endpoint.getConfiguration(); + this.mapper = ObjectHelper.notNull(config.getMapper(), "mapper"); + this.client = new ServiceNowClient(config); + this.dispatchers = new ArrayList<>(); + } + + protected AbstractServiceNowProcessor setBodyAndHeaders(Message message, Class<?> model, Response response) throws Exception { + if (response != null) { + setHeaders(message, model, response); + setBody(message, model, response); + } + + return this; + } + + @Override + public void process(Exchange exchange) throws Exception { + final ServiceNowDispatcher dispatcher = findDispatcher(exchange); + + if (dispatcher != null) { + dispatcher.process(exchange); + } else { + throw new IllegalArgumentException("Unable to process exchange"); + } + } + + // ********************************* + // Header + // ********************************* + + + protected AbstractServiceNowProcessor setHeaders(Message message, Class<?> model, Response response) throws Exception { + List<String> links = response.getStringHeaders().get(HttpHeaders.LINK); + if (links != null) { + for (String link : links) { + String[] parts = link.split(";"); + if (parts.length != 2) { + continue; + } + + // Sanitize parts + String uri = ObjectHelper.between(parts[0], "<", ">"); + String rel = StringHelper.removeQuotes(ObjectHelper.after(parts[1], "=")); + + Map<String, Object> query = URISupport.parseQuery(uri); + Object offset = query.get(ServiceNowParams.SYSPARM_OFFSET.getId()); + + if (offset != null) { + switch (rel) { + case ServiceNowConstants.LINK_FIRST: + message.setHeader(ServiceNowConstants.OFFSET_FIRST, offset); + break; + case ServiceNowConstants.LINK_LAST: + message.setHeader(ServiceNowConstants.OFFSET_LAST, offset); + break; + case ServiceNowConstants.LINK_NEXT: + message.setHeader(ServiceNowConstants.OFFSET_NEXT, offset); + break; + case ServiceNowConstants.LINK_PREV: + message.setHeader(ServiceNowConstants.OFFSET_PREV, offset); + break; + default: + break; + } + } + } + } + + String attachmentMeta = response.getHeaderString(ServiceNowConstants.ATTACHMENT_META_HEADER); + if (ObjectHelper.isNotEmpty(attachmentMeta)) { + message.setHeader( + ServiceNowConstants.CONTENT_META, + mapper.readValue(attachmentMeta, Map.class) + ); + } + + copyHeader(response, HttpHeaders.CONTENT_TYPE, message, ServiceNowConstants.CONTENT_TYPE); + copyHeader(response, HttpHeaders.CONTENT_ENCODING, message, ServiceNowConstants.CONTENT_ENCODING); + + if (model != null) { + message.getHeaders().putIfAbsent(ServiceNowConstants.MODEL, model.getName()); + } + + return this; + } + + // ********************************* + // Body + // ********************************* + + protected AbstractServiceNowProcessor setBody(Message message, Class<?> model, Response response) throws Exception { + if (message != null && response != null) { + if (ObjectHelper.isNotEmpty(response.getHeaderString(HttpHeaders.CONTENT_TYPE))) { + JsonNode node = response.readEntity(JsonNode.class); + Object body = unwrap(node, model); + + if (body != null) { + message.setBody(body); + } + } + } + + return this; + } + + protected AbstractServiceNowProcessor validateBody(Message message, Class<?> model) { + return validateBody(message.getBody(), model); + } + + protected AbstractServiceNowProcessor validateBody(Object body, Class<?> model) { + ObjectHelper.notNull(body, "body"); + + if (!body.getClass().isAssignableFrom(model)) { + throw new IllegalArgumentException( + "Body is not compatible with model (body=" + body.getClass() + ", model=" + model); + } + + return this; + } + + protected Object unwrap(JsonNode answer, Class<?> model) throws IOException { + Object result = null; + + if (answer != null) { + JsonNode node = answer.get("result"); + if (node != null) { + if (node.isArray()) { + if (model.isInstance(Map.class)) { + // If the model is a Map, there's no need to use any + // specific JavaType to instruct Jackson about the + // expected element type + result = mapper.treeToValue(node, List.class); + } else { + result = mapper.readValue(node.traverse(), javaTypeCache.get(model)); + } + } else { + result = mapper.treeToValue(node, model); + } + } + } + + return result; + } + + // ********************************* + // Helpers + // ********************************* + + protected final void addDispatcher(ServiceNowDispatcher dispatcher) { + this.dispatchers.add(dispatcher); + } + + protected final void addDispatcher(String action, Processor processor) { + addDispatcher(ServiceNowDispatcher.on(action, null, processor)); + } + + protected final void addDispatcher(String action, String subject, Processor processor) { + addDispatcher(ServiceNowDispatcher.on(action, subject, processor)); + } + + protected final ServiceNowDispatcher findDispatcher(Exchange exchange) { + ServiceNowDispatcher dispatcher = null; + for (int i = 0; i < dispatchers.size(); i++) { + dispatcher = dispatchers.get(i); + if (dispatcher.match(exchange)) { + return dispatcher; + } + } + + return null; + } + + protected Object getRequestParamFromHeader(ServiceNowParam sysParam, Message message) { + return message.getHeader( + sysParam.getHeader(), + sysParam.getDefaultValue(config), + sysParam.getType() + ); + } + + protected Object getMandatoryRequestParamFromHeader(ServiceNowParam sysParam, Message message) { + return ObjectHelper.notNull( + getRequestParamFromHeader(sysParam, message), + sysParam.getHeader() + ); + } + + protected void copyHeader(Response from, String fromId, Message to, String toId) { + Object fromValue = from.getHeaders().getFirst(fromId); + if (ObjectHelper.isNotEmpty(fromValue)) { + to.setHeader(toId, fromValue); + } + } + + protected Class<?> getModel(Message message) { + return getModel(message, null); + } + + protected Class<?> getModel(Message message, String modelName) { + return message.getHeader( + ServiceNowConstants.MODEL, + ObjectHelper.isEmpty(modelName) ? Map.class : config.getModel(modelName, Map.class), + Class.class); + } + + // ************************************************************************* + // Use ClassValue to lazy create and cache JavaType + // ************************************************************************* + + private class JavaTypeCache extends ClassValue<JavaType> { + @Override + protected JavaType computeValue(Class<?> type) { + return mapper.getTypeFactory().constructCollectionType(List.class, type); + } + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/f655c941/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProducer.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProducer.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProducer.java new file mode 100644 index 0000000..0fd23d7 --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/AbstractServiceNowProducer.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.servicenow; + +import org.apache.camel.impl.HeaderSelectorProducer; + +public abstract class AbstractServiceNowProducer extends HeaderSelectorProducer implements ServiceNowProducer { + private final ServiceNowRelease release; + private final ServiceNowEndpoint endpoint; + + public AbstractServiceNowProducer(ServiceNowEndpoint endpoint, ServiceNowRelease release) { + super(endpoint, ServiceNowConstants.RESOURCE, endpoint.getConfiguration().getResource()); + + this.release = release; + this.endpoint = endpoint; + } + + @Override + public ServiceNowRelease getRelease() { + return release; + } + + protected final ServiceNowConfiguration getConfiguration() { + return endpoint.getConfiguration(); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/f655c941/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java new file mode 100644 index 0000000..b5f4136 --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowClient.java @@ -0,0 +1,140 @@ +/** + * 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.servicenow; + +import java.util.Arrays; +import java.util.Map; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; +import org.apache.camel.CamelException; +import org.apache.camel.Message; +import org.apache.camel.component.servicenow.auth.AuthenticationRequestFilter; +import org.apache.cxf.jaxrs.client.WebClient; + +public class ServiceNowClient { + private final ServiceNowConfiguration configuration; + private final WebClient client; + + public ServiceNowClient(ServiceNowConfiguration configuration) throws Exception { + this.configuration = configuration; + this.client = WebClient.create( + configuration.getApiUrl(), + Arrays.asList( + new AuthenticationRequestFilter(configuration), + new JacksonJsonProvider(configuration.getMapper()), + new ServiceNowExceptionMapper(configuration.getMapper()) + ), + true + ); + + WebClient.getConfig(client) + .getRequestContext() + .put("org.apache.cxf.http.header.split", true); + } + + public ServiceNowClient types(MediaType type) { + return types(type, type); + } + + public ServiceNowClient types(MediaType accept, MediaType type) { + client.accept(accept); + client.type(type); + return this; + } + + public ServiceNowClient path(Object path) { + client.path(path); + return this; + } + + public ServiceNowClient type(MediaType ct) { + client.type(ct); + return this; + } + + public ServiceNowClient type(String type) { + client.type(type); + return this; + } + + public ServiceNowClient accept(MediaType... types) { + client.accept(types); + return this; + } + + public ServiceNowClient accept(String... types) { + client.accept(types); + return this; + } + + public ServiceNowClient query(String name, Object... values) { + client.query(name, values); + return this; + } + + public ServiceNowClient query(ServiceNowParam param, Message message) { + Object value = param.getHeaderValue(message, configuration); + if (value != null) { + client.query(param.getId(), value); + } + + return this; + } + + public Response invoke(String httpMethod) throws Exception { + return invoke(httpMethod, null); + } + + public Response invoke(String httpMethod, Object body) throws Exception { + Response response = client.invoke(httpMethod, body); + int code = response.getStatus(); + + // Only ServiceNow known error status codes are mapped + // See http://wiki.servicenow.com/index.php?title=REST_API#REST_Response_HTTP_Status_Codes + switch(code) { + case 200: + case 201: + case 204: + // Success + break; + case 400: + case 401: + case 403: + case 404: + case 405: + case 406: + case 415: + throw response.readEntity(ServiceNowException.class); + default: + throw new CamelException( + String.format("Status (%d): %s", code, response.readEntity(Map.class)) + ); + } + + return response; + } + + public ServiceNowClient reset() { + client.back(true); + client.reset(); + client.resetQuery(); + + return this; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/f655c941/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java index 30135c9..db0c6f9 100644 --- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java @@ -47,6 +47,14 @@ public class ServiceNowComponent extends UriEndpointComponent { setProperties(configuration, parameters); - return new ServiceNowEndpoint(uri, this, configuration, remaining); + String instanceName = getCamelContext().resolvePropertyPlaceholders(remaining); + if (!configuration.hasApiUrl()) { + configuration.setApiUrl(String.format("https://%s.service-now.com/api", instanceName)); + } + if (!configuration.hasOautTokenUrl()) { + configuration.setOauthTokenUrl(String.format("https://%s.service-now.com/oauth_token.do", instanceName)); + } + + return new ServiceNowEndpoint(uri, this, configuration, instanceName); } } http://git-wip-us.apache.org/repos/asf/camel/blob/f655c941/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java index 8a465d5..9abfdfd 100644 --- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java @@ -58,6 +58,34 @@ public class ServiceNowConfiguration { private Boolean excludeReferenceLink = false; @UriParam private Boolean suppressAutoSysField = false; + @UriParam + private Boolean includeScores = false; + @UriParam + private Boolean includeAggregates = false; + @UriParam + private Boolean includeAvailableBreakdowns = false; + @UriParam + private Boolean includeAvailableAggregates = false; + @UriParam + private Boolean includeScoreNotes = false; + @UriParam + private Boolean topLevelOnly; + @UriParam + private Boolean favorites; + @UriParam + private Boolean key; + @UriParam + private Boolean target; + @UriParam(defaultValue = "true", enums = "false,true,all") + private String display = "true"; + @UriParam(defaultValue = "10") + private Integer perPage = 10; + @UriParam(enums = "value,change,changeperc,gap,gapperc,duedate,name,order,default,group,indicator_group,frequency,target,date,trend,bullet,direction") + private String sortBy; + @UriParam(enums = "asc,desc") + private String sortDir; + @UriParam + private Boolean suppressPaginationHeader = false; @UriParam(defaultValue = "false", enums = "false,true,all") private String displayValue = "false"; @UriParam @@ -66,6 +94,8 @@ public class ServiceNowConfiguration { private Map<String, Class<?>> models; @UriParam(label = "advanced") private ObjectMapper mapper = MAPPER; + @UriParam(defaultValue = "HELSINKI", enums = "FUJI,GENEVA,HELSINKI") + private ServiceNowRelease release = ServiceNowRelease.HELSINKY; public String getUserName() { @@ -198,6 +228,169 @@ public class ServiceNowConfiguration { this.suppressAutoSysField = suppressAutoSysField; } + public Boolean getSuppressPaginationHeader() { + return suppressPaginationHeader; + } + + /** + * Set this value to true to remove the Link header from the response. The + * Link header allows you to request additional pages of data when the number + * of records matching your query exceeds the query limit + */ + public void setSuppressPaginationHeader(Boolean suppressPaginationHeader) { + this.suppressPaginationHeader = suppressPaginationHeader; + } + + public Boolean getIncludeScores() { + return includeScores; + } + + /** + * Set this parameter to true to return all scores for a scorecard. If a value + * is not specified, this parameter defaults to false and returns only the most + * recent score value. + */ + public void setIncludeScores(Boolean includeScores) { + this.includeScores = includeScores; + } + + public Boolean getIncludeAggregates() { + return includeAggregates; + } + + /** + * Set this parameter to true to always return all available aggregates for + * an indicator, including when an aggregate has already been applied. If a + * value is not specified, this parameter defaults to false and returns no + * aggregates. + */ + public void setIncludeAggregates(Boolean includeAggregates) { + this.includeAggregates = includeAggregates; + } + + public Boolean getIncludeAvailableBreakdowns() { + return includeAvailableBreakdowns; + } + + /** + * Set this parameter to true to return all available breakdowns for an indicator. + * If a value is not specified, this parameter defaults to false and returns + * no breakdowns. + */ + public void setIncludeAvailableBreakdowns(Boolean includeAvailableBreakdowns) { + this.includeAvailableBreakdowns = includeAvailableBreakdowns; + } + + public Boolean getIncludeAvailableAggregates() { + return includeAvailableAggregates; + } + + /** + * Set this parameter to true to return all available aggregates for an indicator + * when no aggregate has been applied. If a value is not specified, this parameter + * defaults to false and returns no aggregates. + */ + public void setIncludeAvailableAggregates(Boolean includeAvailableAggregates) { + this.includeAvailableAggregates = includeAvailableAggregates; + } + + public Boolean getIncludeScoreNotes() { + return includeScoreNotes; + } + + /** + * Set this parameter to true to return all notes associated with the score. + * The note element contains the note text as well as the author and timestamp + * when the note was added. + */ + public void setIncludeScoreNotes(Boolean includeScoreNotes) { + this.includeScoreNotes = includeScoreNotes; + } + + public Boolean getFavorites() { + return favorites; + } + + /** + * Set this parameter to true to return only scorecards that are favorites of + * the querying user. + */ + public void setFavorites(Boolean favorites) { + this.favorites = favorites; + } + + public Boolean getKey() { + return key; + } + + /** + * Set this parameter to true to return only scorecards for key indicators. + */ + public void setKey(Boolean key) { + this.key = key; + } + + public Boolean getTarget() { + return target; + } + + /** + * Set this parameter to true to return only scorecards that have a target. + */ + public void setTarget(Boolean target) { + this.target = target; + } + + public String getDisplay() { + return display; + } + + /** + * Set this parameter to true to return only scorecards where the indicator + * Display field is selected. Set this parameter to all to return scorecards + * with any Display field value. This parameter is true by default. + */ + public void setDisplay(String display) { + this.display = display; + } + + public Integer getPerPage() { + return perPage; + } + + /** + * Enter the maximum number of scorecards each query can return. By default + * this value is 10, and the maximum is 100. + */ + public void setPerPage(Integer perPage) { + this.perPage = perPage; + } + + public String getSortBy() { + return sortBy; + } + + /** + * Specify the value to use when sorting results. By default, queries sort + * records by value. + */ + public void setSortBy(String sortBy) { + this.sortBy = sortBy; + } + + public String getSortDir() { + return sortDir; + } + + /** + * Specify the sort direction, ascending or descending. By default, queries + * sort records in descending order. Use sysparm_sortdir=asc to sort in + * ascending order. + */ + public void setSortDir(String sortDir) { + this.sortDir = sortDir; + } + public String getDisplayValue() { return displayValue; } @@ -268,4 +461,28 @@ public class ServiceNowConfiguration { public boolean hasMapper() { return mapper != null; } + + /** + * The ServiceNow release to target, default to Helsinki + * + * See https://docs.servicenow.com + */ + public void setRelease(ServiceNowRelease release) { + this.release = release; + } + + public ServiceNowRelease getRelease() { + return release; + } + + public Boolean getTopLevelOnly() { + return topLevelOnly; + } + + /** + * Gets only those categories whose parent is a catalog. + */ + public void setTopLevelOnly(Boolean topLevelOnly) { + this.topLevelOnly = topLevelOnly; + } } http://git-wip-us.apache.org/repos/asf/camel/blob/f655c941/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java index 8cd6c4b..e699dd7 100644 --- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java @@ -16,37 +16,59 @@ */ package org.apache.camel.component.servicenow; -public interface ServiceNowConstants { - String RESOURCE = "CamelServiceNowResource"; - String TABLE = "CamelServiceNowTable"; - String ACTION = "CamelServiceNowAction"; - String MODEL = "CamelServiceNowModel"; - - String RESOURCE_TABLE = "table"; - String RESOURCE_AGGREGATE = "aggregate"; - String RESOURCE_IMPORT = "import"; - - String ACTION_RETRIEVE = "retrieve"; - String ACTION_CREATE = "create"; - String ACTION_MODIFY = "modify"; - String ACTION_DELETE = "delete"; - String ACTION_UPDATE = "update"; - - String SYSPARM_ID = "CamelServiceNowSysId"; - String SYSPARM_QUERY = "CamelServiceNowQuery"; - String SYSPARM_DISPLAY_VALUE = "CamelServiceNowDisplayValue"; - String SYSPARM_INPUT_DISPLAY_VALUE = "CamelServiceNowInputDisplayValue"; - String SYSPARM_EXCLUDE_REFERENCE_LINK = "CamelServiceNowExcludeReferenceLink"; - String SYSPARM_FIELDS = "CamelServiceNowFields"; - String SYSPARM_MIN_FIELDS = "CamelServiceNowMinFields"; - String SYSPARM_MAX_FIELDS = "CamelServiceNowMaxFields"; - String SYSPARM_SUM_FIELDS = "CamelServiceNowSumFields"; - String SYSPARM_LIMIT = "CamelServiceNowLimit"; - String SYSPARM_VIEW = "CamelServiceNowView"; - String SYSPARM_SUPPRESS_AUTO_SYS_FIELD = "CamelServiceNowSuppressAutoSysField"; - String SYSPARM_AVG_FIELDS = "CamelServiceNowAvgFields"; - String SYSPARM_COUNT = "CamelServiceNowCount"; - String SYSPARM_GROUP_BY = "CamelServiceGroupBy"; - String SYSPARM_ORDER_BY = "CamelServiceOrderBy"; - String SYSPARM_HAVING = "CamelServiceHaving"; +public final class ServiceNowConstants { + public static final String CAMEL_HEADER_PREFIX = "CamelServiceNow"; + + public static final String RESOURCE = "CamelServiceNowResource"; + public static final String ACTION = "CamelServiceNowAction"; + public static final String ACTION_SUBJECT = "CamelServiceNowActionSubject"; + public static final String MODEL = "CamelServiceNowModel"; + public static final String OFFSET_NEXT = "CamelServiceNowOffsetNext"; + public static final String OFFSET_PREV = "CamelServiceNowOffsetPrev"; + public static final String OFFSET_FIRST = "CamelServiceNowOffsetFirst"; + public static final String OFFSET_LAST = "CamelServiceNowOffsetLast"; + public static final String CONTENT_TYPE = "CamelServiceNowContentType"; + public static final String CONTENT_ENCODING = "CamelServiceNowContentEncoding"; + public static final String CONTENT_META = "CamelServiceNowContentMeta"; + + public static final String ATTACHMENT_META_HEADER = "X-Attachment-Metadata"; + + public static final String RESOURCE_TABLE = "table"; + public static final String RESOURCE_AGGREGATE = "aggregate"; + public static final String RESOURCE_IMPORT = "import"; + public static final String RESOURCE_ATTACHMENT = "attachment"; + public static final String RESOURCE_SCORECARDS = "scorecards"; + public static final String RESOURCE_MISC = "misc"; + public static final String RESOURCE_SERVICE_CATALOG = "service_catalog"; + public static final String RESOURCE_SERVICE_CATALOG_ITEMS = "service_catalog_items"; + public static final String RESOURCE_SERVICE_CATALOG_CARTS = "service_catalog_cart"; + public static final String RESOURCE_SERVICE_CATALOG_CATEGORIES = "service_catalog_categories"; + + public static final String ACTION_RETRIEVE = "retrieve"; + public static final String ACTION_CONTENT = "content"; + public static final String ACTION_CREATE = "create"; + public static final String ACTION_MODIFY = "modify"; + public static final String ACTION_DELETE = "delete"; + public static final String ACTION_UPDATE = "update"; + public static final String ACTION_UPLOAD = "upload"; + + public static final String ACTION_SUBJECT_CATEGORIES = "categories"; + public static final String ACTION_SUBJECT_CART = "cart"; + public static final String ACTION_SUBJECT_PRODUCER = "producer"; + public static final String ACTION_SUBJECT_GUIDE = "guide"; + public static final String ACTION_SUBJECT_SUBMIT_GUIDE = "submit_guide"; + public static final String ACTION_SUBJECT_CHECKOUT_GUIDE = "checkout_guide"; + public static final String ACTION_SUBJECT_PERFORMANCE_ANALYTICS = "performance_analytics"; + public static final String ACTION_SUBJECT_USER_ROLE_INHERITANCE = "user_role_inheritance"; + public static final String ACTION_SUBJECT_IDENTIFY_RECONCILE = "identify_reconcile"; + public static final String ACTION_SUBJECT_DELIVERY_ADDRESS = "delivery_address"; + public static final String ACTION_SUBJECT_CHECKOUT = "checkout"; + + public static final String LINK_NEXT = "next"; + public static final String LINK_PREV = "prev"; + public static final String LINK_FIRST = "first"; + public static final String LINK_LAST = "last"; + + private ServiceNowConstants() { + } } http://git-wip-us.apache.org/repos/asf/camel/blob/f655c941/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowDispatcher.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowDispatcher.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowDispatcher.java new file mode 100644 index 0000000..e3a0473 --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowDispatcher.java @@ -0,0 +1,55 @@ +/** + * 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.servicenow; + +import java.util.function.Predicate; + +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.Processor; +import org.apache.camel.util.ObjectHelper; + +public class ServiceNowDispatcher { + private final Predicate<Exchange> predicate; + private final Processor delegate; + + public ServiceNowDispatcher(Predicate<Exchange> predicate, Processor delegate) { + this.predicate = ObjectHelper.notNull(predicate, "predicate"); + this.delegate = ObjectHelper.notNull(delegate, "delegate"); + } + + public boolean match(Exchange exchange) { + return predicate.test(exchange); + } + + public void process(Exchange exchange) throws Exception { + delegate.process(exchange); + } + + // ******************** + // Helpers + // ******************** + + public static ServiceNowDispatcher on(final String action, final String subject, final Processor delegate) { + return new ServiceNowDispatcher(e -> matches(e.getIn(), action, subject), delegate); + } + + public static boolean matches(Message in, String action, final String subject) { + return ObjectHelper.equal(action, in.getHeader(ServiceNowConstants.ACTION, String.class), true) + && ObjectHelper.equal(subject, in.getHeader(ServiceNowConstants.ACTION_SUBJECT, String.class), true); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/f655c941/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java index 2fa39a7..8234482 100644 --- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java @@ -16,26 +16,23 @@ */ package org.apache.camel.component.servicenow; -import java.util.Arrays; - -import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; -import org.apache.camel.component.servicenow.auth.AuthenticationRequestFilter; -import org.apache.camel.component.servicenow.auth.OAuthToken; import org.apache.camel.impl.DefaultEndpoint; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; import org.apache.camel.spi.UriPath; -import org.apache.cxf.jaxrs.client.JAXRSClientFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Represents a ServiceNow endpoint. */ @UriEndpoint(scheme = "servicenow", title = "ServiceNow", syntax = "servicenow:instanceName", producerOnly = true, label = "api,cloud,management") public class ServiceNowEndpoint extends DefaultEndpoint { + private static final Logger LOGGER = LoggerFactory.getLogger(ServiceNowEndpoint.class); @UriPath(description = "The ServiceNow instance name ") @Metadata(required = "true") @@ -43,31 +40,24 @@ public class ServiceNowEndpoint extends DefaultEndpoint { @UriParam private final ServiceNowConfiguration configuration; - private final String apiUrl; - private final String oauthUrl; - private final OAuthToken token; public ServiceNowEndpoint(String uri, ServiceNowComponent component, ServiceNowConfiguration configuration, String instanceName) throws Exception { super(uri, component); this.configuration = configuration; - this.instanceName = component.getCamelContext().resolvePropertyPlaceholders(instanceName); - - this.apiUrl = configuration.hasApiUrl() - ? configuration.getApiUrl() - : String.format("https://%s.service-now.com/api/now", instanceName); - this.oauthUrl = configuration.hasOautTokenUrl() - ? configuration.getOauthTokenUrl() - : String.format("https://%s.service-now.com/oauth_token.do", instanceName); - - this.token = configuration.hasOAuthAuthentication() - ? new OAuthToken(this.oauthUrl, this.configuration) - : null; + this.instanceName = instanceName; } @Override public Producer createProducer() throws Exception { - return new ServiceNowProducer(this); + ServiceNowProducer producer = configuration.getRelease().get(this); + LOGGER.info("Producer for ServiceNow Rel. {} = {}/{}", + configuration.getRelease().name(), + producer.getRelease().name(), + producer.getClass().getName() + ); + + return producer; } @Override @@ -87,16 +77,4 @@ public class ServiceNowEndpoint extends DefaultEndpoint { public String getInstanceName() { return instanceName; } - - public <T> T createClient(Class<T> type) throws Exception { - return JAXRSClientFactory.create( - apiUrl, - type, - Arrays.asList( - new AuthenticationRequestFilter(configuration, token), - new JacksonJsonProvider(configuration.getMapper()), - new ServiceNowExceptionMapper(configuration.getMapper()) - ) - ); - } } http://git-wip-us.apache.org/repos/asf/camel/blob/f655c941/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionMapper.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionMapper.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionMapper.java index 5b80c69..d864246 100644 --- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionMapper.java +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionMapper.java @@ -42,13 +42,22 @@ public class ServiceNowExceptionMapper implements ResponseExceptionMapper<Servic try { // Only ServiceNow known error status codes are mapped // See http://wiki.servicenow.com/index.php?title=REST_API#REST_Response_HTTP_Status_Codes - if (code == Response.Status.NOT_FOUND.getStatusCode() - || code == Response.Status.BAD_REQUEST.getStatusCode() - || code == Response.Status.UNAUTHORIZED.getStatusCode() - || code == Response.Status.FORBIDDEN.getStatusCode() - || code == Response.Status.METHOD_NOT_ALLOWED.getStatusCode()) { - - return mapper.readValue((InputStream)r.getEntity(), ServiceNowException.class); + switch(code) { + case 200: + case 201: + case 204: + // Success + break; + case 400: + case 401: + case 403: + case 404: + case 405: + case 406: + case 415: + return mapper.readValue(r.readEntity(InputStream.class), ServiceNowException.class); + default: + break; } } catch (IOException e) { return new ServiceNowException(e); http://git-wip-us.apache.org/repos/asf/camel/blob/f655c941/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowParam.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowParam.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowParam.java new file mode 100644 index 0000000..5353753 --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowParam.java @@ -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. + */ +package org.apache.camel.component.servicenow; + +import org.apache.camel.Message; + +public interface ServiceNowParam { + String getId(); + String getHeader(); + Class<?> getType(); + Object getDefaultValue(ServiceNowConfiguration configuration); + Object getHeaderValue(Message message); + Object getHeaderValue(Message message, ServiceNowConfiguration configuration); +} http://git-wip-us.apache.org/repos/asf/camel/blob/f655c941/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowParams.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowParams.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowParams.java new file mode 100644 index 0000000..75f16f9 --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowParams.java @@ -0,0 +1,123 @@ +/** + * 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.servicenow; + +import java.util.function.Function; + +import org.apache.camel.Message; +import org.apache.camel.util.ObjectHelper; + +public enum ServiceNowParams implements ServiceNowParam { + PARAM_SYS_ID("sys_id", "CamelServiceNowSysId", String.class), + PARAM_USER_SYS_ID("user_sysid", "CamelServiceNowUserSysId", String.class), + PARAM_USER_ID("user_id", "CamelServiceNowUserId", String.class), + PARAM_CART_ITEM_ID("cart_item_id", "CamelServiceNowCartItemId", String.class), + PARAM_FILE_NAME("file_name", "CamelServiceNowFileName", String.class), + PARAM_TABLE_NAME("table_name", "CamelServiceNowTable", String.class), + PARAM_TABLE_SYS_ID("table_sys_id", "CamelServiceNowTableSysId", String.class), + PARAM_ENCRYPTION_CONTEXT("encryption_context", "CamelServiceNowEncryptionContext", String.class), + SYSPARM_CATEGORY("sysparm_category", "CamelServiceNowCategory", String.class), + SYSPARM_TYPE("sysparm_type", "CamelServiceNowType", String.class), + SYSPARM_CATALOG("sysparm_catalog", "CamelServiceNowCatalog", String.class), + SYSPARM_QUERY("sysparm_query", "CamelServiceNowQuery", String.class), + SYSPARM_DISPLAY_VALUE("sysparm_display_value", "CamelServiceNowDisplayValue", String.class, ServiceNowConfiguration::getDisplayValue), + SYSPARM_INPUT_DISPLAY_VALUE("sysparm_input_display_value", "CamelServiceNowInputDisplayValue", Boolean.class, ServiceNowConfiguration::getInputDisplayValue), + SYSPARM_EXCLUDE_REFERENCE_LINK("sysparm_exclude_reference_link", "CamelServiceNowExcludeReferenceLink", Boolean.class, ServiceNowConfiguration::getExcludeReferenceLink), + SYSPARM_FIELDS("sysparm_fields", "CamelServiceNowFields", String.class), + SYSPARM_LIMIT("sysparm_limit", "CamelServiceNowLimit", Integer.class), + SYSPARM_TEXT("sysparm_text", "CamelServiceNowText", String.class), + SYSPARM_OFFSET("sysparm_offset", "CamelServiceNowOffset", Integer.class), + SYSPARM_VIEW("sysparm_view", "CamelServiceNowView", String.class), + SYSPARM_SUPPRESS_AUTO_SYS_FIELD("sysparm_suppress_auto_sys_field", "CamelServiceNowSuppressAutoSysField", Boolean.class, ServiceNowConfiguration::getSuppressAutoSysField), + SYSPARM_SUPPRESS_PAGINATION_HEADER("sysparm_suppress_pagination_header", "CamelServiceNowSuppressPaginationHeader", Boolean.class, ServiceNowConfiguration::getSuppressPaginationHeader), + SYSPARM_MIN_FIELDS("sysparm_min_fields", "CamelServiceNowMinFields", String.class), + SYSPARM_MAX_FIELDS("sysparm_max_fields", "CamelServiceNowMaxFields", String.class), + SYSPARM_SUM_FIELDS("sysparm_sum_fields", "CamelServiceNowSumFields", String.class), + SYSPARM_AVG_FIELDS("sysparm_avg_fields", "CamelServiceNowAvgFields", String.class), + SYSPARM_COUNT("sysparm_count", "CamelServiceNowCount", Boolean.class), + SYSPARM_GROUP_BY("sysparm_group_by", "CamelServiceNowGroupBy", String.class), + SYSPARM_ORDER_BY("sysparm_order_by", "CamelServiceNowOrderBy", String.class), + SYSPARM_HAVING("sysparm_having", "CamelServiceNowHaving", String.class), + SYSPARM_UUID("sysparm_uuid", "CamelServiceNowUUID", String.class), + SYSPARM_BREAKDOWN("sysparm_breakdown", "CamelServiceNowBreakdown", String.class), + SYSPARM_INCLUDE_SCORES("sysparm_include_scores", "CamelServiceNowIncludeScores", Boolean.class, ServiceNowConfiguration::getIncludeScores), + SYSPARM_INCLUDE_SCORE_NOTES("sysparm_include_score_notes", "CamelServiceNowIncludeScoreNotes", Boolean.class, ServiceNowConfiguration::getIncludeScoreNotes), + SYSPARM_INCLUDE_AGGREGATES("sysparm_include_aggregates", "CamelServiceNowIncludeAggregates", Boolean.class, ServiceNowConfiguration::getIncludeAggregates), + SYSPARM_INCLUDE_AVAILABLE_BREAKDOWNS("sysparm_include_available_breakdowns", "CamelServiceNowIncludeAvailableBreakdowns", Boolean.class, ServiceNowConfiguration::getIncludeAvailableBreakdowns), + SYSPARM_INCLUDE_AVAILABLE_AGGREGATES("sysparm_include_available_aggregates", "CamelServiceNowIncludeAvailableAggregates", Boolean.class, ServiceNowConfiguration::getIncludeAvailableAggregates), + SYSPARM_FAVORITES("sysparm_favorites", "CamelServiceNowFavorites", Boolean.class, ServiceNowConfiguration::getFavorites), + SYSPARM_KEY("sysparm_key", "CamelServiceNowKey", Boolean.class, ServiceNowConfiguration::getKey), + SYSPARM_TARGET("sysparm_target", "CamelServiceNowTarget", Boolean.class, ServiceNowConfiguration::getTarget), + SYSPARM_DISPLAY("sysparm_display", "CamelServiceNowDisplay", String.class, ServiceNowConfiguration::getDisplay), + SYSPARM_PER_PAGE("sysparm_per_page", "CamelServiceNowPerPage", Integer.class, ServiceNowConfiguration::getPerPage), + SYSPARM_SORT_BY("sysparm_sortby", "CamelServiceNowSortBy", String.class, ServiceNowConfiguration::getSortBy), + SYSPARM_SORT_DIR("sysparm_sortdir", "CamelServiceNowSortDir", String.class, ServiceNowConfiguration::getSortDir), + SYSPARM_CONTAINS("sysparm_contains", "CamelServiceNowContains", String.class), + SYSPARM_TAGS("sysparm_tags", "CamelServiceNowTags", String.class), + SYSPARM_PAGE("sysparm_page", "CamelServiceNowPage", String.class), + SYSPARM_ELEMENTS_FILTER("sysparm_elements_filter", "CamelServiceNowElementsFilter", String.class), + SYSPARM_BREAKDOWN_RELATION("sysparm_breakdown_relation", "CamelServiceNowBreakdownRelation", String.class), + SYSPARM_DATA_SOURCE("sysparm_data_source", "CamelServiceNowDataSource", String.class), + SYSPARM_TOP_LEVEL_ONLY("sysparm_top_level_only", "CamelServiceNowTopLevelOnly", Boolean.class, ServiceNowConfiguration::getTopLevelOnly); + + private final String id; + private final String header; + private final Class<?> type; + private final Function<ServiceNowConfiguration, ?> defaultValueSupplier; + + ServiceNowParams(String id, String header, Class<?> type) { + this(id, header, type, null); + } + + ServiceNowParams(String id, String header, Class<?> type, Function<ServiceNowConfiguration, ?> defaultValueSupplier) { + ObjectHelper.notNull(id, "ServiceNowSysParam (id)"); + ObjectHelper.notNull(header, "ServiceNowSysParam (header)"); + ObjectHelper.notNull(type, "ServiceNowSysParam (type)"); + + this.id = id; + this.header = header.startsWith(ServiceNowConstants.CAMEL_HEADER_PREFIX) + ? header + : ServiceNowConstants.CAMEL_HEADER_PREFIX + ObjectHelper.capitalize(header); + + this.type = type; + this.defaultValueSupplier = defaultValueSupplier; + } + + public String getId() { + return id; + } + + public String getHeader() { + return header; + } + + public Class<?> getType() { + return type; + } + + public Object getDefaultValue(ServiceNowConfiguration configuration) { + return defaultValueSupplier != null ? defaultValueSupplier.apply(configuration) : null; + } + + public Object getHeaderValue(Message message) { + return message.getHeader(header, type); + } + + public Object getHeaderValue(Message message, ServiceNowConfiguration configuration) { + return message.getHeader(header, getDefaultValue(configuration), type); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/f655c941/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducer.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducer.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducer.java index d0c91c5..67e08bb 100644 --- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducer.java +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducer.java @@ -16,88 +16,8 @@ */ package org.apache.camel.component.servicenow; -import java.lang.ref.WeakReference; +import org.apache.camel.Producer; -import org.apache.camel.Exchange; -import org.apache.camel.Processor; -import org.apache.camel.component.servicenow.model.ServiceNowAggregateProcessor; -import org.apache.camel.component.servicenow.model.ServiceNowImportSetProcessor; -import org.apache.camel.component.servicenow.model.ServiceNowTableProcessor; -import org.apache.camel.impl.DefaultProducer; -import org.apache.camel.util.ObjectHelper; - -/** - * The ServiceNow producer. - */ -public class ServiceNowProducer extends DefaultProducer { - - private final ServiceNowEndpoint endpoint; - private final ServiceNowConfiguration configuration; - private final WeakThreadLocal tableCache; - private final WeakThreadLocal aggregateCache; - private final WeakThreadLocal importSetCache; - - public ServiceNowProducer(ServiceNowEndpoint endpoint) { - super(endpoint); - - this.endpoint = endpoint; - this.configuration = endpoint.getConfiguration(); - this.tableCache = new WeakThreadLocal(ServiceNowTableProcessor.SUPPLIER); - this.aggregateCache = new WeakThreadLocal(ServiceNowAggregateProcessor.SUPPLIER); - this.importSetCache = new WeakThreadLocal(ServiceNowImportSetProcessor.SUPPLIER); - } - - @Override - public void process(Exchange exchange) throws Exception { - String resource = exchange.getIn().getHeader(ServiceNowConstants.RESOURCE, configuration.getResource(), String.class); - - if (ObjectHelper.equal(ServiceNowConstants.RESOURCE_TABLE, resource, true)) { - tableCache.get().process(exchange); - } else if (ObjectHelper.equal(ServiceNowConstants.RESOURCE_AGGREGATE, resource, true)) { - aggregateCache.get().process(exchange); - } else if (ObjectHelper.equal(ServiceNowConstants.RESOURCE_IMPORT, resource, true)) { - importSetCache.get().process(exchange); - } else { - throw new IllegalArgumentException("Unknown resource type: " + resource); - } - } - - // ************************************************************************* - // Thread-Local processor instances as CXF client proxies are not thread - // safe. To be refactored once moved to Java 8 as ServiceNowProcessorSupplier - // can be replaced by: - // - // java.util.function.Function<ServiceNowEndpoint, Processor> - // - // so an instance of a specific processor can be obtained by a constructor - // ref, i.e: - // - // ServiceNowImportSetProcessor::new - // - // ************************************************************************* - - private final class WeakThreadLocal { - private final ThreadLocal<WeakReference<Processor>> cache; - private final ServiceNowProducerProcessor.Supplier supplier; - - WeakThreadLocal(ServiceNowProducerProcessor.Supplier supplier) { - this.cache = new ThreadLocal<>(); - this.supplier = supplier; - } - - public Processor get() throws Exception { - Processor processor = null; - WeakReference<Processor> ref = cache.get(); - if (ref != null) { - processor = ref.get(); - } - - if (processor == null) { - processor = supplier.get(endpoint); - cache.set(new WeakReference<>(processor)); - } - - return processor; - } - } +public interface ServiceNowProducer extends Producer { + ServiceNowRelease getRelease(); } http://git-wip-us.apache.org/repos/asf/camel/blob/f655c941/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducerProcessor.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducerProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducerProcessor.java deleted file mode 100644 index 83b61ce..0000000 --- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducerProcessor.java +++ /dev/null @@ -1,139 +0,0 @@ -/** - * 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.servicenow; - -import java.util.List; -import java.util.Map; - -import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.camel.Exchange; -import org.apache.camel.Message; -import org.apache.camel.Processor; -import org.apache.camel.util.ObjectHelper; - -public abstract class ServiceNowProducerProcessor<T> implements Processor { - - protected final ServiceNowEndpoint endpoint; - protected final ServiceNowConfiguration config; - protected final T client; - protected final ObjectMapper mapper; - - // Cache for JavaTypes - private final JavaTypeCache javaTypeCache; - - protected ServiceNowProducerProcessor(ServiceNowEndpoint endpoint, Class<T> type) throws Exception { - this.javaTypeCache = new JavaTypeCache(); - this.endpoint = endpoint; - this.config = endpoint.getConfiguration(); - this.client = endpoint.createClient(type); - this.mapper = ObjectHelper.notNull(config.getMapper(), "mapper"); - } - - @Override - public void process(Exchange exchange) throws Exception { - final Message in = exchange.getIn(); - final String tableName = in.getHeader(ServiceNowConstants.TABLE, config.getTable(), String.class); - final Class<?> model = in.getHeader(ServiceNowConstants.MODEL, config.getModel(tableName, Map.class), Class.class); - final String action = in.getHeader(ServiceNowConstants.ACTION, String.class); - final String sysId = in.getHeader(ServiceNowConstants.SYSPARM_ID, String.class); - - doProcess( - exchange, - ObjectHelper.notNull(model, "model"), - ObjectHelper.notNull(action, "action"), - ObjectHelper.notNull(tableName, "tableName"), - sysId); - } - - protected abstract void doProcess( - Exchange exchange, - Class<?> model, - String action, - String tableName, - String sysId) throws Exception; - - - protected ServiceNowProducerProcessor<T> validateBody(Message message, Class<?> model) { - return validateBody(message.getBody(), model); - } - - protected ServiceNowProducerProcessor<T> validateBody(Object body, Class<?> model) { - ObjectHelper.notNull(body, "body"); - - if (!body.getClass().isAssignableFrom(model)) { - throw new IllegalArgumentException( - "Body is not compatible with model (body=" + body.getClass() + ", model=" + model); - } - - return this; - } - - protected ServiceNowProducerProcessor<T> setBody(Message message, Class<?> model, JsonNode answer) throws Exception { - message.setBody(unwrap(answer, model)); - - return this; - } - - protected Object unwrap(JsonNode answer, Class<?> model) throws Exception { - Object result = null; - - if (answer != null) { - JsonNode node = answer.get("result"); - if (node != null) { - if (node.isArray()) { - if (model.isInstance(Map.class)) { - // If the model is a Map, there's no need to use any - // specific JavaType to instruct Jackson about the - // expected element type - result = mapper.treeToValue(node, List.class); - } else { - result = mapper.readValue(node.traverse(), javaTypeCache.get(model)); - } - } else { - result = mapper.treeToValue(node, model); - } - } - } - - return result; - } - - // ************************************************************************* - // Use ClassValue to lazy create and cache JavaType - // ************************************************************************* - - private class JavaTypeCache extends ClassValue<JavaType> { - @Override - protected JavaType computeValue(Class<?> type) { - return mapper.getTypeFactory().constructCollectionType(List.class, type); - } - } - - // ************************************************************************* - // To be replaced with: - // - // java.util.function.Function<ServiceNowEndpoint, Processor> - // - // Once Camel will be Java 8 ready - // ************************************************************************* - - public interface Supplier { - Processor get(ServiceNowEndpoint endpoint) throws Exception; - } -} http://git-wip-us.apache.org/repos/asf/camel/blob/f655c941/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducerSupplier.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducerSupplier.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducerSupplier.java new file mode 100644 index 0000000..d339417 --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducerSupplier.java @@ -0,0 +1,22 @@ +/** + * 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.servicenow; + +public interface ServiceNowProducerSupplier { + ServiceNowProducer get(ServiceNowEndpoint endpoint) throws Exception; +} http://git-wip-us.apache.org/repos/asf/camel/blob/f655c941/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowRelease.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowRelease.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowRelease.java new file mode 100644 index 0000000..84f475a --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowRelease.java @@ -0,0 +1,41 @@ +/** + * 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.servicenow; + +import org.apache.camel.component.servicenow.releases.fuji.FujiServiceNowProducer; +import org.apache.camel.component.servicenow.releases.helsinki.HelsinkiServiceNowProducer; + +public enum ServiceNowRelease implements ServiceNowProducerSupplier { + FUJI { + @Override + public ServiceNowProducer get(ServiceNowEndpoint endpoint) throws Exception { + return new FujiServiceNowProducer(endpoint); + } + }, + GENEVA { + @Override + public ServiceNowProducer get(ServiceNowEndpoint endpoint) throws Exception { + return null; + } + }, + HELSINKY { + @Override + public ServiceNowProducer get(ServiceNowEndpoint endpoint) throws Exception { + return new HelsinkiServiceNowProducer(endpoint); + } + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/f655c941/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/auth/AuthenticationRequestFilter.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/auth/AuthenticationRequestFilter.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/auth/AuthenticationRequestFilter.java index d6e3b05..9e934ad 100644 --- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/auth/AuthenticationRequestFilter.java +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/auth/AuthenticationRequestFilter.java @@ -35,9 +35,9 @@ public class AuthenticationRequestFilter implements ClientRequestFilter { private final OAuthToken token; private final String authString; - public AuthenticationRequestFilter(ServiceNowConfiguration configuration, OAuthToken token) throws IOException { + public AuthenticationRequestFilter(ServiceNowConfiguration configuration) throws IOException { this.configuration = configuration; - this.token = token; + this.token = configuration.hasOAuthAuthentication() ? new OAuthToken(this.configuration) : null; this.authString = buildBasicAuthString(configuration); }