diff options
18 files changed, 1354 insertions, 0 deletions
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: + + <dependency> + <groupId>org.openecomp</groupId> + <artifactId>router-core</artifactId> + <version>1.0.0-SNAPSHOT</version> + </dependency> + +# 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. + + + <route xmlns="http://camel.apache.org/schema/spring" trace="true"> + <!-- Take some input from the console. --> + <from uri="stream:in?promptMessage=Enter Something: " /> + + <!-- Set the URL that we want to send our REST request to. --> + <setHeader headerName="ecomp-url"> + <constant>https://localhost:9509/services/search-data-service/v1/search/indexes/gdf/documents/88</constant> + </setHeader> + + <!-- Set values for some HTTP headers that we want to populate for our reqeust. --> + <setHeader headerName="X-FromAppId"> + <constant>DataLayer</constant> + </setHeader> + <setHeader headerName="X-TransactionId"> + <constant>gdf1</constant> + </setHeader> + + <!-- Invoke the REST client, using our console input as the content body of our request. --> + <!-- Note that we provide the paths to the client certificate and keystore, as well as --> + <!-- the obfuscated password for the keystore. --> + <to uri="rest-client:put?ecompClientCert=c:/dev/dl_microservice/target/swm/package/nix/dist_files/opt/app/ajsc-aai-data-layer-microservice/bundleconfig/etc/auth/aai-client-cert.p12&ecompKeystore=c:/dev/dl_microservice/target/swm/package/nix/dist_files/opt/app/ajsc-aai-data-layer-microservice/bundleconfig/etc/auth/tomcat_keystore&ecompKeystorePassword=70c87528c88dcd9f9c2558d30e817868"/> + <to uri="stream:out" /> + + </route> @@ -0,0 +1,193 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.openecomp</groupId> + <artifactId>router-core</artifactId> + <packaging>bundle</packaging> + <version>1.0.0-SNAPSHOT</version> + <name>Core Data Router Components</name> + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> + <checkstyle.config.location>google_checks.xml</checkstyle.config.location> + <nexusproxy>https://nexus.onap.org</nexusproxy> + <!-- Sonar Properties --> + <sonar.language>java</sonar.language> + <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin> + <sonar.surefire.reportsPath>${project.build.directory}/surefire-reports</sonar.surefire.reportsPath> + <sonar.jacoco.reportPath>${project.build.directory}/coverage-reports/jacoco.exec</sonar.jacoco.reportPath> + <sonar.jacoco.reportMissing.force.zero>false</sonar.jacoco.reportMissing.force.zero> + <sonar.projectVersion>${project.version}</sonar.projectVersion> + </properties> + <dependencies> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-core</artifactId> + <version>2.15.5</version> + </dependency> + <!-- support camel documentation --> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>apt</artifactId> + <version>2.15.5</version> + </dependency> + <!-- logging --> + <dependency> + <groupId>org.openecomp.aai.logging-service</groupId> + <artifactId>common-logging</artifactId> + <version>1.0.0</version> + </dependency> + <dependency> + <groupId>com.att.nsa</groupId> + <artifactId>cambriaClient</artifactId> + <version>0.0.1</version> + </dependency> + <!-- Dependencies for the REST Client component --> + <!-- Library to obfuscate encrypted passwords --> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-security</artifactId> + <version>9.3.8.RC0</version> + </dependency> + <!-- ECOMP REST Client Library. --> + <dependency> + <groupId>org.openecomp.aai</groupId> + <artifactId>rest-client</artifactId> + <version>1.0.0-SNAPSHOT</version> + </dependency> + <!-- End REST Client specific dependencies. --> + <!-- testing --> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-test</artifactId> + <version>2.15.5</version> + <scope>test</scope> + </dependency> + </dependencies> + <build> + <defaultGoal>install</defaultGoal> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>2.5.1</version> + <configuration> + <source>1.8</source> + <target>1.8</target> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-resources-plugin</artifactId> + <version>2.6</version> + <configuration> + <encoding>UTF-8</encoding> + </configuration> + </plugin> + <!-- to generate the MANIFEST-FILE of the bundle --> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <version>2.3.7</version> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-SymbolicName>org.openecomp.router-core</Bundle-SymbolicName> + <Export-Service>org.apache.camel.spi.ComponentResolver;component=event-bus</Export-Service> + </instructions> + </configuration> + </plugin> + <!-- license plugin --> + <plugin> + <groupId>com.mycila</groupId> + <artifactId>license-maven-plugin</artifactId> + <version>3.0</version> + <configuration> + <header>License.txt</header> + <includes> + <include>src/main/java/**</include> + </includes> + </configuration> + <executions> + <execution> + <goals> + <goal>format</goal> + </goals> + <phase>process-sources</phase> + </execution> + </executions> + </plugin> + <!-- Checkstyle plugin - used to report on compliance with --> + <!-- the Google style guide. --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-site-plugin</artifactId> + <version>3.3</version> + <configuration> + <reportPlugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-checkstyle-plugin</artifactId> + <version>2.17</version> + <reportSets> + <reportSet> + <reports> + <report>checkstyle</report> + </reports> + </reportSet> + </reportSets> + </plugin> + </reportPlugins> + </configuration> + </plugin> + <plugin> + <groupId>org.sonatype.plugins</groupId> + <artifactId>nexus-staging-maven-plugin</artifactId> + <version>1.6.7</version> + <extensions>true</extensions> + <configuration> + <nexusUrl>${nexusproxy}</nexusUrl> + <stagingProfileId>176c31dfe190a</stagingProfileId> + <serverId>ecomp-staging</serverId> + </configuration> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>sonar-maven-plugin</artifactId> + <version>3.2</version> + </plugin> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + <version>0.7.7.201606060606</version> + <configuration> + <dumpOnExit>true</dumpOnExit> + </configuration> + <executions> + <execution> + <id>jacoco-initialize-unit-tests</id> + <goals> + <goal>prepare-agent</goal> + </goals> + <configuration> + <destFile>${project.build.directory}/coverage-reports/jacoco.exec</destFile> + <!-- <append>true</append> --> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + <distributionManagement> + <repository> + <id>ecomp-releases</id> + <name>ECOMP Release Repository</name> + <url>${nexusproxy}/content/repositories/releases/</url> + </repository> + <snapshotRepository> + <id>ecomp-snapshots</id> + <name>ECOMP Snapshot Repository</name> + <url>${nexusproxy}/content/repositories/snapshots/</url> + </snapshotRepository> + </distributionManagement> +</project>
\ 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<String, Object> 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<String> 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<String> 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<String, Object> 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<String, Object> 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<String, List<String>> 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<String, List<String>> populateRestHeaders(Exchange exchange) { + + Map<String, List<String>> 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 + |