diff options
author | Liam Fallon <liam.fallon@ericsson.com> | 2018-06-08 17:05:17 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@onap.org> | 2018-06-08 17:05:17 +0000 |
commit | d0746b062ca6b85eae756db6eb6c4dead037a35a (patch) | |
tree | 896107ee6e4787c42f34225fed944653f18bb2be /plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver | |
parent | 6a9b54b275feff5369419a86997e94d0a95fc48e (diff) | |
parent | 697d02bf4e4188e3040cd987dee97d15f397a35f (diff) |
Merge "Adding plugins-event module to apex-pdp"
Diffstat (limited to 'plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver')
7 files changed, 871 insertions, 0 deletions
diff --git a/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/pom.xml b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/pom.xml new file mode 100644 index 000000000..643908932 --- /dev/null +++ b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/pom.xml @@ -0,0 +1,59 @@ +<!-- + ============LICENSE_START======================================================= + Copyright (C) 2018 Ericsson. 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 at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + SPDX-License-Identifier: Apache-2.0 + ============LICENSE_END========================================================= +--> +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.onap.policy.apex-pdp.plugins.plugins-event.plugins-event-carrier</groupId> + <artifactId>plugins-event-carrier</artifactId> + <version>2.0.0-SNAPSHOT</version> + </parent> + + <artifactId>plugins-event-carrier-restserver</artifactId> + <name>${project.artifactId}</name> + <description>[${project.parent.artifactId}] Plugin for handling events being transported over REST where Apex acts as a REST server</description> + + <properties> + <apex-plugins-event-carrier-restserver-dir>${project.basedir}/src</apex-plugins-event-carrier-restserver-dir> + </properties> + + <dependencies> + <dependency> + <groupId>org.onap.policy.apex-pdp.services</groupId> + <artifactId>services-engine</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.core</groupId> + <artifactId>jersey-client</artifactId> + <version>${version.jersey.core}</version> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.containers</groupId> + <artifactId>jersey-container-grizzly2-http</artifactId> + <version>${version.grizzly2-http}</version> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.containers</groupId> + <artifactId>jersey-container-servlet-core</artifactId> + <version>2.25.1</version> + </dependency> + </dependencies> +</project>
\ No newline at end of file diff --git a/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/ApexRestServerConsumer.java b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/ApexRestServerConsumer.java new file mode 100644 index 000000000..71bf80f66 --- /dev/null +++ b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/ApexRestServerConsumer.java @@ -0,0 +1,281 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2016-2018 Ericsson. 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 at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.apex.plugins.event.carrier.restserver; + +import java.net.URI; +import java.util.EnumMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + +import javax.ws.rs.core.Response; + +import org.glassfish.grizzly.http.server.HttpServer; +import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; +import org.glassfish.jersey.server.ResourceConfig; +import org.onap.policy.apex.core.infrastructure.threading.ApplicationThreadFactory; +import org.onap.policy.apex.core.infrastructure.threading.ThreadUtilities; +import org.onap.policy.apex.service.engine.event.ApexEventConsumer; +import org.onap.policy.apex.service.engine.event.ApexEventException; +import org.onap.policy.apex.service.engine.event.ApexEventReceiver; +import org.onap.policy.apex.service.engine.event.PeeredReference; +import org.onap.policy.apex.service.engine.event.SynchronousEventCache; +import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters; +import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This class implements an Apex event consumer that receives events from a REST server. + * + * @author Liam Fallon (liam.fallon@ericsson.com) + */ +public class ApexRestServerConsumer implements ApexEventConsumer, Runnable { + // Get a reference to the logger + private static final Logger LOGGER = LoggerFactory.getLogger(ApexRestServerConsumer.class); + + private static final String BASE_URI_TEMPLATE = "http://%s:%d/apex"; + + // The amount of time to wait in milliseconds between checks that the consumer thread has stopped + private static final long REST_SERVER_CONSUMER_WAIT_SLEEP_TIME = 50; + + // The REST parameters read from the parameter service + private RESTServerCarrierTechnologyParameters restConsumerProperties; + + // The event receiver that will receive events from this consumer + private ApexEventReceiver eventReceiver; + + // The name for this consumer + private String name = null; + + // The peer references for this event handler + private Map<EventHandlerPeeredMode, PeeredReference> peerReferenceMap = new EnumMap<>(EventHandlerPeeredMode.class); + + // The consumer thread and stopping flag + private Thread consumerThread; + private boolean stopOrderedFlag = false; + + // The local HTTP server to use for REST call reception if we are running a local Grizzly server + private HttpServer server; + + // Holds the next identifier for event execution. + private static AtomicLong nextExecutionID = new AtomicLong(0L); + + /** + * Private utility to get the next candidate value for a Execution ID. This value will always be unique in a single + * JVM + * + * @return the next candidate value for a Execution ID + */ + private static synchronized long getNextExecutionID() { + return nextExecutionID.getAndIncrement(); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.service.engine.event.ApexEventConsumer#init(java.lang.String, + * org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters, + * org.onap.policy.apex.service.engine.event.ApexEventReceiver) + */ + @Override + public void init(final String consumerName, final EventHandlerParameters consumerParameters, + final ApexEventReceiver incomingEventReceiver) throws ApexEventException { + this.eventReceiver = incomingEventReceiver; + this.name = consumerName; + + // Check and get the REST Properties + if (!(consumerParameters.getCarrierTechnologyParameters() instanceof RESTServerCarrierTechnologyParameters)) { + final String errorMessage = + "specified consumer properties are not applicable to REST Server consumer (" + this.name + ")"; + LOGGER.warn(errorMessage); + throw new ApexEventException(errorMessage); + } + restConsumerProperties = + (RESTServerCarrierTechnologyParameters) consumerParameters.getCarrierTechnologyParameters(); + + // Check if we are in synchronous mode + if (!consumerParameters.isPeeredMode(EventHandlerPeeredMode.SYNCHRONOUS)) { + final String errorMessage = + "REST Server consumer (" + this.name + ") must run in synchronous mode with a REST Server producer"; + LOGGER.warn(errorMessage); + throw new ApexEventException(errorMessage); + } + + // Check if we're in standalone mode + if (restConsumerProperties.isStandalone()) { + // Check if host and port are defined + if (restConsumerProperties.getHost() == null || restConsumerProperties.getPort() == -1) { + final String errorMessage = + "the parameters \"host\" and \"port\" must be defined for REST Server consumer (" + this.name + + ") in standalone mode"; + LOGGER.warn(errorMessage); + throw new ApexEventException(errorMessage); + } + + // Compose the URI for the standalone server + final String baseURI = String.format(BASE_URI_TEMPLATE, restConsumerProperties.getHost(), + restConsumerProperties.getPort()); + + // Instantiate the standalone server + final ResourceConfig rc = new ResourceConfig(RestServerEndpoint.class); + server = GrizzlyHttpServerFactory.createHttpServer(URI.create(baseURI), rc); + + while (!server.isStarted()) { + ThreadUtilities.sleep(REST_SERVER_CONSUMER_WAIT_SLEEP_TIME); + } + } + + // Register this consumer with the REST server end point + RestServerEndpoint.registerApexRestServerConsumer(this.name, this); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.service.engine.event.ApexEventConsumer#start() + */ + @Override + public void start() { + // Configure and start the event reception thread + final String threadName = this.getClass().getName() + ":" + this.name; + consumerThread = new ApplicationThreadFactory(threadName).newThread(this); + consumerThread.setDaemon(true); + consumerThread.start(); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.service.engine.event.ApexEventConsumer#getName() + */ + @Override + public String getName() { + return name; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.service.engine.event.ApexEventConsumer#getPeeredReference(org.onap.policy.apex.service. + * parameters. eventhandler.EventHandlerPeeredMode) + */ + @Override + public PeeredReference getPeeredReference(final EventHandlerPeeredMode peeredMode) { + return peerReferenceMap.get(peeredMode); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.service.engine.event.ApexEventConsumer#setPeeredReference(org.onap.policy.apex.service. + * parameters. eventhandler.EventHandlerPeeredMode, org.onap.policy.apex.service.engine.event.PeeredReference) + */ + @Override + public void setPeeredReference(final EventHandlerPeeredMode peeredMode, final PeeredReference peeredReference) { + peerReferenceMap.put(peeredMode, peeredReference); + } + + /** + * Receive an event for processing in Apex. + * + * @param event the event to receive + * @return the response from Apex + */ + public Response receiveEvent(final String event) { + // Get an execution ID for the event + final long executionId = getNextExecutionID(); + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(name + ": sending event " + name + '_' + executionId + " to Apex, event=" + event); + } + + try { + // Send the event into Apex + eventReceiver.receiveEvent(executionId, event); + } catch (final Exception e) { + final String errorMessage = "error receiving events on event consumer " + name + ", " + e.getMessage(); + LOGGER.warn(errorMessage); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()) + .entity("{'errorMessage', '" + errorMessage + "'}").build(); + } + + final SynchronousEventCache synchronousEventCache = + (SynchronousEventCache) peerReferenceMap.get(EventHandlerPeeredMode.SYNCHRONOUS); + // Wait until the event is in the cache of events sent to apex + do { + ThreadUtilities.sleep(REST_SERVER_CONSUMER_WAIT_SLEEP_TIME); + } while (!synchronousEventCache.existsEventToApex(executionId)); + + // Now wait for the reply or for the event to time put + do { + ThreadUtilities.sleep(REST_SERVER_CONSUMER_WAIT_SLEEP_TIME); + + // Check if we have received an answer from Apex + if (synchronousEventCache.existsEventFromApex(executionId)) { + // We have received a response event, read and remove the response event and remove the sent event from + // the cache + final Object responseEvent = synchronousEventCache.removeCachedEventFromApexIfExists(executionId); + synchronousEventCache.removeCachedEventToApexIfExists(executionId); + + // Return the event as a response to the call + return Response.status(Response.Status.OK.getStatusCode()).entity(responseEvent.toString()).build(); + } + } while (synchronousEventCache.existsEventToApex(executionId)); + + // The event timed out + final String errorMessage = "processing of event on event consumer " + name + " timed out, event=" + event; + LOGGER.warn(errorMessage); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()) + .entity("{'errorMessage', '" + errorMessage + "'}").build(); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + // Keep the consumer thread alive until it is shut down. We do not currently do anything in the thread but may + // do supervision in the future + while (consumerThread.isAlive() && !stopOrderedFlag) { + ThreadUtilities.sleep(REST_SERVER_CONSUMER_WAIT_SLEEP_TIME); + } + + if (server != null) { + server.shutdown(); + } + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.apps.uservice.consumer.ApexEventConsumer#stop() + */ + @Override + public void stop() { + stopOrderedFlag = true; + + while (consumerThread.isAlive()) { + ThreadUtilities.sleep(REST_SERVER_CONSUMER_WAIT_SLEEP_TIME); + } + } +} diff --git a/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/ApexRestServerProducer.java b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/ApexRestServerProducer.java new file mode 100644 index 000000000..e51482ce4 --- /dev/null +++ b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/ApexRestServerProducer.java @@ -0,0 +1,167 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2016-2018 Ericsson. 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 at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.apex.plugins.event.carrier.restserver; + +import java.util.EnumMap; +import java.util.Map; + +import org.onap.policy.apex.service.engine.event.ApexEventException; +import org.onap.policy.apex.service.engine.event.ApexEventProducer; +import org.onap.policy.apex.service.engine.event.PeeredReference; +import org.onap.policy.apex.service.engine.event.SynchronousEventCache; +import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters; +import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Concrete implementation of an Apex event producer that sends events using REST. + * + * @author Liam Fallon (liam.fallon@ericsson.com) + * + */ +public class ApexRestServerProducer implements ApexEventProducer { + private static final Logger LOGGER = LoggerFactory.getLogger(ApexRestServerProducer.class); + + // The REST carrier properties + private RESTServerCarrierTechnologyParameters restProducerProperties; + + // The name for this producer + private String name = null; + + // The peer references for this event handler + private Map<EventHandlerPeeredMode, PeeredReference> peerReferenceMap = new EnumMap<>(EventHandlerPeeredMode.class); + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.service.engine.event.ApexEventProducer#init(java.lang.String, + * org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters) + */ + @Override + public void init(final String producerName, final EventHandlerParameters producerParameters) + throws ApexEventException { + this.name = producerName; + + // Check and get the REST Properties + if (!(producerParameters.getCarrierTechnologyParameters() instanceof RESTServerCarrierTechnologyParameters)) { + final String errorMessage = + "specified producer properties are not applicable to REST Server producer (" + this.name + ")"; + LOGGER.warn(errorMessage); + throw new ApexEventException(errorMessage); + } + restProducerProperties = + (RESTServerCarrierTechnologyParameters) producerParameters.getCarrierTechnologyParameters(); + + // Check if host and port are defined + if (restProducerProperties.getHost() != null || restProducerProperties.getPort() != -1 + || restProducerProperties.isStandalone()) { + final String errorMessage = + "the parameters \"host\", \"port\", and \"standalone\" are illegal on REST Server producer (" + + this.name + ")"; + LOGGER.warn(errorMessage); + throw new ApexEventException(errorMessage); + } + + // Check if we are in synchronous mode + if (!producerParameters.isPeeredMode(EventHandlerPeeredMode.SYNCHRONOUS)) { + final String errorMessage = + "REST Server producer (" + this.name + ") must run in synchronous mode with a REST Server consumer"; + LOGGER.warn(errorMessage); + throw new ApexEventException(errorMessage); + } + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.service.engine.event.ApexEventProducer#getName() + */ + @Override + public String getName() { + return name; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.service.engine.event.ApexEventProducer#getPeeredReference(org.onap.policy.apex.service. + * parameters. eventhandler.EventHandlerPeeredMode) + */ + @Override + public PeeredReference getPeeredReference(final EventHandlerPeeredMode peeredMode) { + return peerReferenceMap.get(peeredMode); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.service.engine.event.ApexEventProducer#setPeeredReference(org.onap.policy.apex.service. + * parameters. eventhandler.EventHandlerPeeredMode, org.onap.policy.apex.service.engine.event.PeeredReference) + */ + @Override + public void setPeeredReference(final EventHandlerPeeredMode peeredMode, final PeeredReference peeredReference) { + peerReferenceMap.put(peeredMode, peeredReference); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.service.engine.event.ApexEventProducer#sendEvent(long, java.lang. String, + * java.lang.Object) + */ + @Override + public void sendEvent(final long executionId, final String eventName, final Object event) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(name + ": event " + executionId + ':' + eventName + " recevied from Apex, event=" + event); + } + + // If we are not synchronized, then exit + final SynchronousEventCache synchronousEventCache = + (SynchronousEventCache) peerReferenceMap.get(EventHandlerPeeredMode.SYNCHRONOUS); + if (synchronousEventCache == null) { + return; + } + + // We see all events on the receiver, even those that are not replies to events sent by the synchronized + // consumer of this producer, ignore those + // events + if (!synchronousEventCache.existsEventToApex(executionId)) { + return; + } + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(name + ": event " + executionId + ':' + eventName + " is a reply to a REST server call from " + + name); + } + + // Add the event to the received event cache + synchronousEventCache.cacheSynchronizedEventFromApex(executionId, event); + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.service.engine.event.ApexEventProducer#stop() + */ + @Override + public void stop() {} +} diff --git a/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/RESTServerCarrierTechnologyParameters.java b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/RESTServerCarrierTechnologyParameters.java new file mode 100644 index 000000000..47e31fffa --- /dev/null +++ b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/RESTServerCarrierTechnologyParameters.java @@ -0,0 +1,136 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2016-2018 Ericsson. 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 at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.apex.plugins.event.carrier.restserver; + +import org.onap.policy.apex.service.parameters.carriertechnology.CarrierTechnologyParameters; + +/** + * Apex parameters for REST as an event carrier technology with Apex as a REST client. + * + * The parameters for this plugin are: + * <ol> + * <li>standalone: A flag indicating if APEX should start a standalone HTTP server to process REST requests (true) or + * whether it should use an underlying servlet infrastructure such as Apache Tomcat (False). This parameter is legal + * only on REST server event inputs. + * <li>host: The host name to use when setting up a standalone HTTP server. This parameter is legal only on REST server + * event inputs in standalone mode. + * <li>port: The port to use when setting up a standalone HTTP server. This parameter is legal only on REST server event + * inputs in standalone mode. + * </ol> + * + * @author Liam Fallon (liam.fallon@ericsson.com) + */ +public class RESTServerCarrierTechnologyParameters extends CarrierTechnologyParameters { + // @formatter:off + private static final int MIN_USER_PORT = 1024; + private static final int MAX_USER_PORT = 65535; + + /** The label of this carrier technology. */ + public static final String RESTSERVER_CARRIER_TECHNOLOGY_LABEL = "RESTSERVER"; + + /** The producer plugin class for the REST carrier technology. */ + public static final String RESTSERVER_EVENT_PRODUCER_PLUGIN_CLASS = ApexRestServerProducer.class.getCanonicalName(); + + /** The consumer plugin class for the REST carrier technology. */ + public static final String RESTSERVER_EVENT_CONSUMER_PLUGIN_CLASS = ApexRestServerConsumer.class.getCanonicalName(); + + // REST server parameters + private boolean standalone = false; + private String host = null; + private int port = -1; + // @formatter:on + + /** + * Constructor to create a REST carrier technology parameters instance and register the instance with the parameter + * service. + */ + public RESTServerCarrierTechnologyParameters() { + super(RESTServerCarrierTechnologyParameters.class.getCanonicalName()); + + // Set the carrier technology properties for the web socket carrier technology + this.setLabel(RESTSERVER_CARRIER_TECHNOLOGY_LABEL); + this.setEventProducerPluginClass(RESTSERVER_EVENT_PRODUCER_PLUGIN_CLASS); + this.setEventConsumerPluginClass(RESTSERVER_EVENT_CONSUMER_PLUGIN_CLASS); + } + + /** + * Check if the REST server is running in standalone mode or is using an underlying servlet infrastructure to manage + * requests. + * + * @return true if in standalone mode + */ + public boolean isStandalone() { + return standalone; + } + + /** + * Gets the host. + * + * @return the host + */ + public String getHost() { + return host; + } + + /** + * Gets the port. + * + * @return the port + */ + public int getPort() { + return port; + } + + /* + * (non-Javadoc) + * + * @see org.onap.policy.apex.apps.uservice.parameters.ApexParameterValidator#validate() + */ + @Override + public String validate() { + final StringBuilder errorMessageBuilder = new StringBuilder(); + + errorMessageBuilder.append(super.validate()); + + // Check if host is defined, it is only defined on REST server consumers + if (standalone) { + if (host != null) { + if (host.trim().length() == 0) { + errorMessageBuilder.append(" host not specified, must be host as a string\n"); + } + } + + // Check if port is defined, it is only defined on REST server consumers + if (port != -1) { + if (port < MIN_USER_PORT || port > MAX_USER_PORT) { + errorMessageBuilder + .append(" port [" + port + "] invalid, must be specified as 1024 <= port <= 6535\n"); + } + } + } else { + if (host != null || port != -1) { + errorMessageBuilder.append(" host and port are specified only in standalone mode\n"); + } + } + + return errorMessageBuilder.toString(); + } +} diff --git a/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/RestServerEndpoint.java b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/RestServerEndpoint.java new file mode 100644 index 000000000..beee10fd0 --- /dev/null +++ b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/RestServerEndpoint.java @@ -0,0 +1,150 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2016-2018 Ericsson. 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 at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.apex.plugins.event.carrier.restserver; + +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Class RestServerEndpoint is the end point servlet class for handling REST requests and responses to and from + * Apex. + * + * @author Liam Fallon (liam.fallon@ericsson.com) + */ +@Path("/{eventInput}") +@Produces({ MediaType.APPLICATION_JSON }) +@Consumes({ MediaType.APPLICATION_JSON }) +public class RestServerEndpoint { + // Get a reference to the logger + private static final Logger LOGGER = LoggerFactory.getLogger(RestServerEndpoint.class); + + // Statistics on the amount of HTTP messages handled + private static int getMessagesReceived = 0; + private static int postEventMessagesReceived = 0; + private static int putEventMessagesReceived = 0; + + // This map is used to hold all the REST server event inputs. This is used to determine which consumer to send input + // events to + private static Map<String, ApexRestServerConsumer> consumerMap = + new LinkedHashMap<String, ApexRestServerConsumer>(); + + // The ID of this event input. This gets injected from the URL. + @PathParam("eventInput") + private String eventInputID = null; + + /** + * Register an Apex consumer with the REST server end point. + * + * @param consumerEventInputID The event input ID that indicates this consumer shoud be used + * @param consumer The consumer to register + */ + public static void registerApexRestServerConsumer(final String consumerEventInputID, + final ApexRestServerConsumer consumer) { + consumerMap.put(consumerEventInputID, consumer); + } + + /** + * Get statistics on apex REST event handling. + * + * @return the response + */ + @Path("/Status") + @GET + public Response serviceGetStats() { + getMessagesReceived++; + return Response.status(Response.Status.OK.getStatusCode()) + .entity("{\n" + "\"INPUTS\": \"" + consumerMap.keySet() + "\",\n" + "\"STAT\": " + getMessagesReceived + + ",\n" + "\"POST\": " + postEventMessagesReceived + ",\n" + "\"PUT\": " + + putEventMessagesReceived + "\n}") + .build(); + } + + /** + * Service post request, an incoming event over RETS to Apex. + * + * @param jsonString the JSON string containing the data coming in on the REST call + * @return the response event to the request + */ + @Path("/EventIn") + @POST + public Response servicePostRequest(final String jsonString) { + postEventMessagesReceived++; + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("event input " + eventInputID + ", received POST of event \"" + jsonString + "\""); + } + + // Common handler method for POST and PUT requests + return handleEvent(jsonString); + } + + /** + * Service put request, an incoming event over RETS to Apex. + * + * @param jsonString the JSON string containing the data coming in on the REST call + * @return the response event to the request + */ + @Path("/EventIn") + @PUT + public Response servicePutRequest(final String jsonString) { + putEventMessagesReceived++; + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("event input \"" + eventInputID + "\", received PUT of event \"" + jsonString + "\""); + } + + // Common handler method for POST and PUT requests + return handleEvent(jsonString); + } + + /** + * Common event handler for events received on POST and PUT messages. + * + * @param jsonString the JSON string containing the data coming in on the REST call + * @return the response event to the request + */ + private Response handleEvent(final String jsonString) { + // Find the correct consumer for this REST message + final ApexRestServerConsumer eventConsumer = consumerMap.get(eventInputID); + if (eventConsumer == null) { + final String errorMessage = + "event input " + eventInputID + " is not defined in the Apex configuration file"; + LOGGER.warn(errorMessage); + return Response.status(Response.Status.BAD_REQUEST.getStatusCode()) + .entity("{'errorMessage', '" + errorMessage + "'}").build(); + } + + return eventConsumer.receiveEvent(jsonString); + } +} diff --git a/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/package-info.java b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/package-info.java new file mode 100644 index 000000000..98a1c4bd6 --- /dev/null +++ b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/main/java/org/onap/policy/apex/plugins/event/carrier/restserver/package-info.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2016-2018 Ericsson. 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 at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +/** + * APEX REST consumer and producer plugins when APEX is acting as a REST client. + * + * @author Joss Armstrong (joss.armstrong@ericsson.com) + * + */ + +package org.onap.policy.apex.plugins.event.carrier.restserver; diff --git a/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/test/resources/logback-test.xml b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/test/resources/logback-test.xml new file mode 100644 index 000000000..dc591b1f1 --- /dev/null +++ b/plugins/plugins-event/plugins-event-carrier/plugins-event-carrier-restserver/src/test/resources/logback-test.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + Copyright (C) 2016-2018 Ericsson. 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 at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + SPDX-License-Identifier: Apache-2.0 + ============LICENSE_END========================================================= +--> + +<configuration> + + <contextName>Apex</contextName> + <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" /> + <property name="LOG_DIR" value="${java.io.tmpdir}/apex_logging/" /> + + <!-- USE FOR STD OUT ONLY --> + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <Pattern>%d %contextName [%t] %level %logger{36} - %msg%n</Pattern> + </encoder> + </appender> + + <root level="info"> + <appender-ref ref="STDOUT" /> + </root> + + <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${LOG_DIR}/apex.log</file> + <encoder> + <pattern>%d %-5relative [procId=${processId}] [%thread] %-5level + %logger{26} - %msg %n %ex{full}</pattern> + </encoder> + </appender> + + <logger name="org.onap.policy.apex.plugins.event.carrier.restserver" level="trace" additivity="false"> + <appender-ref ref="STDOUT" /> + </logger> +</configuration> |