From 3e372947d497014b4aad4c2c1d04d6c50a74e2e0 Mon Sep 17 00:00:00 2001 From: "Bansal, Nitin (nb121v)" Date: Mon, 8 May 2017 17:20:38 -0400 Subject: Initial OpenECOMP Data Router Core commit Change-Id: Iee15b2f7870476eb48e4fb95f2564d3377749c6b Signed-off-by: Bansal, Nitin (nb121v) --- .gitignore | 6 + .gitreview | 4 + License.txt | 22 ++ README.md | 102 ++++++++ pom.xml | 193 ++++++++++++++++ .../org/openecomp/event/EventBusComponent.java | 52 +++++ .../java/org/openecomp/event/EventBusConsumer.java | 181 +++++++++++++++ .../java/org/openecomp/event/EventBusEndpoint.java | 165 +++++++++++++ .../java/org/openecomp/event/EventBusProducer.java | 45 ++++ .../java/org/openecomp/logging/RouterCoreMsgs.java | 55 +++++ .../org/openecomp/rest/RestClientComponent.java | 55 +++++ .../org/openecomp/rest/RestClientConsumer.java | 41 ++++ .../org/openecomp/rest/RestClientEndpoint.java | 127 ++++++++++ .../org/openecomp/rest/RestClientProducer.java | 256 +++++++++++++++++++++ .../services/org/apache/camel/component/event-bus | 1 + .../org/apache/camel/component/rest-client | 1 + .../resources/logging/RouterCoreMsgs.properties | 34 +++ src/test/resources/log4j.properties | 14 ++ 18 files changed, 1354 insertions(+) create mode 100644 .gitignore create mode 100644 .gitreview create mode 100644 License.txt create mode 100644 README.md create mode 100644 pom.xml create mode 100644 src/main/java/org/openecomp/event/EventBusComponent.java create mode 100644 src/main/java/org/openecomp/event/EventBusConsumer.java create mode 100644 src/main/java/org/openecomp/event/EventBusEndpoint.java create mode 100644 src/main/java/org/openecomp/event/EventBusProducer.java create mode 100644 src/main/java/org/openecomp/logging/RouterCoreMsgs.java create mode 100644 src/main/java/org/openecomp/rest/RestClientComponent.java create mode 100644 src/main/java/org/openecomp/rest/RestClientConsumer.java create mode 100644 src/main/java/org/openecomp/rest/RestClientEndpoint.java create mode 100644 src/main/java/org/openecomp/rest/RestClientProducer.java create mode 100644 src/main/resources/META-INF/services/org/apache/camel/component/event-bus create mode 100644 src/main/resources/META-INF/services/org/apache/camel/component/rest-client create mode 100644 src/main/resources/logging/RouterCoreMsgs.properties create mode 100644 src/test/resources/log4j.properties diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e2b927a --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.classpath +.project +.settings/ +target/ +logs/ +debug-logs/ diff --git a/.gitreview b/.gitreview new file mode 100644 index 0000000..bb6b063 --- /dev/null +++ b/.gitreview @@ -0,0 +1,4 @@ +[gerrit] +host=gerrit.onap.org +port=29418 +project=aai/router-core.git diff --git a/License.txt b/License.txt new file mode 100644 index 0000000..d0741ef --- /dev/null +++ b/License.txt @@ -0,0 +1,22 @@ +============LICENSE_START======================================================= +DataRouter +================================================================================ +Copyright © 2017 AT&T Intellectual Property. +Copyright © 2017 Amdocs +All rights reserved. +================================================================================ +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License ati + + 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. +============LICENSE_END========================================================= + +ECOMP and OpenECOMP are trademarks +and service marks of AT&T Intellectual Property. diff --git a/README.md b/README.md new file mode 100644 index 0000000..58e7d2f --- /dev/null +++ b/README.md @@ -0,0 +1,102 @@ +# Overview +This component contains a number of general Apache Camel components which are intended for use by the data-router. + +# Maven Dependency +To make use of the Camel components included in this repository, include the following artifact in your dependencies list: + + + org.openecomp + router-core + 1.0.0-SNAPSHOT + + +# How to Build: + + > mvn clean install + + +## Rest Client Component + +The REST client component provides a simple endpoint for sending HTTP requests to a REST endpoint. + +### URI Format + ecomp-rest:op[?options] + +Where, + +op = One of GET, PUT, POST, or DELETE + +### URI Options +The following option parameters must be passed in to the component for HTTPS communications: + +| Parameter | Description | +| --------- | ----------- | +| ecomp-client-cert | Fully qualified path to the client certificate to use for HTTPS communications. | +| ecomp-keystore | Fully qualified path to the keystore file to use for HTTP communications. | +| ecomp-keystore-password | Obfuscated password for the keystore. | + +### IN Message + +#### Ecomp-Rest Header Parameters +| Header Name | Description | +| ----------- | ----------- | +| ecomp-url | The fully qualified URL for the HTTP request to be send. This is mandatory. | + +#### HTTP Header Parameters +The following parameters, if they are present in the Exchange In Message Headers, will be included as header values +in the HTTP request generated by the component: + +| HTTP Header Name | +| ---------------- | +| X-FromAppId | +| X-TransactionId | +| resourceVersion | +| ETag | +| If-Match | +| If-None-Match | +| Accept | + +#### Message Body +For HTTP operations that require a content body, the body of the IN message will be used. + +### OUT Message + +#### Headers +The following header values are populated on the OUT message: + +| ecomp-response-code | The response code produced by the HTTP request. | +| ecomp-response-message | The response message produced by the HTTP request. | + +#### Message Body +For HTTP operations that produce a content body, the body of the OUT message will be populated with this result. + +### Example + +The following route file illustrates a simple example which takes console input and invokes the rest client, using the input from the +console as the content body for the REST request. + + + + + + + + + https://localhost:9509/services/search-data-service/v1/search/indexes/gdf/documents/88 + + + + + DataLayer + + + gdf1 + + + + + + + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..985749e --- /dev/null +++ b/pom.xml @@ -0,0 +1,193 @@ + + + 4.0.0 + org.openecomp + router-core + bundle + 1.0.0-SNAPSHOT + Core Data Router Components + + UTF-8 + UTF-8 + google_checks.xml + https://nexus.onap.org + + java + jacoco + ${project.build.directory}/surefire-reports + ${project.build.directory}/coverage-reports/jacoco.exec + false + ${project.version} + + + + org.apache.camel + camel-core + 2.15.5 + + + + org.apache.camel + apt + 2.15.5 + + + + org.openecomp.aai.logging-service + common-logging + 1.0.0 + + + com.att.nsa + cambriaClient + 0.0.1 + + + + + org.eclipse.jetty + jetty-security + 9.3.8.RC0 + + + + org.openecomp.aai + rest-client + 1.0.0-SNAPSHOT + + + + + org.apache.camel + camel-test + 2.15.5 + test + + + + install + + + org.apache.maven.plugins + maven-compiler-plugin + 2.5.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-resources-plugin + 2.6 + + UTF-8 + + + + + org.apache.felix + maven-bundle-plugin + 2.3.7 + true + + + org.openecomp.router-core + org.apache.camel.spi.ComponentResolver;component=event-bus + + + + + + com.mycila + license-maven-plugin + 3.0 + +
License.txt
+ + src/main/java/** + +
+ + + + format + + process-sources + + +
+ + + + org.apache.maven.plugins + maven-site-plugin + 3.3 + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.17 + + + + checkstyle + + + + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.7 + true + + ${nexusproxy} + 176c31dfe190a + ecomp-staging + + + + org.codehaus.mojo + sonar-maven-plugin + 3.2 + + + org.jacoco + jacoco-maven-plugin + 0.7.7.201606060606 + + true + + + + jacoco-initialize-unit-tests + + prepare-agent + + + ${project.build.directory}/coverage-reports/jacoco.exec + + + + + +
+
+ + + ecomp-releases + ECOMP Release Repository + ${nexusproxy}/content/repositories/releases/ + + + ecomp-snapshots + ECOMP Snapshot Repository + ${nexusproxy}/content/repositories/snapshots/ + + +
\ No newline at end of file diff --git a/src/main/java/org/openecomp/event/EventBusComponent.java b/src/main/java/org/openecomp/event/EventBusComponent.java new file mode 100644 index 0000000..6795931 --- /dev/null +++ b/src/main/java/org/openecomp/event/EventBusComponent.java @@ -0,0 +1,52 @@ +/** + * ============LICENSE_START======================================================= + * DataRouter + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License ati + * + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ +package org.openecomp.event; + +import org.apache.camel.CamelContext; +import org.apache.camel.Endpoint; +import org.apache.camel.impl.UriEndpointComponent; + +import java.util.Map; + +/** + * Represents the component that manages {@link EventBusEndpoint}. + */ +public class EventBusComponent extends UriEndpointComponent { + + public EventBusComponent() { + super(EventBusEndpoint.class); + } + + public EventBusComponent(CamelContext context) { + super(context, EventBusEndpoint.class); + } + + protected Endpoint createEndpoint(String uri, String remaining, Map parameters) + throws Exception { + Endpoint endpoint = new EventBusEndpoint(uri, this); + setProperties(endpoint, parameters); + return endpoint; + } +} diff --git a/src/main/java/org/openecomp/event/EventBusConsumer.java b/src/main/java/org/openecomp/event/EventBusConsumer.java new file mode 100644 index 0000000..30ac40e --- /dev/null +++ b/src/main/java/org/openecomp/event/EventBusConsumer.java @@ -0,0 +1,181 @@ +/** + * ============LICENSE_START======================================================= + * DataRouter + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License ati + * + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ +package org.openecomp.event; + +import com.att.nsa.cambria.client.CambriaClientBuilders; +import com.att.nsa.cambria.client.CambriaClientBuilders.ConsumerBuilder; +import com.att.nsa.cambria.client.CambriaConsumer; + +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.Processor; +import org.apache.camel.impl.ScheduledPollConsumer; +import org.openecomp.cl.api.Logger; +import org.openecomp.cl.eelf.LoggerFactory; +import org.openecomp.cl.mdc.MdcContext; +import org.openecomp.logging.RouterCoreMsgs; + +import java.net.MalformedURLException; +import java.security.GeneralSecurityException; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.ScheduledThreadPoolExecutor; + +/** + * The consumer component which is used to pull messages off of the event bus and send them to the + * next processor in the route chain. This type of consumer is based off of a scheduled poller so + * that events are pulled on a regular basis. + */ +public class EventBusConsumer extends ScheduledPollConsumer { + + private Logger logger = LoggerFactory.getInstance().getLogger(EventBusConsumer.class); + private Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(EventBusConsumer.class); + private final EventBusEndpoint endpoint; + + private CambriaConsumer consumer; + + /** + * EventBusConsumer Constructor. + */ + public EventBusConsumer(EventBusEndpoint endpoint, Processor processor) { + super(endpoint, processor); + super.setDelay(endpoint.getPollingDelay()); + this.endpoint = endpoint; + + setScheduledExecutorService(new ScheduledThreadPoolExecutor(endpoint.getPoolSize())); + + String[] urls = endpoint.getUrl().split(","); + + List urlList = null; + + if (urls != null) { + urlList = Arrays.asList(urls); + } + + try { + + ConsumerBuilder consumerBuilder = new CambriaClientBuilders.ConsumerBuilder() + .usingHosts(urlList).onTopic(endpoint.getEventTopic()) + .knownAs(endpoint.getGroupName(), endpoint.getGroupId()); + + String apiKey = endpoint.getApiKey(); + String apiSecret = endpoint.getApiSecret(); + + if (apiKey != null && apiSecret != null) { + consumerBuilder.authenticatedBy(endpoint.getApiKey(), endpoint.getApiSecret()); + } + + consumer = consumerBuilder.build(); + + } catch (MalformedURLException | GeneralSecurityException e) { + logger.error(RouterCoreMsgs.EVENT_CONSUMER_CREATION_EXCEPTION, e.getLocalizedMessage()); + } + } + + /** + * Method which is called by the Camel process on a scheduled basis. This specific implementation + * reads messages off of the configured topic and schedules tasks to process them . + * + * @return the number of messages that were processed off the event queue + */ + @Override + protected int poll() throws Exception { + + logger.debug("Checking for event on topic: " + endpoint.getEventTopic()); + + int processCount = 0; + + Iterable messages = null; + + messages = consumer.fetch(); + + String topic = endpoint.getEventTopic(); + + for (String message : messages) { + Exchange exchange = endpoint.createExchange(); + exchange.getIn().setBody(message); + getScheduledExecutorService().submit(new EventProcessor(exchange, topic)); + ++processCount; + } + return processCount; + } + + protected void doStop() throws Exception { + super.doStop(); + if (consumer != null) { + consumer.close(); + } + } + + protected void doShutdown() throws Exception { + super.doShutdown(); + if (consumer != null) { + consumer.close(); + } + } + + /** + * Class responsible for processing messages pulled off of the event bus. + */ + private class EventProcessor implements Runnable { + + private Exchange message; + + private String topic; + + EventProcessor(Exchange message, String topic) { + this.message = message; + this.topic = topic; + } + + public void run() { + try { + + MdcContext.initialize(UUID.randomUUID().toString(), "DataRouter", "", "Event-Bus", ""); + + // Sends the message to the next processor in the defined Camel route + getProcessor().process(message); + + Message response = message.getOut(); + if (response != null) { + logger.debug("Routing response: " + response.getBody()); + } + + } catch (Exception e) { + logger.error(RouterCoreMsgs.EVENT_PROCESSING_EXCEPTION, e.getLocalizedMessage()); + } finally { + // log exception if an exception occurred and was not handled + if (message.getException() != null) { + logger.info(RouterCoreMsgs.PROCESS_EVENT, topic, "FAILURE"); + auditLogger.info(RouterCoreMsgs.PROCESS_EVENT, topic, "FAILURE"); + } else { + logger.info(RouterCoreMsgs.PROCESS_EVENT, topic, "SUCCESS"); + auditLogger.info(RouterCoreMsgs.PROCESS_EVENT, topic, "SUCCESS"); + } + } + } + } +} diff --git a/src/main/java/org/openecomp/event/EventBusEndpoint.java b/src/main/java/org/openecomp/event/EventBusEndpoint.java new file mode 100644 index 0000000..470b974 --- /dev/null +++ b/src/main/java/org/openecomp/event/EventBusEndpoint.java @@ -0,0 +1,165 @@ +/** + * ============LICENSE_START======================================================= + * DataRouter + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License ati + * + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ +package org.openecomp.event; + + +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.spi.Metadata; +import org.apache.camel.spi.UriEndpoint; +import org.apache.camel.spi.UriParam; +import org.apache.camel.spi.UriPath; +import org.eclipse.jetty.util.security.Password; + +/** + * Represents a EventBus endpoint. + */ +@UriEndpoint(scheme = "event-bus", syntax = "event-bus:name", + consumerClass = EventBusConsumer.class, title = "event-bus") +public class EventBusEndpoint extends DefaultEndpoint { + @UriPath + @Metadata(required = "true") + private String name; + + @UriParam(label = "eventTopic") + @Metadata(required = "true") + private String eventTopic; + @UriParam(label = "groupName") + @Metadata(required = "true") + private String groupName; + @UriParam(label = "groupId") + @Metadata(required = "true") + private String groupId; + @UriParam(label = "apiKey") + private String apiKey; + @UriParam(label = "apiSecret") + private String apiSecret; + @UriParam(label = "url") + @Metadata(required = "true") + private String url; + @UriParam(label = "poolSize") + @Metadata(required = "true", defaultValue="20") + private int poolSize = 20; + @UriParam(label = "pollingDelay") + @Metadata(required = "true", defaultValue="30000") + private int pollingDelay = 30000; + + public EventBusEndpoint() {} + + public EventBusEndpoint(String uri, EventBusComponent component) { + super(uri, component); + } + + public EventBusEndpoint(String endpointUri) { + super(endpointUri); + } + + public Producer createProducer() throws Exception { + return new EventBusProducer(this); + } + + public Consumer createConsumer(Processor processor) throws Exception { + return new EventBusConsumer(this, processor); + } + + public boolean isSingleton() { + return false; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public String getEventTopic() { + return eventTopic; + } + + public void setEventTopic(String eventTopic) { + this.eventTopic = eventTopic; + } + + public String getGroupName() { + return groupName; + } + + public void setGroupName(String groupName) { + this.groupName = groupName; + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getApiKey() { + return apiKey == null ? null : Password.deobfuscate(apiKey); + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public String getApiSecret() { + return apiSecret == null ? null : Password.deobfuscate(apiSecret); + } + + public void setApiSecret(String apiSecret) { + this.apiSecret = apiSecret; + } + + public int getPoolSize() { + return poolSize; + } + + public void setPoolSize(int poolsize) { + this.poolSize = poolsize; + } + + public int getPollingDelay() { + return pollingDelay; + } + + public void setPollingDelay(int pollingDelay) { + this.pollingDelay = pollingDelay; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } +} + diff --git a/src/main/java/org/openecomp/event/EventBusProducer.java b/src/main/java/org/openecomp/event/EventBusProducer.java new file mode 100644 index 0000000..ecfebc3 --- /dev/null +++ b/src/main/java/org/openecomp/event/EventBusProducer.java @@ -0,0 +1,45 @@ +/** + * ============LICENSE_START======================================================= + * DataRouter + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License ati + * + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ +package org.openecomp.event; + +import org.apache.camel.Exchange; +import org.apache.camel.impl.DefaultProducer; + +/** + * The EventBus producer. + */ +public class EventBusProducer extends DefaultProducer { + private EventBusEndpoint endpoint; + + public EventBusProducer(EventBusEndpoint endpoint) { + super(endpoint); + this.endpoint = endpoint; + } + + public void process(Exchange exchange) throws Exception { + // Publishing to event bus is currently not supported + } + +} diff --git a/src/main/java/org/openecomp/logging/RouterCoreMsgs.java b/src/main/java/org/openecomp/logging/RouterCoreMsgs.java new file mode 100644 index 0000000..cb79618 --- /dev/null +++ b/src/main/java/org/openecomp/logging/RouterCoreMsgs.java @@ -0,0 +1,55 @@ +/** + * ============LICENSE_START======================================================= + * DataRouter + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License ati + * + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ +package org.openecomp.logging; + +import com.att.eelf.i18n.EELFResourceManager; +import org.openecomp.cl.eelf.LogMessageEnum; + +public enum RouterCoreMsgs implements LogMessageEnum { + + /** + * Processed event {0}. Result: {1}. + * + * Arguments: {0} = event topic {1} = result + */ + PROCESS_EVENT, + /** + * Arguments: {0} = Processing exception + */ + EVENT_PROCESSING_EXCEPTION, + + /** + * Arguments: {0} = Creation exception + */ + EVENT_CONSUMER_CREATION_EXCEPTION; + + + /** + * Static initializer to ensure the resource bundles for this class are loaded... + */ + static { + EELFResourceManager.loadMessageBundle("logging/RouterCoreMsgs"); + } +} diff --git a/src/main/java/org/openecomp/rest/RestClientComponent.java b/src/main/java/org/openecomp/rest/RestClientComponent.java new file mode 100644 index 0000000..8d29af1 --- /dev/null +++ b/src/main/java/org/openecomp/rest/RestClientComponent.java @@ -0,0 +1,55 @@ +/** + * ============LICENSE_START======================================================= + * DataRouter + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License ati + * + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ +package org.openecomp.rest; + +import org.apache.camel.CamelContext; +import org.apache.camel.Endpoint; +import org.apache.camel.impl.UriEndpointComponent; + +import java.util.Map; + + +/** + * Represents the component that manages {@link RestClientEndpoint}. + */ +public class RestClientComponent extends UriEndpointComponent { + + public RestClientComponent() { + super(RestClientEndpoint.class); + } + + public RestClientComponent(CamelContext context) { + super(context, RestClientEndpoint.class); + } + + @Override + protected Endpoint createEndpoint(String uri, String remaining, Map parameters) + throws Exception { + + Endpoint endpoint = new RestClientEndpoint(uri, this); + setProperties(endpoint, parameters); + return endpoint; + } +} diff --git a/src/main/java/org/openecomp/rest/RestClientConsumer.java b/src/main/java/org/openecomp/rest/RestClientConsumer.java new file mode 100644 index 0000000..c9724f0 --- /dev/null +++ b/src/main/java/org/openecomp/rest/RestClientConsumer.java @@ -0,0 +1,41 @@ +/** + * ============LICENSE_START======================================================= + * DataRouter + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License ati + * + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ +package org.openecomp.rest; + +import org.apache.camel.Processor; +import org.apache.camel.impl.DefaultConsumer; + + +/** + * The RestClient consumer. + */ +public class RestClientConsumer extends DefaultConsumer { + private final RestClientEndpoint endpoint; + + public RestClientConsumer(RestClientEndpoint endpoint, Processor processor) { + super(endpoint, processor); + this.endpoint = endpoint; + } +} diff --git a/src/main/java/org/openecomp/rest/RestClientEndpoint.java b/src/main/java/org/openecomp/rest/RestClientEndpoint.java new file mode 100644 index 0000000..1b59704 --- /dev/null +++ b/src/main/java/org/openecomp/rest/RestClientEndpoint.java @@ -0,0 +1,127 @@ +/** + * ============LICENSE_START======================================================= + * DataRouter + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License ati + * + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ +package org.openecomp.rest; + +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.spi.Metadata; +import org.apache.camel.spi.UriEndpoint; +import org.apache.camel.spi.UriParam; +import org.apache.camel.spi.UriPath; + +import java.util.Map; + + +/** + * Represents a RestClient endpoint. + */ +@UriEndpoint(scheme = "ecomp-rest", syntax = "ecomp-rest:op", + consumerClass = RestClientConsumer.class, label = "RestClient2", title = "") +public class RestClientEndpoint extends DefaultEndpoint { + + public static final String CONTEXT_PARAM_CLIENT_CERT = "ecomp-client-cert"; + public static final String CONTEXT_PARAM_KEYSTORE = "ecomp-keystore"; + public static final String CONTEXT_PARAM_KEYSTORE_PWD = "ecomp-keystore-password"; + + public static final String IN_HEADER_URL = "ecomp-url"; + + public static final String OUT_HEADER_RESPONSE_CODE = "ecomp-response-code"; + public static final String OUT_HEADER_RESPONSE_MSG = "ecomp-response-message"; + + @UriPath + @Metadata(required = "true") + private String op; + + @UriParam + private String ecompClientCert; + + @UriParam + private String ecompKeystore; + + @UriParam + private String ecompKeystorePassword; + + + public RestClientEndpoint() {} + + public RestClientEndpoint(String uri, RestClientComponent component) { + super(uri, component); + } + + public RestClientEndpoint(String endpointUri) { + super(endpointUri); + } + + @Override + protected void setProperties(Object bean, Map parameters) throws Exception { + super.setProperties(bean, parameters); + } + + public Producer createProducer() throws Exception { + return new RestClientProducer(this); + } + + public Consumer createConsumer(Processor processor) throws Exception { + return new RestClientConsumer(this, processor); + } + + public boolean isSingleton() { + return true; + } + + public String getOp() { + return op; + } + + public void setOp(String op) { + this.op = op; + } + + public String getEcompClientCert() { + return ecompClientCert; + } + + public void setEcompClientCert(String ecompClientCert) { + this.ecompClientCert = ecompClientCert; + } + + public String getEcompKeystore() { + return ecompKeystore; + } + + public void setEcompKeystore(String ecompKeystore) { + this.ecompKeystore = ecompKeystore; + } + + public String getEcompKeystorePassword() { + return ecompKeystorePassword; + } + + public void setEcompKeystorePassword(String ecompKeystorePassword) { + this.ecompKeystorePassword = ecompKeystorePassword; + } +} diff --git a/src/main/java/org/openecomp/rest/RestClientProducer.java b/src/main/java/org/openecomp/rest/RestClientProducer.java new file mode 100644 index 0000000..3a8df18 --- /dev/null +++ b/src/main/java/org/openecomp/rest/RestClientProducer.java @@ -0,0 +1,256 @@ +/** + * ============LICENSE_START======================================================= + * DataRouter + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License ati + * + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ +package org.openecomp.rest; + +import org.apache.camel.Exchange; +import org.apache.camel.impl.DefaultProducer; +import org.eclipse.jetty.util.security.Password; +import org.openecomp.cl.api.Logger; +import org.openecomp.cl.eelf.LoggerFactory; +import org.openecomp.event.EventBusConsumer; + +import org.openecomp.restclient.client.Headers; +import org.openecomp.restclient.client.OperationResult; +import org.openecomp.restclient.client.RestClient; +import org.openecomp.restclient.rest.HttpUtil; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + + +/** + * The EcompRest producer. + */ +public class RestClientProducer extends DefaultProducer { + + private static enum Operation { + GET, PUT, POST, DELETE + } + + private RestClientEndpoint endpoint; + + /** REST client used for sending HTTP requests. */ + private RestClient restClient; + + private Logger logger = LoggerFactory.getInstance().getLogger(RestClientProducer.class); + + + public RestClientProducer(RestClientEndpoint endpoint) { + super(endpoint); + this.endpoint = endpoint; + } + + @Override + public void process(Exchange exchange) { + + // Extract the URL for our REST request from the IN message header. + String url = exchange.getIn().getHeader(RestClientEndpoint.IN_HEADER_URL).toString(); + + // Populate the HTTP Request header values from any values passed in via the + // IN message headers. + Map> headers = populateRestHeaders(exchange); + + if (logger.isDebugEnabled()) { + StringBuilder sb = new StringBuilder(); + sb.append("Process REST request - operation=").append(getOperation(exchange)); + sb.append(" headers=["); + for (String key : headers.keySet()) { + sb.append("{").append(key).append("->").append(headers.get(key)).append("} "); + } + sb.append("]"); + sb.append(" content: ").append(exchange.getIn().getBody()); + logger.debug(sb.toString()); + } + + // Now, invoke the REST client to perform the operation. + OperationResult result = null; + switch (getOperation(exchange)) { + + case GET: + result = getRestClient().get(url, headers, MediaType.APPLICATION_JSON_TYPE); + break; + + case PUT: + result = getRestClient().put(url, exchange.getIn().getBody().toString(), headers, + MediaType.APPLICATION_JSON_TYPE, null); + break; + + case POST: + result = getRestClient().post(url, exchange.getIn().getBody().toString(), headers, + MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE); + break; + + case DELETE: + result = getRestClient().delete(url, headers, MediaType.APPLICATION_JSON_TYPE); + break; + + default: + // The supplied operation is not supported. + result = new OperationResult(); + result.setResultCode(Response.Status.BAD_REQUEST.getStatusCode()); + result.setFailureCause("Unsupported HTTP Operation: " + getOperation(exchange)); + + break; + } + + // Populate the OUT message with our result. + exchange.getOut().setHeader(RestClientEndpoint.OUT_HEADER_RESPONSE_CODE, + result.getResultCode()); + if (HttpUtil.isHttpResponseClassSuccess(result.getResultCode())) { + exchange.getOut().setHeader(RestClientEndpoint.OUT_HEADER_RESPONSE_MSG, + responseStatusStringFromResult(result)); + exchange.getOut().setBody(result.getResult()); + } else { + exchange.getOut().setHeader(RestClientEndpoint.OUT_HEADER_RESPONSE_MSG, + result.getFailureCause()); + } + + } + + + /** + * Extracts the requested REST operation from the exchange message. + * + * @param exchange - The Camel exchange to pull the operation from. + * + * @return - The REST operation being requested. + */ + private Operation getOperation(Exchange exchange) { + + String toEndpoint = ((String) exchange.getProperty(Exchange.TO_ENDPOINT)); + + String operation = toEndpoint.substring((toEndpoint.lastIndexOf("://") + 3)); + + int position = operation.indexOf('?'); + if (position >= 0) { + operation = operation.substring(0, position); + } + + return Operation.valueOf(operation.toUpperCase()); + } + + + + /** + * This method extracts values from the IN message which are intended to be used to populate the + * HTTP Header entries for our REST request. + * + * @param exchange - The Camel exchange to extract the HTTP header parameters from. + * + * @return - A map of HTTP header names and values. + */ + private Map> populateRestHeaders(Exchange exchange) { + + Map> headers = new HashMap<>(); + + if (exchange.getIn().getHeader(Headers.FROM_APP_ID) != null) { + headers.put(Headers.FROM_APP_ID, + Arrays.asList(exchange.getIn().getHeader(Headers.FROM_APP_ID).toString())); + } + if (exchange.getIn().getHeader(Headers.TRANSACTION_ID) != null) { + headers.put(Headers.TRANSACTION_ID, + Arrays.asList(exchange.getIn().getHeader(Headers.TRANSACTION_ID).toString())); + } + if (exchange.getIn().getHeader(Headers.RESOURCE_VERSION) != null) { + headers.put(Headers.RESOURCE_VERSION, + Arrays.asList(exchange.getIn().getHeader(Headers.RESOURCE_VERSION).toString())); + } + if (exchange.getIn().getHeader(Headers.ETAG) != null) { + headers.put(Headers.ETAG, Arrays.asList(exchange.getIn().getHeader(Headers.ETAG).toString())); + } + if (exchange.getIn().getHeader(Headers.IF_MATCH) != null) { + headers.put(Headers.IF_MATCH, + Arrays.asList(exchange.getIn().getHeader(Headers.IF_MATCH).toString())); + } + if (exchange.getIn().getHeader(Headers.IF_NONE_MATCH) != null) { + headers.put(Headers.IF_NONE_MATCH, + Arrays.asList(exchange.getIn().getHeader(Headers.IF_NONE_MATCH).toString())); + } + if (exchange.getIn().getHeader(Headers.ACCEPT) != null) { + headers.put(Headers.ACCEPT, + Arrays.asList(exchange.getIn().getHeader(Headers.ACCEPT).toString())); + } + if (exchange.getIn().getHeader("Content-Type") != null) { + headers.put("Content-Type", + Arrays.asList(exchange.getIn().getHeader("Content-Type").toString())); + } + + return headers; + } + + + /** + * This helper method converts an HTTP response code into the associated string. + * + * @param result - A result object to get the response code from. + * + * @return - The string message associated with the supplied response code. + */ + private String responseStatusStringFromResult(OperationResult result) { + + // Not every valid response code is actually represented by the Response.Status + // object, so we need to guard against missing codes, otherwise we throw null + // pointer exceptions when we try to generate our metrics logs... + Response.Status responseStatus = Response.Status.fromStatusCode(result.getResultCode()); + String responseStatusCodeString = ""; + if (responseStatus != null) { + responseStatusCodeString = responseStatus.toString(); + } + + return responseStatusCodeString; + } + + /** + * Instantiate the REST client that will be used for sending our HTTP requests. + * + * @return - An instance of the REST client. + */ + private RestClient getRestClient() { + + if (restClient == null) { + + String keystoreFilename = endpoint.getEcompKeystore(); + String keystorePassword = endpoint.getEcompKeystorePassword(); + String clientCertFilename = endpoint.getEcompClientCert(); + + if (logger.isDebugEnabled()) { + logger.debug("Instantiating REST Client with client_cert=" + clientCertFilename + + " keystore=" + keystoreFilename + " keystorePassword=" + keystorePassword); + } + + // Create REST client for search service + restClient = new RestClient().validateServerHostname(false).validateServerCertChain(true) + .clientCertFile(clientCertFilename) + .clientCertPassword(Password.deobfuscate(keystorePassword)).trustStore(keystoreFilename); + } + + return restClient; + } +} diff --git a/src/main/resources/META-INF/services/org/apache/camel/component/event-bus b/src/main/resources/META-INF/services/org/apache/camel/component/event-bus new file mode 100644 index 0000000..8256ed6 --- /dev/null +++ b/src/main/resources/META-INF/services/org/apache/camel/component/event-bus @@ -0,0 +1 @@ +class=org.openecomp.event.EventBusComponent diff --git a/src/main/resources/META-INF/services/org/apache/camel/component/rest-client b/src/main/resources/META-INF/services/org/apache/camel/component/rest-client new file mode 100644 index 0000000..493eb1f --- /dev/null +++ b/src/main/resources/META-INF/services/org/apache/camel/component/rest-client @@ -0,0 +1 @@ +class=org.openecomp.rest.RestClientComponent diff --git a/src/main/resources/logging/RouterCoreMsgs.properties b/src/main/resources/logging/RouterCoreMsgs.properties new file mode 100644 index 0000000..5c8c183 --- /dev/null +++ b/src/main/resources/logging/RouterCoreMsgs.properties @@ -0,0 +1,34 @@ +#Resource key=Error Code|Message text|Resolution text |Description text +####### +#Newlines can be utilized to add some clarity ensuring continuing line +#has atleast one leading space +#ResourceKey=\ +# ERR0000E\ +# Sample error msg txt\ +# Sample resolution msg\ +# Sample description txt +# +###### +#Error code classification category +#000 Info/Debug +#100 Permission errors +#200 Availability errors/Timeouts +#300 Data errors +#400 Schema Interface type/validation errors +#500 Business process errors +#900 Unknown errors +# +######################################################################## + + +PROCESS_EVENT=\ + AC0001I|\ + Processed event from topic {0}. Result: {1} + +EVENT_PROCESSING_EXCEPTION=\ + AC0501E|\ + Could not process request from event bus due to the following exception: {0} + +EVENT_CONSUMER_CREATION_EXCEPTION=\ + AC0502E|\ + Could not create event consumer due to the following exception: {0} \ No newline at end of file diff --git a/src/test/resources/log4j.properties b/src/test/resources/log4j.properties new file mode 100644 index 0000000..3b1bd38 --- /dev/null +++ b/src/test/resources/log4j.properties @@ -0,0 +1,14 @@ +# +# The logging properties used +# +log4j.rootLogger=INFO, out + +# uncomment the following line to turn on Camel debugging +#log4j.logger.org.apache.camel=DEBUG + +# CONSOLE appender not used by default +log4j.appender.out=org.apache.log4j.ConsoleAppender +log4j.appender.out.layout=org.apache.log4j.PatternLayout +log4j.appender.out.layout.ConversionPattern=[%30.30t] %-30.30c{1} %-5p %m%n +#log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n + -- cgit 1.2.3-korg