summaryrefslogtreecommitdiffstats
path: root/champ-service
diff options
context:
space:
mode:
Diffstat (limited to 'champ-service')
-rw-r--r--champ-service/License.txt21
-rw-r--r--champ-service/ajsc-shared-config/etc/logback.xml235
-rw-r--r--champ-service/antBuild/build.xml178
-rw-r--r--champ-service/appconfig-local/auth/champion-service_policy.json-REPLACE1
-rw-r--r--champ-service/appconfig-local/auth/tomcat_keystore-REPLACE1
-rw-r--r--champ-service/appconfig-local/champ-api.properties-REPLACE7
-rw-r--r--champ-service/bundleconfig-local/etc/appprops/AAFUserRoles.properties12
-rw-r--r--champ-service/bundleconfig-local/etc/appprops/PostProcessorInterceptors.properties2
-rw-r--r--champ-service/bundleconfig-local/etc/appprops/PreProcessorInterceptors.properties3
-rw-r--r--champ-service/bundleconfig-local/etc/appprops/app-intercepts.properties7
-rw-r--r--champ-service/bundleconfig-local/etc/appprops/methodMapper.properties45
-rw-r--r--champ-service/bundleconfig-local/etc/sysprops/sys-props.properties117
-rw-r--r--champ-service/pom.xml360
-rw-r--r--champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/conf/jaxrsBeans.groovy11
-rw-r--r--champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/docs/README.txt1
-rw-r--r--champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/lib/README.txt1
-rw-r--r--champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/champ.route4
-rw-r--r--champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/jaxrsExample.route5
-rw-r--r--champ-service/src/main/assemble/ajsc_module_assembly.xml66
-rw-r--r--champ-service/src/main/assemble/ajsc_props_assembly.xml23
-rw-r--r--champ-service/src/main/assemble/ajsc_runtime_assembly.xml44
-rw-r--r--champ-service/src/main/bin/start.sh94
-rw-r--r--champ-service/src/main/config/ajsc-chef.jksbin0 -> 5256 bytes
-rw-r--r--champ-service/src/main/config/ajsc-jetty.xml114
-rw-r--r--champ-service/src/main/config/ajsc-override-web.xml50
-rw-r--r--champ-service/src/main/config/ajscJetty.jksbin0 -> 3736 bytes
-rw-r--r--champ-service/src/main/config/cadi.properties28
-rw-r--r--champ-service/src/main/config/jul-redirect.properties13
-rw-r--r--champ-service/src/main/config/keyfile27
-rw-r--r--champ-service/src/main/config/runner-web.xml94
-rw-r--r--champ-service/src/main/docker/Dockerfile34
-rw-r--r--champ-service/src/main/java/org/onap/champ/ChampRESTAPI.java568
-rw-r--r--champ-service/src/main/java/org/onap/champ/async/ChampAsyncRequestProcessor.java327
-rw-r--r--champ-service/src/main/java/org/onap/champ/async/ChampAsyncResponsePublisher.java160
-rw-r--r--champ-service/src/main/java/org/onap/champ/entity/ChampObjectDeserializer.java67
-rw-r--r--champ-service/src/main/java/org/onap/champ/entity/ChampObjectSerializer.java54
-rw-r--r--champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipDeserializer.java73
-rw-r--r--champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipSerializer.java55
-rw-r--r--champ-service/src/main/java/org/onap/champ/event/GraphEvent.java245
-rw-r--r--champ-service/src/main/java/org/onap/champ/event/GraphEventEdge.java221
-rw-r--r--champ-service/src/main/java/org/onap/champ/event/GraphEventVertex.java187
-rw-r--r--champ-service/src/main/java/org/onap/champ/exception/ChampServiceException.java62
-rw-r--r--champ-service/src/main/java/org/onap/champ/service/ChampDataService.java355
-rw-r--r--champ-service/src/main/java/org/onap/champ/service/ChampThreadFactory.java47
-rw-r--r--champ-service/src/main/java/org/onap/champ/service/ChampTransactionCache.java77
-rw-r--r--champ-service/src/main/java/org/onap/champ/service/ChampUUIDService.java115
-rw-r--r--champ-service/src/main/java/org/onap/champ/service/EchoService.java54
-rw-r--r--champ-service/src/main/java/org/onap/champ/service/logging/ChampMsgs.java130
-rw-r--r--champ-service/src/main/java/org/onap/champ/service/logging/LoggingUtil.java92
-rw-r--r--champ-service/src/main/java/org/onap/champ/util/ChampProperties.java53
-rw-r--r--champ-service/src/main/java/org/onap/champ/util/ChampServiceConstants.java14
-rw-r--r--champ-service/src/main/resources/META-INF/services/javax.ws.rs.client.ClientBuilder1
-rw-r--r--champ-service/src/main/resources/logging/ChampMsgs.properties78
-rw-r--r--champ-service/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context1
-rw-r--r--champ-service/src/main/runtime/context/default#0.context1
-rw-r--r--champ-service/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json1
-rw-r--r--champ-service/src/main/runtime/shiroRole/ajscadmin.json1
-rw-r--r--champ-service/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json1
-rw-r--r--champ-service/src/main/runtime/shiroRole/contextadmin#default.json1
-rw-r--r--champ-service/src/main/runtime/shiroUser/ajsc.json1
-rw-r--r--champ-service/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json1
-rw-r--r--champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json1
-rw-r--r--champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json1
63 files changed, 4643 insertions, 0 deletions
diff --git a/champ-service/License.txt b/champ-service/License.txt
new file mode 100644
index 0000000..469f362
--- /dev/null
+++ b/champ-service/License.txt
@@ -0,0 +1,21 @@
+============LICENSE_START==========================================
+org.onap.aai
+===================================================================
+Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+Copyright © 2017 Amdocs
+===================================================================
+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.
+============LICENSE_END============================================
+ECOMP is a trademark and service mark of AT&T Intellectual Property.
+
+
diff --git a/champ-service/ajsc-shared-config/etc/logback.xml b/champ-service/ajsc-shared-config/etc/logback.xml
new file mode 100644
index 0000000..12ed478
--- /dev/null
+++ b/champ-service/ajsc-shared-config/etc/logback.xml
@@ -0,0 +1,235 @@
+<!--
+
+ ============LICENSE_START==========================================
+ org.onap.aai
+ ===================================================================
+ Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ Copyright © 2017 Amdocs
+ ===================================================================
+ 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.
+ ============LICENSE_END============================================
+ ECOMP is a trademark and service mark of AT&T Intellectual Property.
+
+-->
+<configuration scan="true" scanPeriod="3 seconds" debug="false">
+ <!--<jmxConfigurator /> -->
+ <!-- directory path for all other type logs -->
+
+ <property name="logDir" value="${AJSC_HOME}/logs" />
+
+
+ <!-- specify the component name
+ <ECOMP-component-name>::= "MSO" | "DCAE" | "ASDC " | "AAI" |"Policy" | "SDNC" | "AC" -->
+ <property name="componentName" value="AAI-CHAMP" />
+
+ <!-- default eelf log file names -->
+ <property name="generalLogName" value="error" />
+ <property name="metricsLogName" value="metrics" />
+ <property name="auditLogName" value="audit" />
+ <property name="debugLogName" value="debug" />
+
+ <property name="errorLogPattern" value="%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%mdc{RequestId}|%thread|champ-service|%mdc{PartnerName}|%logger||%.-5level|%msg%n" />
+ <property name="auditMetricPattern" value="%m%n" />
+
+ <property name="logDirectory" value="${logDir}/${componentName}" />
+
+ <!-- Example evaluator filter applied against console appender -->
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>${errorLogPattern}</pattern>
+ </encoder>
+ </appender>
+
+ <!-- ============================================================================ -->
+ <!-- EELF Appenders -->
+ <!-- ============================================================================ -->
+
+ <!-- The EELFAppender is used to record events to the general application
+ log -->
+
+ <appender name="EELF"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${logDirectory}/${generalLogName}.log</file>
+ <rollingPolicy
+ class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/${generalLogName}.%d{yyyy-MM-dd}.log.zip
+ </fileNamePattern>
+ <maxHistory>60</maxHistory>
+ </rollingPolicy>
+ <encoder>
+ <pattern>${errorLogPattern}</pattern>
+ </encoder>
+ </appender>
+ <appender name="asyncEELF" class="ch.qos.logback.classic.AsyncAppender">
+ <!-- deny all events with a level below INFO, that is TRACE and DEBUG -->
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>INFO</level>
+ </filter>
+ <queueSize>256</queueSize>
+ <appender-ref ref="EELF" />
+ </appender>
+
+
+ <!-- EELF Audit Appender. This appender is used to record audit engine
+ related logging events. The audit logger and appender are specializations
+ of the EELF application root logger and appender. This can be used to segregate
+ Policy engine events from other components, or it can be eliminated to record
+ these events as part of the application root log. -->
+
+ <appender name="EELFAudit"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${logDirectory}/${auditLogName}.log</file>
+ <rollingPolicy
+ class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/${auditLogName}.%d{yyyy-MM-dd}.log.zip
+ </fileNamePattern>
+ <maxHistory>60</maxHistory>
+ </rollingPolicy>
+ <encoder>
+ <pattern>${auditMetricPattern}</pattern>
+ </encoder>
+ </appender>
+ <appender name="asyncEELFAudit" class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>256</queueSize>
+ <appender-ref ref="EELFAudit" />
+ </appender>
+
+ <appender name="EELFMetrics"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${logDirectory}/${metricsLogName}.log</file>
+ <rollingPolicy
+ class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/${metricsLogName}.%d{yyyy-MM-dd}.log.zip
+ </fileNamePattern>
+ <maxHistory>60</maxHistory>
+ </rollingPolicy>
+ <encoder>
+ <!-- <pattern>"%d{HH:mm:ss.SSS} [%thread] %-5level %logger{1024} -
+ %msg%n"</pattern> -->
+ <pattern>${auditMetricPattern}</pattern>
+ </encoder>
+ </appender>
+
+
+ <appender name="asyncEELFMetrics" class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>256</queueSize>
+ <appender-ref ref="EELFMetrics"/>
+ </appender>
+
+ <appender name="EELFDebug"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${logDirectory}/${debugLogName}.log</file>
+ <rollingPolicy
+ class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/${debugLogName}.%d{yyyy-MM-dd}.log.zip
+ </fileNamePattern>
+ <maxHistory>60</maxHistory>
+ </rollingPolicy>
+ <encoder>
+ <pattern>${errorLogPattern}</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="asyncEELFDebug" class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>256</queueSize>
+ <appender-ref ref="EELFDebug" />
+ <includeCallerData>false</includeCallerData>
+ </appender>
+
+
+ <!-- ============================================================================ -->
+ <!-- EELF loggers -->
+ <!-- ============================================================================ -->
+ <logger name="com.att.eelf" level="info" additivity="false">
+ <appender-ref ref="asyncEELF" />
+ <appender-ref ref="asyncEELFDebug" />
+ </logger>
+
+ <logger name="com.att.eelf.security" level="info" additivity="false">
+ <appender-ref ref="asyncEELFSecurity" />
+ </logger>
+ <logger name="com.att.eelf.perf" level="info" additivity="false">
+ <appender-ref ref="asyncEELFPerformance" />
+ </logger>
+ <logger name="com.att.eelf.server" level="info" additivity="false">
+ <appender-ref ref="asyncEELFServer" />
+ </logger>
+ <logger name="com.att.eelf.policy" level="info" additivity="false">
+ <appender-ref ref="asyncEELFPolicy" />
+ </logger>
+ <logger name="com.att.eelf.audit" level="info" additivity="false">
+ <appender-ref ref="asyncEELFAudit" />
+ </logger>
+ <logger name="com.att.eelf.metrics" level="info" additivity="false">
+ <appender-ref ref="asyncEELFMetrics" />
+ </logger>
+
+ <!-- Spring related loggers -->
+ <logger name="org.springframework" level="WARN" />
+ <logger name="org.springframework.beans" level="WARN" />
+ <logger name="org.springframework.web" level="WARN" />
+ <logger name="com.blog.spring.jms" level="WARN" />
+
+ <!-- AJSC Services (bootstrap services) -->
+ <logger name="ajsc" level="WARN" />
+ <logger name="ajsc.RouteMgmtService" level="WARN" />
+ <logger name="ajsc.ComputeService" level="WARN" />
+ <logger name="ajsc.VandelayService" level="WARN" />
+ <logger name="ajsc.FilePersistenceService" level="WARN" />
+ <logger name="ajsc.UserDefinedJarService" level="WARN" />
+ <logger name="ajsc.UserDefinedBeansDefService" level="WARN" />
+ <logger name="ajsc.LoggingConfigurationService" level="WARN" />
+
+ <!-- AJSC related loggers (DME2 Registration, csi logging, restlet, servlet
+ logging) -->
+ <logger name="ajsc.utils" level="WARN" />
+ <logger name="ajsc.utils.DME2Helper" level="WARN" />
+ <logger name="ajsc.filters" level="WARN" />
+ <logger name="ajsc.beans.interceptors" level="WARN" />
+ <logger name="ajsc.restlet" level="WARN" />
+ <logger name="ajsc.servlet" level="WARN" />
+ <logger name="com.att" level="INFO" />
+ <logger name="com.att.ajsc.csi.logging" level="WARN" />
+ <logger name="com.att.ajsc.filemonitor" level="WARN" />
+
+ <!-- champ-service loggers -->
+ <logger name="org.onap.champ" level="INFO" />
+
+ <!-- Other Loggers that may help troubleshoot -->
+ <logger name="net.sf" level="WARN" />
+ <logger name="org.apache" level="WARN" />
+ <logger name="org.apache.commons.httpclient" level="WARN" />
+ <logger name="org.apache.commons" level="WARN" />
+ <logger name="org.apache.coyote" level="WARN" />
+ <logger name="org.apache.jasper" level="WARN" />
+
+ <!-- Camel Related Loggers (including restlet/servlet/jaxrs/cxf logging.
+ May aid in troubleshooting) -->
+ <logger name="org.apache.camel" level="WARN" />
+ <logger name="org.apache.cxf" level="WARN" />
+ <logger name="org.apache.camel.processor.interceptor" level="WARN" />
+ <logger name="org.apache.cxf.jaxrs.interceptor" level="WARN" />
+ <logger name="org.apache.cxf.service" level="WARN" />
+ <logger name="org.restlet" level="WARN" />
+ <logger name="org.apache.camel.component.restlet" level="WARN" />
+
+ <!-- logback internals logging -->
+ <logger name="ch.qos.logback.classic" level="WARN" />
+ <logger name="ch.qos.logback.core" level="WARN" />
+
+ <root>
+ <appender-ref ref="asyncEELF" />
+ <!-- <appender-ref ref="asyncEELFDebug" /> -->
+ </root>
+
+</configuration>
diff --git a/champ-service/antBuild/build.xml b/champ-service/antBuild/build.xml
new file mode 100644
index 0000000..b898a9e
--- /dev/null
+++ b/champ-service/antBuild/build.xml
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+ <target name="runLocal">
+ <java dir="${basedir}" fork="yes" newenvironment="true"
+ failonerror="true" classname="com.att.ajsc.runner.Runner">
+ <classpath
+ path="${classpath}:${basedir}/ajsc-shared-config/etc:${runAjscHome}/lib/ajsc-runner-${ajscRuntimeVersion}.jar" />
+
+ <!-- Windows Users may need to add a jvmarg arg to create a temp directory
+ properly. -->
+ <!-- <jvmarg value="-Djava.io.tmpdir=C:/yourTempDirectory"/> -->
+
+ <!-- Uncomment the following 2 jvmarg values to enable Remote Debugging.
+ -->
+ <!-- <jvmarg value="-Xdebug" /> -->
+ <!-- <jvmarg value="-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5432"
+ /> -->
+
+ <jvmarg value="-XX:MaxPermSize=512m" />
+ <jvmarg value="-Xmx1024m" />
+
+ <!-- Main ajsc Variables below (Variables necessary for proper startup
+ of AJSC) -->
+ <env key="AJSC_HOME" value="${runAjscHome}" />
+ <sysproperty key="AJSC_HOME" value="${runAjscHome}" />
+ <!-- you may specify any external location for AJSC_CONF_HOME where etc
+ folder & all other configs can be found under it. If not specified, it will
+ default to AJSC_HOME -->
+ <sysproperty key="AJSC_CONF_HOME" value="${basedir}/bundleconfig-local" />
+ <sysproperty key="AJSC_SHARED_CONFIG" value="${basedir}/ajsc-shared-config" />
+
+ <!-- Location of logback.xml file used for logging configurations. Please,
+ note, when deploying a service to either CSI or NON-CSI environment, this
+ system property will be set in sys-props.properties file. We are setting
+ it here for running locally due to the ease of use of maven variable for
+ basedir. -->
+ <sysproperty key="logback.configurationFile"
+ value="${basedir}/ajsc-shared-config/etc/logback.xml" />
+
+ <!-- Setting system properties for the AJSC external libs and properties
+ folders below. When deploying to a node, these properties will be set within
+ the bundleconfig/etc/sysprops/sys-props.properties file. However, when running
+ locally, the ${basedir} substitution works more efficiently in this manner. -->
+ <sysproperty key="AJSC_EXTERNAL_LIB_FOLDERS" value="${basedir}/target/commonLibs" />
+ <sysproperty key="AJSC_EXTERNAL_PROPERTIES_FOLDERS"
+ value="${basedir}/ajsc-shared-config/etc" />
+
+ <!-- End of Main ajsc Variables below (Variables necessary for proper
+ startup of AJSC) -->
+
+ <!-- Uncomment the following line to add oauthentication to your Service -->
+ <!-- <sysproperty key="spring.profiles.active" value="oauth" /> -->
+
+ <!-- If using Cassandra as Database, Enter the ip/host and port below
+ based on your known configuration -->
+ <!-- <sysproperty key="cassandra.ip" value="hostname" /> -->
+ <!-- <sysproperty key="cassandra.port" value="9042" /> -->
+
+ <!-- The APP_SERVLET_URL_PATTERN variable is defaulted to "/services"
+ within the initial configuration of the AJSC. If you are changing the CamelServlet
+ Filter within the ajsc-override-web.xml, you should use that url-pattern
+ here. This is necessary to properly register your service with dme2. An empty
+ value, "", is used when NO value is wanted (url-pattern would be /* for CamelServlet
+ Filter) -->
+ <!-- As of 4.5.1, this property is no longer needed -->
+ <!-- <sysproperty key="APP_SERVLET_URL_PATTERN" value="/services" /> -->
+
+ <!-- GRM/DME2 System Properties below -->
+ <sysproperty key="AJSC_SERVICE_NAMESPACE" value="${module.ajsc.namespace.name}" />
+ <sysproperty key="AJSC_SERVICE_VERSION" value="${module.ajsc.namespace.version}" />
+ <sysproperty key="SOACLOUD_SERVICE_VERSION" value="${project.version}" />
+ <!-- End of GRM/DME2 System Property Variables -->
+
+ <!-- The following server.port variable was necessary for the proper registration
+ of the AJSC to dme2. This value may still need to be used if the Developer
+ is hardcoding their port (example: 8080). Then, the server.port value="8080".
+ The default functionality for the AJSC is to use EPHEMERAL ports. In this
+ case, you do NOT need to set the server.port value. The AJSC will find the
+ proper port value and register to dme2 correctly -->
+ <!-- <sysproperty key="server.port" value="${serverPort}" /> -->
+
+ <!-- Command Line Arguments to add to the java command. Here, you can
+ specify the port as well as the Context you want your service to run in.
+ Use context=/ to run in an unnamed Context (Root Context). The default configuration
+ of the AJSC is to run under the /ajsc Context. Setting the port here can
+ aid during the development phase of your service. However, you can leave
+ this argument out entirely, and the AJSC will default to using an Ephemeral
+ port. -->
+ <arg line="context=/ port=${serverPort} sslport=${sslport}" />
+ </java>
+ </target>
+ <target name="prep_home_directory_for_swm_pkgcreate">
+
+
+ <!-- These tasks are copying contents from the installHomeDirectory into
+ the eventual $AJSC_HOME directory for running locally and soa cloud installation -->
+ <echo message="ENTERING 'prep_home_directory_for_swm_pkgcreate' ant tasks" />
+
+ <copy
+ toDir="${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/bundleconfig"
+ failonerror="true">
+ <fileset dir="${basedir}/bundleconfig-local" includes="**/**" />
+ </copy>
+ <copy
+ toDir="${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/bundleconfig/etc"
+ failonerror="true">
+ <fileset dir="${basedir}/ajsc-shared-config/etc" includes="**/**" />
+ </copy>
+ <!-- End of NON-CSI related build copy task. -->
+
+ <!-- Copying any zips (deployment packages) to $AJSC_HOME/services for
+ auto-deployment -->
+ <copy
+ toDir="${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/services"
+ failonerror="false">
+ <fileset dir="${basedir}/services" includes="*.zip" />
+ </copy>
+
+ <!-- Copying runtimeEnvironment zip file to $AJSC_HOME/runtime and renaming
+ runtimeEnvironment.zip for proper auto-deployment of ajsc services.
+ <copy
+ tofile="${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/runtime/runtimeEnvironment.zip">
+ <fileset dir="target" includes="*-runtimeEnvironment.zip" />
+ </copy>-->
+
+ <!-- Copying dependencies from the service project (not provided by AJSC
+ Container) to the $AJSC_HOME/extJars folder to be accessible on the classpath -->
+ <copy
+ toDir="${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/extJars"
+ failonerror="false">
+ <fileset dir="target/userjars" includes="*" />
+ </copy>
+
+ <!-- extApps directory MUST be created for ajsc-runner to run correctly,
+ even if empty. DO NOT REMOVE!!! -->
+ <!-- extApps directory created to deploy other war files on startup or
+ hot deploy War files after ajsc starts up. -->
+ <mkdir
+ dir="${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/extApps" />
+
+ <!-- Copying any extra wars to $AJSC_HOME/extApps to be deployed within
+ AJSC -->
+ <copy
+ toDir="${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/extApps"
+ failonerror="false">
+ <fileset dir="${basedir}/src/main/resources/extApps"
+ includes="*" />
+ </copy>
+
+ <!-- staticContent folder is for serving static content within an ajsc
+ service. Any static content to be served will be copyied to the ultimate
+ $AJSC_HOME/staticContent folder and can be served with the att-static-content
+ camel component. -->
+ <!-- Uncomment the following snippet to copy items from staticContent folder
+ to ultimate $AJSC_HOME/staticConent -->
+ <!-- <copy toDir="${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/staticContent"
+ failonerror="false"> <fileset dir="${basedir}/staticContent" includes="**/**"
+ /> </copy> -->
+
+ <!-- Copying extra jar files that have been labeled as dependencies in
+ service project to /extJars folder to be made available on the classpath
+ for your service -->
+ <copy
+ toDir="${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/extJars"
+ failonerror="false">
+ <fileset dir="target" includes="*.jar" />
+ </copy>
+
+ <!-- Copying deployment packages created within the project to the $AJSC_HOME/services
+ folder to be auto deployed. -->
+ <copy
+ toDir="${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/services">
+ <fileset dir="target" includes="*.zip" excludes="*-runtimeEnvironment.zip" />
+ </copy>
+
+ <echo message="EXITING 'prep_assembly_output_for_swm_plugin' ant tasks" />
+ </target>
+</project>
diff --git a/champ-service/appconfig-local/auth/champion-service_policy.json-REPLACE b/champ-service/appconfig-local/auth/champion-service_policy.json-REPLACE
new file mode 100644
index 0000000..ee9bf44
--- /dev/null
+++ b/champ-service/appconfig-local/auth/champion-service_policy.json-REPLACE
@@ -0,0 +1 @@
+This should be replaced with an actual policy file \ No newline at end of file
diff --git a/champ-service/appconfig-local/auth/tomcat_keystore-REPLACE b/champ-service/appconfig-local/auth/tomcat_keystore-REPLACE
new file mode 100644
index 0000000..cfc37ff
--- /dev/null
+++ b/champ-service/appconfig-local/auth/tomcat_keystore-REPLACE
@@ -0,0 +1 @@
+Place keystore here \ No newline at end of file
diff --git a/champ-service/appconfig-local/champ-api.properties-REPLACE b/champ-service/appconfig-local/champ-api.properties-REPLACE
new file mode 100644
index 0000000..9ad9b33
--- /dev/null
+++ b/champ-service/appconfig-local/champ-api.properties-REPLACE
@@ -0,0 +1,7 @@
+Replace with your actual properties file. Should contain something like:
+
+keyName=aai-uuid
+sourceOfTruthName=source-of-truth
+createdTsName=aai-created-ts
+lastModTsName=aai-last-mod-ts
+collectionPropertiesKey=properties \ No newline at end of file
diff --git a/champ-service/bundleconfig-local/etc/appprops/AAFUserRoles.properties b/champ-service/bundleconfig-local/etc/appprops/AAFUserRoles.properties
new file mode 100644
index 0000000..dde7e09
--- /dev/null
+++ b/champ-service/bundleconfig-local/etc/appprops/AAFUserRoles.properties
@@ -0,0 +1,12 @@
+
+#If using AAF for Role based authentication/authorization, define your routes/services which will utilize AAF. The AJSC will
+#read this file and protect the routes given with the AAF role defined.
+
+#The following example would protect the JAXRS echo example service provided with the archetype.
+#/services/${namespace}/v1/jaxrs-services/jaxrsExample/echo/*=com.att.ajsc.myper|mymachine|manage
+
+#The following example would protect ALL AJSC services running within your project.
+#/**=com.att.ajsc.myperm|mymachine|manage
+
+#The following example would protect ALL REST services utilizing the Camel restlet routes.
+#/rest/**=com.att.ajsc.myperm|mymachine|manage
diff --git a/champ-service/bundleconfig-local/etc/appprops/PostProcessorInterceptors.properties b/champ-service/bundleconfig-local/etc/appprops/PostProcessorInterceptors.properties
new file mode 100644
index 0000000..17b5036
--- /dev/null
+++ b/champ-service/bundleconfig-local/etc/appprops/PostProcessorInterceptors.properties
@@ -0,0 +1,2 @@
+#This properties file is for defining any PostProcessorInterceptors that have been created for your AJSC service.
+
diff --git a/champ-service/bundleconfig-local/etc/appprops/PreProcessorInterceptors.properties b/champ-service/bundleconfig-local/etc/appprops/PreProcessorInterceptors.properties
new file mode 100644
index 0000000..ddaefdd
--- /dev/null
+++ b/champ-service/bundleconfig-local/etc/appprops/PreProcessorInterceptors.properties
@@ -0,0 +1,3 @@
+#This properties file is for defining any PreProcessorInterceptors that have been created for your AJSC service.
+
+/**=com.att.ajsc.csi.restmethodmap.RestMethodMapInterceptor
diff --git a/champ-service/bundleconfig-local/etc/appprops/app-intercepts.properties b/champ-service/bundleconfig-local/etc/appprops/app-intercepts.properties
new file mode 100644
index 0000000..bcf3912
--- /dev/null
+++ b/champ-service/bundleconfig-local/etc/appprops/app-intercepts.properties
@@ -0,0 +1,7 @@
+
+#This is where all your application intercept strategies must be configured. AJSC reads this property file and adds
+#the list of intercepts specified here to the camel context. This can be useful for accessing every exchange object transferred from/to
+#each endpoint in the request/response flow and can allow for more precise debugging and/or processing of the exchange.
+
+#e.g.
+#intercepts=org.openecomp.champ.JaxrsEchoService,packagename.class1name,packagename.class2name
diff --git a/champ-service/bundleconfig-local/etc/appprops/methodMapper.properties b/champ-service/bundleconfig-local/etc/appprops/methodMapper.properties
new file mode 100644
index 0000000..1cda3e5
--- /dev/null
+++ b/champ-service/bundleconfig-local/etc/appprops/methodMapper.properties
@@ -0,0 +1,45 @@
+//
+// Json object holds the method mapping.Update the JSON object with the proper route to logical mapping based
+// on the example provided below :
+// "helloWorld" = Service Name
+// "method" = http method
+// "url" = the url component from the route
+// "logicalName"= When a combination of method and url from the route matches the json object ,
+// the logical name is put in the http header as "x-CSI-ServiceName" and "x-CSI-MethodName"
+// "dme2url"= if provided it register the endpoint to GRM, it is optional. This is useful for JAX-RS services.
+
+{
+ "helloWorld": [
+ {
+ "method": "get",
+ "url": "/rest/champ-service/v1/helloWorld",
+ "logicalName": "GetMethod(Logical)"
+ },
+ {
+ "method": "get",
+ "url": "/services/champ-service/v1/jaxrsExample/jaxrs-services/echo/{input}",
+ "logicalName": "GetJaxrsExampleEcho(Logical)",
+ "dme2url": "/services/champ-service/v1/jaxrsExample/jaxrs-services/echo/{input}"
+ },
+ {
+ "method": "get",
+ "url": "/services/champ-service/v1/jaxrsExample/jaxrs-services/property/{fileName}/{input}",
+ "logicalName": "GetJaxrsExampleProperty(Logical)",
+ "dme2url": "/services/champ-service/v1/jaxrsExample/jaxrs-services/property/{fileName}/{input}"
+ }
+ ],
+ "errormessage":
+ [
+ {
+ "method": "get",
+ "url": "/services/champ-service/v1/jaxrsExample/errormessage/emls",
+ "logicalName": "setCAETHeaders(Logical)"
+ },
+ {
+ "method": "get",
+ "url": "/services/champ-service/v1/errorMessageLookupService2",
+ "logicalName": "setCAETHeaders(Logical)"
+ }
+
+ ]
+} \ No newline at end of file
diff --git a/champ-service/bundleconfig-local/etc/sysprops/sys-props.properties b/champ-service/bundleconfig-local/etc/sysprops/sys-props.properties
new file mode 100644
index 0000000..26cd13d
--- /dev/null
+++ b/champ-service/bundleconfig-local/etc/sysprops/sys-props.properties
@@ -0,0 +1,117 @@
+#This file is used for defining AJSC system properties for different configuration schemes and is necessary for the AJSC to run properly.
+#The sys-props.properties file is used for running locally. The template.sys-props.properties file will be used when deployed
+#to a SOA/CSI Cloud node.
+
+#AJSC System Properties. The following properties are required for ALL AJSC services. If you are adding System Properties for your
+#particular service, please add them AFTER all AJSC related System Properties.
+
+#For Cadi Authorization, use value="authentication-scheme-1
+CadiAuthN=authentication-scheme-1
+
+#For Basic Authorization, use value="authentication-scheme-1
+authN=authentication-scheme-2
+
+#Persistence used for AJSC meta-data storage. For most environments, "file" should be used.
+ajscPersistence=file
+
+#For Direct Invocation to be enabled (values=true/false)
+directInvocationEnable=false
+
+# If using hawtio for local development, these properties will allow for faster server startup and usage for local development
+
+hawtio.authenticationEnabled=false
+hawtio.config.pullOnStartup=false
+
+#Removes the extraneous restlet console output
+org.restlet.engine.loggerFacadeClass=org.restlet.ext.slf4j.Slf4jLoggerFacade
+
+#server.host property to be enabled for local DME2 related testing
+#server.host=<Your network IP address>
+
+#Enable/disable SSL (values=true/false). This property also determines which protocol to use (https if true, http otherwise), to register services into GRM through DME2.
+enableSSL=false
+
+
+#Enable/disable EJB Container
+ENABLE_EJB=false
+
+#Enable/disable OSGI
+isOSGIEnable=false
+
+#Generate/Skip api docs
+isApiDoc=false
+
+#CSI related variables for CSM framework
+csm.hostname=servername
+
+
+#SOA_CLOUD_ENV is used to register your service with dme2 and can be turned off for local development (values=true/false).
+SOA_CLOUD_ENV=false
+
+#CONTINUE_ON_LISTENER_EXCEPTION will exit the application if there is a DME2 exception at the time of registration.
+CONTINUE_ON_LISTENER_EXCEPTION=false
+
+#Jetty Container ThreadCount Configuration Variables
+AJSC_JETTY_ThreadCount_MIN=1
+AJSC_JETTY_ThreadCount_MAX=200
+AJSC_JETTY_IDLETIME_MAX=3000
+
+#Camel Context level default threadPool Profile configuration
+CAMEL_POOL_SIZE=10
+CAMEL_MAX_POOL_SIZE=20
+CAMEL_KEEP_ALIVE_TIME=60
+CAMEL_MAX_QUEUE_SIZE=1000
+
+#GRM/DME2 System Properties
+AFT_DME2_CONN_IDLE_TIMEOUTMS=5000
+AJSC_ENV=SOACLOUD
+
+SOACLOUD_NAMESPACE=com.att.ajsc
+SOACLOUD_ENV_CONTEXT=DEV
+SOACLOUD_PROTOCOL=http
+SOACLOUD_ROUTE_OFFER=DEFAULT
+
+AFT_LATITUDE=23.4
+AFT_LONGITUDE=33.6
+AFT_ENVIRONMENT=AFTUAT
+
+#Restlet Component Default Properties
+RESTLET_COMPONENT_CONTROLLER_DAEMON=true
+RESTLET_COMPONENT_CONTROLLER_SLEEP_TIME_MS=100
+RESTLET_COMPONENT_INBOUND_BUFFER_SIZE=8192
+RESTLET_COMPONENT_MIN_THREADS=1
+RESTLET_COMPONENT_MAX_THREADS=10
+RESTLET_COMPONENT_LOW_THREADS=8
+RESTLET_COMPONENT_MAX_QUEUED=0
+RESTLET_COMPONENT_MAX_CONNECTIONS_PER_HOST=-1
+RESTLET_COMPONENT_MAX_TOTAL_CONNECTIONS=-1
+RESTLET_COMPONENT_OUTBOUND_BUFFER_SIZE=8192
+RESTLET_COMPONENT_PERSISTING_CONNECTIONS=true
+RESTLET_COMPONENT_PIPELINING_CONNECTIONS=false
+RESTLET_COMPONENT_THREAD_MAX_IDLE_TIME_MS=60000
+RESTLET_COMPONENT_USE_FORWARDED_HEADER=false
+RESTLET_COMPONENT_REUSE_ADDRESS=true
+
+#Externalized jar and properties file location. In CSI environments, there are a few libs that have been externalized to aid
+#in CSTEM maintenance of the versions of these libs. The most important to the AJSC is the DME2 lib. Not only is this lib necessary
+#for proper registration of your AJSC service on a node, but it is also necessary for running locally as well. Another framework
+#used in CSI envs is the CSM framework. These 2 framework libs are shown as "provided" dependencies within the pom.xml. These
+#dependencies will be copied into the target/commonLibs folder with the normal "mvn clean package" goal of the AJSC. They will
+#then be added to the classpath via AJSC_EXTERNAL_LIB_FOLDERS system property. Any files (mainly property files) that need
+#to be on the classpath should be added to the AJSC_EXTERNAL_PROPERTIES_FOLDERS system property. The default scenario when
+#testing your AJSC service locally will utilize the target/commonLibs directory for DME2 and CSM related artifacts and 2
+#default csm properties files will be used for local testing with anything CSM knorelated.
+#NOTE: we are using maven-replacer-plugin to replace "(doubleUnderscore)basedir(doubleUnderscore)" with ${basedir} within the
+#target directory for running locally. Multiple folder locations can be separated by the pipe ("|") character.
+#Please, NOTE: for running locally, we are setting this system property in the antBuild/build.xml "runLocal" target and in the
+#"runAjsc" profile within the pom.xml. This is to most effectively use maven variables (${basedir}, most specifically. Therefore,
+#when running locally, the following 2 properties should be set within the profile(s) themselves.
+#Example: target/commonLibs|target/otherLibs
+#AJSC_EXTERNAL_LIB_FOLDERS=__basedir__/target/commonLibs
+#AJSC_EXTERNAL_PROPERTIES_FOLDERS=__basedir__/ajsc-shared-config/etc
+#End of AJSC System Properties
+
+#Service System Properties. Please, place any Service related System Properties below.
+
+KEY_STORE_PASSWORD=OBF:1y0q1uvc1uum1uvg1pil1pjl1uuq1uvk1uuu1y10
+KEY_MANAGER_PASSWORD=OBF:1y0q1uvc1uum1uvg1pil1pjl1uuq1uvk1uuu1y10
diff --git a/champ-service/pom.xml b/champ-service/pom.xml
new file mode 100644
index 0000000..9edf59d
--- /dev/null
+++ b/champ-service/pom.xml
@@ -0,0 +1,360 @@
+<?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/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>com.att.ajsc</groupId>
+ <artifactId>ajsc-archetype-parent</artifactId>
+ <version>2.0.0</version>
+ </parent>
+
+ <groupId>org.onap.aai</groupId>
+ <artifactId>champ-service</artifactId>
+ <version>1.2.0-SNAPSHOT</version>
+
+ <properties>
+ <runAjscHome>${basedir}/target/swm/package/nix/dist_files${distFilesRoot}</runAjscHome>
+ <ajscRuntimeVersion>2.0.0</ajscRuntimeVersion>
+
+ <absoluteDistFilesRoot>/appl/${project.artifactId}</absoluteDistFilesRoot>
+
+ <!-- For NO Versioning, REMOVE the /${project.version} from the <distFilesRoot>
+ property, below. PLEASE, NOTE: If your ${project.version} is a "-SNAPSHOT"
+ version, THIS will be used as your directory structure. If you do NOT want
+ this, simply remove the "-SNAPSHOT" from your <version> declaration at the
+ top of pom.xml -->
+ <distFilesRoot>/appl/${project.artifactId}/${project.version}</distFilesRoot>
+
+ <event.client.version>1.2.0</event.client.version>
+ <common.logging.groupid>org.onap.aai.logging-service</common.logging.groupid>
+ <common.logging.version>1.2.0</common.logging.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-core</artifactId>
+ <version>1.18.6</version>
+ </dependency>
+
+ <!-- AJSC Dependencies -->
+ <dependency>
+ <groupId>dom4j</groupId>
+ <artifactId>dom4j</artifactId>
+ <version>1.6.1</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.att.aft</groupId>
+ <artifactId>dme2</artifactId>
+ <version>3.1.200</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <!--Adding this dependency explicit.-->
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ <version>20160212</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>2.23</version>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.4</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>2.6.2</version>
+ </dependency>
+
+ <dependency>
+ <groupId>${common.logging.groupid}</groupId>
+ <artifactId>common-logging</artifactId>
+ <version>${common.logging.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ <version>1.1.7</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse.persistence</groupId>
+ <artifactId>eclipselink</artifactId>
+ <version>2.6.2</version>
+ </dependency>
+
+ <!-- Event Bus Library. -->
+ <dependency>
+ <groupId>org.onap.aai.event-client</groupId>
+ <artifactId>event-client-api</artifactId>
+ <version>${event.client.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.aai.event-client</groupId>
+ <artifactId>event-client-dmaap</artifactId>
+ <version>${event.client.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.aai.event-client</groupId>
+ <artifactId>event-client-kafka</artifactId>
+ <version>${event.client.version}</version>
+ </dependency>
+
+ <!-- Champ graph database library. -->
+ <dependency>
+ <groupId>org.onap.aai</groupId>
+ <artifactId>champ-core</artifactId>
+ <version>1.2.0-SNAPSHOT</version>
+ <scope>compile</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.hbase</groupId>
+ <artifactId>hbase-client</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.onap.aai.event-client</groupId>
+ <artifactId>event-client-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.onap.aai.event-client</groupId>
+ <artifactId>event-client-dmaap</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.onap.aai.event-client</groupId>
+ <artifactId>event-client-kafka</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.7</version>
+ <executions>
+ <execution>
+ <id>copy-docker-file</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>target</outputDirectory>
+ <overwrite>true</overwrite>
+ <resources>
+ <resource>
+ <directory>${basedir}/src/main/docker</directory>
+ <filtering>true</filtering>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>${basedir}/src/main/bin/</directory>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <version>0.7.9</version>
+ <executions>
+ <execution>
+ <id>default-prepare-agent</id>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>default-report</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>report</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>default-check</id>
+ <goals>
+ <goal>check</goal>
+ </goals>
+ <configuration>
+ <rules>
+ <!-- implementation is needed only for Maven 2 -->
+ <rule implementation="org.jacoco.maven.RuleConfiguration">
+ <element>BUNDLE</element>
+ <limits>
+ <!-- implementation is needed only for Maven 2 -->
+ <limit implementation="org.jacoco.report.check.Limit">
+ <counter>INSTRUCTION</counter>
+ <value>COVEREDRATIO</value>
+ <minimum>.15</minimum>
+ </limit>
+ <limit implementation="org.jacoco.report.check.Limit">
+ <counter>BRANCH</counter>
+ <value>COVEREDRATIO</value>
+ <minimum>.12</minimum>
+ </limit>
+ <limit implementation="org.jacoco.report.check.Limit">
+ <counter>COMPLEXITY</counter>
+ <value>COVEREDRATIO</value>
+ <minimum>.15</minimum>
+ </limit>
+ <limit implementation="org.jacoco.report.check.Limit">
+ <counter>LINE</counter>
+ <value>COVEREDRATIO</value>
+ <minimum>.10</minimum>
+ </limit>
+ <limit implementation="org.jacoco.report.check.Limit">
+ <counter>METHOD</counter>
+ <value>COVEREDRATIO</value>
+ <minimum>.17</minimum>
+ </limit>
+ <limit implementation="org.jacoco.report.check.Limit">
+ <counter>CLASS</counter>
+ <value>MISSEDCOUNT</value>
+ <maximum>5</maximum>
+ </limit>
+ </limits>
+ </rule>
+ </rules>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>runAjsc</id>
+ <build>
+ <defaultGoal>initialize</defaultGoal>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.3.2</version>
+ <executions>
+ <execution>
+ <phase>initialize</phase>
+ <goals>
+ <goal>java</goal>
+ </goals>
+ <configuration>
+ <includeProjectDependencies>false</includeProjectDependencies>
+ <includePluginDependencies>true</includePluginDependencies>
+ <executable>java</executable>
+ <mainClass>com.att.ajsc.runner.Runner</mainClass>
+ <executableDependency>
+ <groupId>com.att.ajsc</groupId>
+ <artifactId>ajsc-runner</artifactId>
+ </executableDependency>
+ <additionalClasspathElements>
+ <additionalClasspathElement>${basedir}/ajsc-shared-config/etc</additionalClasspathElement>
+ </additionalClasspathElements>
+
+ <environmentVariables>
+ <AJSC_HOME>${runAjscHome}</AJSC_HOME>
+ </environmentVariables>
+
+ <!-- Main AJSC System Properties below (necessary for proper startup) -->
+ <systemProperties>
+ <systemProperty>
+ <key>AJSC_HOME</key>
+ <value>${runAjscHome}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>CONFIG_HOME</key>
+ <value>${basedir}/appconfig-local/</value>
+ </systemProperty>
+ <systemProperty>
+ <key>AJSC_CONF_HOME</key>
+ <value>${basedir}/bundleconfig-local</value>
+ </systemProperty>
+ <systemProperty>
+ <key>logback.configurationFile</key>
+ <value>${basedir}/ajsc-shared-config/etc/logback.xml</value>
+ </systemProperty>
+ <systemProperty>
+ <key>AJSC_SHARED_CONFIG</key>
+ <value>${basedir}/ajsc-shared-config</value>
+ </systemProperty>
+
+ <sysproperty>
+ <key>AJSC_EXTERNAL_LIB_FOLDERS</key>
+ <value>${basedir}/target/commonLibs</value>
+ </sysproperty>
+ <sysproperty>
+ <key>AJSC_EXTERNAL_PROPERTIES_FOLDERS</key>
+ <value>${basedir}/ajsc-shared-config/etc</value>
+ </sysproperty>
+
+ <systemProperty>
+ <key>AJSC_SERVICE_NAMESPACE</key>
+ <value>${module.ajsc.namespace.name}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>AJSC_SERVICE_VERSION</key>
+ <value>${module.ajsc.namespace.version}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>SOACLOUD_SERVICE_VERSION</key>
+ <value>${project.version}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>server.port</key>
+ <value>${serverPort}</value>
+ </systemProperty>
+ </systemProperties>
+
+ <!-- Command Line Arguments to add to the java command. Here, you
+ can specify the port as well as the Context you want your service to run
+ in. Use context=/ to run in an unnamed Context (Root Context). The default
+ configuration of the AJSC is to run under the / Context. Setting the port
+ here can aid during the development phase of your service. However, you can
+ leave this argument out entirely, and the AJSC will default to using an Ephemeral
+ port. -->
+ <arguments>
+ <argument>context=/</argument>
+ <argument>port=${serverPort}</argument>
+ <argument>sslport=${sslport}</argument>
+ </arguments>
+ </configuration>
+ </execution>
+ </executions>
+ <configuration>
+ <executable>java</executable>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>com.att.ajsc</groupId>
+ <artifactId>ajsc-runner</artifactId>
+ <version>${ajscRuntimeVersion}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
diff --git a/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/conf/jaxrsBeans.groovy b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/conf/jaxrsBeans.groovy
new file mode 100644
index 0000000..17d80a4
--- /dev/null
+++ b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/conf/jaxrsBeans.groovy
@@ -0,0 +1,11 @@
+beans{
+ xmlns cxf: "http://camel.apache.org/schema/cxf"
+ xmlns jaxrs: "http://cxf.apache.org/jaxrs"
+ xmlns util: "http://www.springframework.org/schema/util"
+
+ echoService(org.onap.champ.service.EchoService)
+
+ util.list(id: 'echoServices') {
+ ref(bean:'echoService')
+ }
+} \ No newline at end of file
diff --git a/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/docs/README.txt b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/docs/README.txt
new file mode 100644
index 0000000..3707179
--- /dev/null
+++ b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/docs/README.txt
@@ -0,0 +1 @@
+Place any docs here that you want to access within the ajsc upon deployment of your service.
diff --git a/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/lib/README.txt b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/lib/README.txt
new file mode 100644
index 0000000..639e21b
--- /dev/null
+++ b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/lib/README.txt
@@ -0,0 +1 @@
+3rd party JAR's needed by your jars (if any) for a ajsc deployment package go here... \ No newline at end of file
diff --git a/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/champ.route b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/champ.route
new file mode 100644
index 0000000..cf8d115
--- /dev/null
+++ b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/champ.route
@@ -0,0 +1,4 @@
+<route xmlns="http://camel.apache.org/schema/spring" trace="true">
+ <from uri="att-dme2-servlet:///champ-service/v1/?matchOnUriPrefix=true" />
+ <to uri="cxfbean:champRestService" />
+</route> \ No newline at end of file
diff --git a/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/jaxrsExample.route b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/jaxrsExample.route
new file mode 100644
index 0000000..a132030
--- /dev/null
+++ b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/jaxrsExample.route
@@ -0,0 +1,5 @@
+<route xmlns="http://camel.apache.org/schema/spring" trace="true">
+ <from uri="att-dme2-servlet:///echo-service/?matchOnUriPrefix=true" />
+ <to uri="cxfbean:echoServices" />
+</route>
+
diff --git a/champ-service/src/main/assemble/ajsc_module_assembly.xml b/champ-service/src/main/assemble/ajsc_module_assembly.xml
new file mode 100644
index 0000000..4ec4e28
--- /dev/null
+++ b/champ-service/src/main/assemble/ajsc_module_assembly.xml
@@ -0,0 +1,66 @@
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+ <id>${version}</id>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <fileSets>
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-ajsc/routes/</directory>
+ <outputDirectory>${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/routes/</outputDirectory>
+ <includes>
+ <include>*.route</include>
+ </includes>
+
+ </fileSet>
+
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-ajsc/docs/</directory>
+ <outputDirectory>${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/docs/</outputDirectory>
+ <includes>
+ <include>*.*</include>
+ <!-- <include>*.vm</include> -->
+ </includes>
+
+ </fileSet>
+
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-ajsc/lib/</directory>
+ <outputDirectory>${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/lib/</outputDirectory>
+ <includes>
+ <include>*.jar</include>
+ </includes>
+
+ </fileSet>
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-ajsc/extJars/</directory>
+ <outputDirectory>${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/extJars/</outputDirectory>
+ <includes>
+ <include>*.jar</include>
+ </includes>
+ </fileSet>
+
+ <!-- also try to grab outputs from the "jar" plugin's package phase -->
+ <fileSet>
+ <directory>${project.basedir}/target/</directory>
+ <outputDirectory>${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/lib/</outputDirectory>
+ <includes>
+ <include>*.jar</include>
+ </includes>
+ </fileSet>
+
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-ajsc/conf/</directory>
+ <outputDirectory>${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/conf/</outputDirectory>
+ <includes>
+ <include>*.*</include>
+ </includes>
+
+ </fileSet>
+ </fileSets>
+
+</assembly>
+
diff --git a/champ-service/src/main/assemble/ajsc_props_assembly.xml b/champ-service/src/main/assemble/ajsc_props_assembly.xml
new file mode 100644
index 0000000..5b8a6fa
--- /dev/null
+++ b/champ-service/src/main/assemble/ajsc_props_assembly.xml
@@ -0,0 +1,23 @@
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+ <id>${version}_properties</id>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <fileSets>
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-ajsc/props</directory>
+ <outputDirectory>${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/props/</outputDirectory>
+ <includes>
+ <include>*.props</include>
+ </includes>
+
+ </fileSet>
+
+ </fileSets>
+
+</assembly>
+
diff --git a/champ-service/src/main/assemble/ajsc_runtime_assembly.xml b/champ-service/src/main/assemble/ajsc_runtime_assembly.xml
new file mode 100644
index 0000000..e37d366
--- /dev/null
+++ b/champ-service/src/main/assemble/ajsc_runtime_assembly.xml
@@ -0,0 +1,44 @@
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+ <id>runtimeEnvironment</id>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <fileSets>
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-runtime/context/</directory>
+ <outputDirectory>runtime/context/</outputDirectory>
+ <includes>
+ <include>*.context</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-runtime/serviceProperties/</directory>
+ <outputDirectory>runtime/serviceProperties/</outputDirectory>
+ <includes>
+ <include>*.props</include>
+ </includes>
+ </fileSet><fileSet>
+ <directory>${project.basedir}/target/versioned-runtime/shiroRole</directory>
+ <outputDirectory>runtime/shiroRole/</outputDirectory>
+ <includes>
+ <include>*.json</include>
+ </includes>
+ </fileSet><fileSet>
+ <directory>${project.basedir}/target/versioned-runtime/shiroUser</directory>
+ <outputDirectory>runtime/shiroUser/</outputDirectory>
+ <includes>
+ <include>*.json</include>
+ </includes>
+ </fileSet><fileSet>
+ <directory>${project.basedir}/target/versioned-runtime/shiroUserRole</directory>
+ <outputDirectory>runtime/shiroUserRole</outputDirectory>
+ <includes>
+ <include>*.json</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+</assembly> \ No newline at end of file
diff --git a/champ-service/src/main/bin/start.sh b/champ-service/src/main/bin/start.sh
new file mode 100644
index 0000000..de8a4fb
--- /dev/null
+++ b/champ-service/src/main/bin/start.sh
@@ -0,0 +1,94 @@
+#!/bin/sh
+#
+# ============LICENSE_START==========================================
+# org.onap.aai
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2017 Amdocs
+# ===================================================================
+# 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.
+# ============LICENSE_END============================================
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
+
+BASEDIR="/opt/app/champ-service/"
+AJSC_HOME="$BASEDIR"
+AJSC_CONF_HOME="$AJSC_HOME/bundleconfig/"
+
+if [ -z "$CONFIG_HOME" ]; then
+ echo "CONFIG_HOME must be set in order to start up process"
+ exit 1
+fi
+
+if [ -z "$KEY_STORE_PASSWORD" ]; then
+ echo "KEY_STORE_PASSWORD must be set in order to start up process"
+ exit 1
+else
+ echo "KEY_STORE_PASSWORD=$KEY_STORE_PASSWORD\n" >> $AJSC_CONF_HOME/etc/sysprops/sys-props.properties
+fi
+
+if [ -z "$KEY_MANAGER_PASSWORD" ]; then
+ echo "KEY_MANAGER_PASSWORD must be set in order to start up process"
+ exit 1
+else
+ echo "KEY_MANAGER_PASSWORD=$KEY_MANAGER_PASSWORD\n" >> $AJSC_CONF_HOME/etc/sysprops/sys-props.properties
+fi
+
+# Add any spring bean configuration files to the Gizmo deployment
+if [ -n "$SERVICE_BEANS" ]; then
+ echo "Adding the following dynamic service beans to the deployment: "
+ mkdir -p /tmp/champ-service/v1/conf
+ for f in `ls $SERVICE_BEANS`
+ do
+ cp $SERVICE_BEANS/$f /tmp/champ-service/v1/conf
+ echo "Adding dynamic service bean $SERVICE_BEANS/$f"
+ done
+ jar uf /opt/app/champ-service/services/champ-service_v1.zip* -C /tmp/ champ-service
+ rm -rf /tmp/champ-service
+fi
+
+CLASSPATH="$AJSC_HOME/lib/*"
+CLASSPATH="$CLASSPATH:$AJSC_HOME/extJars/"
+CLASSPATH="$CLASSPATH:$AJSC_HOME/etc/"
+
+# Check to see if the provided implementation exists in the image and add it to the classpath
+for file in $( find ${BASEDIR}graph-deps/* -maxdepth 0 -type d ); do
+ CURRIMPL=$(echo $file | cut -d"/" -f6)
+ if [ "x$GRAPHIMPL" = "x$CURRIMPL" ]; then
+ CLASSPATH_GRAPHIMPL=$file
+ echo "Setting up graph implementation of $GRAPHIMPL"
+ else
+ SUPPORTED_GRAPHIMPL="$SUPPORTED_GRAPHIMPL $CURRIMPL"
+ fi
+done
+if [ -n "$CLASSPATH_GRAPHIMPL" ]; then
+ cp $CLASSPATH_GRAPHIMPL/* $AJSC_HOME/extJars/
+else
+ echo "Configured graph implementation '$GRAPHIMPL' is not supported. Acceptable implementations are one of: $SUPPORTED_GRAPHIMPL"
+ exit 1
+fi
+
+PROPS="-DAJSC_HOME=$AJSC_HOME"
+PROPS="$PROPS -DAJSC_CONF_HOME=$BASEDIR/bundleconfig/"
+PROPS="$PROPS -Dlogback.configurationFile=$BASEDIR/bundleconfig/etc/logback.xml"
+PROPS="$PROPS -DAJSC_SHARED_CONFIG=$AJSC_CONF_HOME"
+PROPS="$PROPS -DAJSC_SERVICE_NAMESPACE=champ-service"
+PROPS="$PROPS -DAJSC_SERVICE_VERSION=v1"
+PROPS="$PROPS -Dserver.port=9522"
+PROPS="$PROPS -DCONFIG_HOME=$CONFIG_HOME"
+JVM_MAX_HEAP=${MAX_HEAP:-1024}
+
+echo $CLASSPATH
+
+exec java -Xmx${JVM_MAX_HEAP}m $PROPS -classpath $CLASSPATH com.att.ajsc.runner.Runner context=// sslport=9522
diff --git a/champ-service/src/main/config/ajsc-chef.jks b/champ-service/src/main/config/ajsc-chef.jks
new file mode 100644
index 0000000..aeca770
--- /dev/null
+++ b/champ-service/src/main/config/ajsc-chef.jks
Binary files differ
diff --git a/champ-service/src/main/config/ajsc-jetty.xml b/champ-service/src/main/config/ajsc-jetty.xml
new file mode 100644
index 0000000..98cc02e
--- /dev/null
+++ b/champ-service/src/main/config/ajsc-jetty.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<!-- Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. -->
+<Configure id="ajsc-server" class="org.eclipse.jetty.server.Server">
+ <!-- DO NOT REMOVE!!!! This is setting up the AJSC Context -->
+ <New id="ajscContext" class="org.eclipse.jetty.webapp.WebAppContext">
+ <Set name="contextPath"><SystemProperty name="AJSC_CONTEXT_PATH" /></Set>
+ <Set name="extractWAR">true</Set>
+ <Set name="tempDirectory"><SystemProperty name="AJSC_TEMP_DIR" /></Set>
+ <Set name="war"><SystemProperty name="AJSC_WAR_PATH" /></Set>
+ <Set name="descriptor"><SystemProperty name="AJSC_HOME" />/etc/runner-web.xml</Set>
+ <Set name="overrideDescriptor"><SystemProperty name="AJSC_HOME" />/etc/ajsc-override-web.xml</Set>
+ <Set name="throwUnavailableOnStartupException">true</Set>
+ <Set name="servletHandler">
+ <New class="org.eclipse.jetty.servlet.ServletHandler">
+ <Set name="startWithUnavailable">false</Set>
+ </New>
+ </Set>
+ <Set name="extraClasspath"><SystemProperty name="AJSC_HOME" />/extJars/champ-service.jar,<SystemProperty name="AJSC_HOME" />/extJars/json-20160212.jar,<SystemProperty name="AJSC_HOME" />/extJars/javax.ws.rs-api-2.0.1.jar,<SystemProperty name="AJSC_HOME" />/extJars/jersey-client-2.23.jar</Set>
+ </New>
+
+ <Set name="handler">
+ <New id="Contexts"
+ class="org.eclipse.jetty.server.handler.ContextHandlerCollection">
+ <Set name="Handlers">
+ <Array type="org.eclipse.jetty.webapp.WebAppContext">
+ <Item>
+ <Ref refid="ajscContext" />
+ </Item>
+ </Array>
+ </Set>
+ </New>
+ </Set>
+
+ <Call name="addBean">
+ <Arg>
+ <New id="DeploymentManager" class="org.eclipse.jetty.deploy.DeploymentManager">
+ <Set name="contexts">
+ <Ref refid="Contexts" />
+ </Set>
+ <Call id="extAppHotDeployProvider" name="addAppProvider">
+ <Arg>
+ <New class="org.eclipse.jetty.deploy.providers.WebAppProvider">
+ <Set name="monitoredDirName"><SystemProperty name="AJSC_HOME" />/extApps</Set>
+ <Set name="scanInterval">10</Set>
+ <Set name="extractWars">true</Set>
+ </New>
+ </Arg>
+ </Call>
+ </New>
+ </Arg>
+ </Call>
+
+ <New id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
+ <Set name="keyStorePath">file:<SystemProperty name="CONFIG_HOME" />/auth/tomcat_keystore</Set>
+ <Set name="KeyStorePassword">
+ <Call class="org.eclipse.jetty.util.security.Password" name="deobfuscate">
+ <Arg><SystemProperty name="KEY_STORE_PASSWORD" /></Arg>
+ </Call>
+ </Set>
+ <Set name="KeyManagerPassword">
+ <Call class="org.eclipse.jetty.util.security.Password" name="deobfuscate">
+ <Arg><SystemProperty name="KEY_MANAGER_PASSWORD" /></Arg>
+ </Call>
+ </Set>
+ <Set name="needClientAuth">true</Set>
+ <Set name="wantClientAuth">true</Set>
+ </New>
+
+ <Call id="sslConnector" name="addConnector">
+ <Arg>
+ <New class="org.eclipse.jetty.server.ServerConnector">
+ <Arg name="server">
+ <Ref refid="ajsc-server" />
+ </Arg>
+ <Arg name="factories">
+ <Array type="org.eclipse.jetty.server.ConnectionFactory">
+ <Item>
+ <New class="org.eclipse.jetty.server.SslConnectionFactory">
+ <Arg name="next">http/1.1</Arg>
+ <Arg name="sslContextFactory">
+ <Ref refid="sslContextFactory" />
+ </Arg>
+ </New>
+ </Item>
+ <Item>
+ <New class="org.eclipse.jetty.server.HttpConnectionFactory">
+ <Arg name="config">
+ <New class="org.eclipse.jetty.server.HttpConfiguration">
+ <Call name="addCustomizer">
+ <Arg>
+ <New class="org.eclipse.jetty.server.SecureRequestCustomizer" />
+ </Arg>
+ </Call>
+ </New>
+ </Arg>
+ </New>
+ </Item>
+ </Array>
+ </Arg>
+ <Set name="port"><SystemProperty name="AJSC_HTTPS_PORT" default="9522" /></Set>
+ <Set name="idleTimeout">30000</Set>
+ </New>
+ </Arg>
+ </Call>
+
+ <Get name="ThreadPool">
+ <Set name="minThreads"><SystemProperty name="AJSC_JETTY_ThreadCount_MIN" /></Set>
+ <Set name="maxThreads"><SystemProperty name="AJSC_JETTY_ThreadCount_MAX" /></Set>
+ <Set name="idleTimeout"><SystemProperty name="AJSC_JETTY_IDLETIME_MAX" /></Set>
+ <Set name="detailedDump">false</Set>
+ </Get>
+
+</Configure>
diff --git a/champ-service/src/main/config/ajsc-override-web.xml b/champ-service/src/main/config/ajsc-override-web.xml
new file mode 100644
index 0000000..8e02d6d
--- /dev/null
+++ b/champ-service/src/main/config/ajsc-override-web.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ metadata-complete="false" version="3.0">
+
+ <filter-mapping>
+ <filter-name>InterceptorFilter</filter-name>
+ <url-pattern>/services/*</url-pattern>
+ </filter-mapping>
+ <filter-mapping>
+ <filter-name>InterceptorFilter</filter-name>
+ <url-pattern>/rest/*</url-pattern>
+ </filter-mapping>
+
+ <filter-mapping>
+ <filter-name>springSecurityFilterChain</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <servlet-mapping>
+ <servlet-name>ManagementServlet</servlet-name>
+ <url-pattern>/mgmt</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>RestletServlet</servlet-name>
+ <url-pattern>/rest/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>CamelServlet</servlet-name>
+ <url-pattern>/services/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>jsp</servlet-name>
+ <url-pattern>*.jsp</url-pattern>
+ <url-pattern>*.jspf</url-pattern>
+ <url-pattern>*.jspx</url-pattern>
+ <url-pattern>*.xsp</url-pattern>
+ <url-pattern>*.JSP</url-pattern>
+ <url-pattern>*.JSPF</url-pattern>
+ <url-pattern>*.JSPX</url-pattern>
+ <url-pattern>*.XSP</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>default</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app> \ No newline at end of file
diff --git a/champ-service/src/main/config/ajscJetty.jks b/champ-service/src/main/config/ajscJetty.jks
new file mode 100644
index 0000000..48cdbff
--- /dev/null
+++ b/champ-service/src/main/config/ajscJetty.jks
Binary files differ
diff --git a/champ-service/src/main/config/cadi.properties b/champ-service/src/main/config/cadi.properties
new file mode 100644
index 0000000..cc527ed
--- /dev/null
+++ b/champ-service/src/main/config/cadi.properties
@@ -0,0 +1,28 @@
+#This properties file is used for defining AAF properties related to the CADI framework. This file is used for running AAF framework
+hostname=mywebserver.att.com
+
+#Setting csp_domain to PROD will allow for testing using your attuid and password through GLO.
+csp_domain=PROD
+csp_devl_localhost=true
+
+basic_realm=csp.att.com
+#basic_realm=aaf.att.com
+basic_warn=TRUE
+
+cadi_loglevel=WARN
+cadi_keyfile=target/swm/package/nix/dist_files/appl/champ-service/etc/keyfile
+
+# Configure AAF
+#These are dummy values add appropriate values required
+aaf_url=url
+
+#AJSC - MECHID
+#These are dummy values add appropriate values required
+aaf_id=dummyid@ajsc.att.com
+aaf_password=enc:277edqJCjT0RlUI3BtbDQa-3Ha-CQGd
+aaf_timeout=5000
+aaf_clean_interval=30000
+aaf_user_expires=5000
+aaf_high_count=1000
+
+
diff --git a/champ-service/src/main/config/jul-redirect.properties b/champ-service/src/main/config/jul-redirect.properties
new file mode 100644
index 0000000..8b6624d
--- /dev/null
+++ b/champ-service/src/main/config/jul-redirect.properties
@@ -0,0 +1,13 @@
+
+# Bridge JUL->slf4j Logging Configuration File
+#
+# This file bridges the JUL logging infrastructure into
+# SLF4J so JUL logs go to logback implementation provided
+# in this project. SLF4J also captures log4j and has
+# other framework options as well providing a common
+# logging infrastructure for capturing all logs from different
+# libraries using different frameworks in one place.
+
+# Global properties
+handlers=org.slf4j.bridge.SLF4JBridgeHandler
+.level= ALL
diff --git a/champ-service/src/main/config/keyfile b/champ-service/src/main/config/keyfile
new file mode 100644
index 0000000..882e86a
--- /dev/null
+++ b/champ-service/src/main/config/keyfile
@@ -0,0 +1,27 @@
+ZuIwp0TkyVPDeX1Up-8JtkMWvjsCpoiu1_VKeWrtrvxunvAke8_tiFyHPPyb2nkhepFYj6tXzpfS
+rGz5XF_TH9NbsKaP8u0HV5clz2WriYQRvHS85vjY7hXxkpFuLb7zkLAPqTyIDpj7FiW61NzsRUAq
+TM8jH16jr7mBNnb56w24mNGOwznMPcIZKcjgZU1ekaPDFpWyhQElU7Y0q_94P_Gkk45r66Hj22sU
+OiOaaftmudZlswLw8-8Zaakqf2yW9HjMVfuYCwSodBHCW5rdB3Ctb5W36rnD_AQco3Ky2PgPmqvk
+QkJYuUHpbuDqVHqLOajlKSIGMTIqAIBg51fRaaONtD-Q5xzY8E5wO1YWTLKcP5tsNvUpzM8Wu3NS
+ynpGpUcvlTqWWsGzTbzOyamyKkdNdx97sSqjM25Zh1-ps48h6cddGYWpab7SUvqRCS11QBUyLTry
+2iwTEHMhHRIbo7PO99ALQfuq9gI1zKGfurJdvLBeBaFs5SCF0AiCZ3WcDO8Rv3HpxVZ2_ShbDxb0
+eMoO6SotXu51fj8Y3-WqsfZziQyEsHyqpg5uQ6yUtz01h5YHLEoVuotF1U4agmQR6kEkYk-wNOiZ
+v-8gaA9gtbLoAdKhuKFxQgQLNMf6GzVzZNujbmDzLoZAP_mXAv29aBPaf64Ugzv-Oa5GZdBgD-Xd
+_pahML-ionw99r0TnkpShYmDqMKhMdjaP3m87WIAZkIB-L-VTyKcEsJ4340VSzCOsv3waiM0S89u
+4cMcG5y-PLY8IoipIlLUPTWD3SjcQ9DV1Dt3T5KjdWLsj48D3W4K4e9PB8yxs0gtUjgVUR2_xEir
+G5eDO9Ac1eHFWGDFFP0SgG-TbHJUKlvy9mwLzmU0fC3xPjhqmIr-v0HxF7HN-tmb1LHDorno8tSN
+u7kUGcKSchIiFfvkd066crUb2mH7PnXTaWmAjyVj9VsBExFUYEdpHMAV4sAP9-RxZGDRt46UhrDK
+QZvvNhBVyOEjHPHWI4vl1r1v8HNH1_2jZu5DVJWyHWR56aCo1lhFH9_X6UAHUHbnXViDONZOVXlT
+9-WD0tk2zJGuwrhdZDAnPnAmjfwbwbpnr5Hmex1i1JiD7WVyP1kbfoej2TmdiYbxr9oBYaGQ29JI
+aHod7MQCLtvL1z5XgnDPLZ4y3_9SbqHKYbNa8UgZkTLF5EacGThYVFDLA9cbafHDtR1kMGE3vv4D
+EJ-0pAYTOGmKlVI7DwNyKsY9JTyudrxTqhOxi9jgcJNWiUaNe9yhL8Pyc2YBqUTTYhh_a2d1rvkZ
+0Gh1crviVxqBrIkRKaMRXZ4f1vDLz-3NvG_vwPOo8WRFo5nGmSdTw7CjBaigJ_cYCfDhoP11pEnw
+cndsZNcHs-v05LlxeIIMDD_f5Bvz-il_DLA4eK2HqgLdxh8ziSDl2azk14MJY4amzz6reEXUuKLV
+RsZGf_jbDGKhE2HuDQ5ovoLOi4OqE1oRuqh-dGxitrYouP2SN1l_1tCEMRth86FMV-6AQtZsvdUo
+y9MtQ7e35atjA8nHtgADlDTmJBKQiUHUsOZ77p1qp17HAFMovUkc739opfEYnKUn6Itpw5Ipm_Is
+ra6chJUfMpOFof5rb5OjqFAN27c_-mPo1lQU3ndYlKGh_n5V8ufX6v2Yri8WzOPf6hjVYotkmoMP
+NPAICDCB8W5ddBjsopzLVVEtaXDu9Qj6-zf77hT4iQ7rBd2Ner8iLqN3Kis0dvkNM3_uH8onau1G
+Y_YYw7PPSZyd2S_7Dd6G-IG4ayO6e5DD6oUwwekyiQI_3rTXNa_wldGxqW9u818010ekE4Qdlfcj
+beIn7fAeaOjReZ87hRgWyMs-EgTVHw8RL3yI_O6VvRTVRONRF1Y4C_-IYa8z-bfrwXx3BBd9TTgb
+EnS9wVOyC2OgUN6BhPLGLhxzkJ05nEjizXEc9t5EPYoSRwesajGGrrG_0-qWbuU5hKLPLkyeJLHb
+5HXOTVsrUR59Vov2M3_EswkxcImblox3k3VS2yihZMGyfqLzZIUXgd8ufkevKKU6DxwacGTb \ No newline at end of file
diff --git a/champ-service/src/main/config/runner-web.xml b/champ-service/src/main/config/runner-web.xml
new file mode 100644
index 0000000..5f65183
--- /dev/null
+++ b/champ-service/src/main/config/runner-web.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ metadata-complete="false" version="3.0">
+
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>/WEB-INF/spring-servlet.xml,
+ classpath:applicationContext.xml
+ </param-value>
+ </context-param>
+
+ <context-param>
+ <param-name>spring.profiles.default</param-name>
+ <param-value>nooauth</param-value>
+ </context-param>
+
+ <listener>
+ <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+ </listener>
+
+ <servlet>
+ <servlet-name>ManagementServlet</servlet-name>
+ <servlet-class>ajsc.ManagementServlet</servlet-class>
+ </servlet>
+
+
+ <filter>
+ <filter-name>InterceptorFilter</filter-name>
+ <filter-class>ajsc.filters.InterceptorFilter</filter-class>
+ <init-param>
+ <param-name>preProcessor_interceptor_config_file</param-name>
+ <param-value>/etc/PreProcessorInterceptors.properties</param-value>
+ </init-param>
+ <init-param>
+ <param-name>postProcessor_interceptor_config_file</param-name>
+ <param-value>/etc/PostProcessorInterceptors.properties</param-value>
+ </init-param>
+
+ </filter>
+
+ <servlet>
+ <servlet-name>RestletServlet</servlet-name>
+ <servlet-class>ajsc.restlet.RestletSpringServlet</servlet-class>
+ <init-param>
+ <param-name>org.restlet.component</param-name>
+ <param-value>restletComponent</param-value>
+ </init-param>
+ </servlet>
+
+ <servlet>
+ <servlet-name>CamelServlet</servlet-name>
+ <servlet-class>ajsc.servlet.AjscCamelServlet</servlet-class>
+ </servlet>
+
+
+ <filter>
+ <filter-name>springSecurityFilterChain</filter-name>
+ <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
+ </filter>
+
+ <servlet>
+ <servlet-name>spring</servlet-name>
+ <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+<!-- <servlet-mapping>
+ <servlet-name>spring</servlet-name>
+ <url-pattern>/</url-pattern>
+ </servlet-mapping>-->
+
+<!-- BEGIN jsp -->
+
+ <servlet id="jsp">
+ <servlet-name>jsp</servlet-name>
+ <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
+ </servlet>
+
+
+
+
+
+ <!-- BEGIN static content -->
+ <servlet>
+ <servlet-name>default</servlet-name>
+ <servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
+ <init-param>
+ <param-name>dirAllowed</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ </servlet>
+ <!-- END static content -->
+</web-app>
diff --git a/champ-service/src/main/docker/Dockerfile b/champ-service/src/main/docker/Dockerfile
new file mode 100644
index 0000000..cf299a2
--- /dev/null
+++ b/champ-service/src/main/docker/Dockerfile
@@ -0,0 +1,34 @@
+FROM ubuntu:14.04
+
+ARG MICRO_HOME=/opt/app/champ-service
+ARG BIN_HOME=$MICRO_HOME/bin
+ARG GRAPHLIB_HOME=$MICRO_HOME/graph-deps
+
+RUN apt-get update
+
+# Install and setup java8
+RUN apt-get update && apt-get install -y software-properties-common
+RUN sudo -E add-apt-repository ppa:openjdk-r/ppa && apt-get update && apt-get install -y openjdk-8-jdk
+ENV JAVA_HOME usr/lib/jvm/java-8-openjdk-amd64
+RUN export JAVA_HOME
+
+# Build up the deployment folder structure
+RUN mkdir -p $MICRO_HOME
+ADD swm/package/nix/dist_files/appl/champ-service/* $MICRO_HOME/
+RUN mkdir -p $GRAPHLIB_HOME
+ADD graph-deps $GRAPHLIB_HOME
+RUN mkdir -p $BIN_HOME
+COPY *.sh $BIN_HOME
+RUN chmod 755 $BIN_HOME/*
+RUN ln -s /logs $MICRO_HOME/logs
+
+# Create the aai user
+RUN mkdir /opt/aaihome && \
+ groupadd -g 492381 aaiadmin && \
+ useradd -r -u 341790 -g 492381 -ms /bin/bash -d /opt/aaihome/aaiadmin aaiadmin && \
+ chown -R aaiadmin:aaiadmin $MICRO_HOME
+USER aaiadmin
+
+EXPOSE 9522 9522
+
+CMD ["/opt/app/champ-service/bin/start.sh"]
diff --git a/champ-service/src/main/java/org/onap/champ/ChampRESTAPI.java b/champ-service/src/main/java/org/onap/champ/ChampRESTAPI.java
new file mode 100644
index 0000000..3d7e074
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/ChampRESTAPI.java
@@ -0,0 +1,568 @@
+package org.onap.champ;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Timer;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+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.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriInfo;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.onap.aai.champcore.ChampTransaction;
+import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException;
+import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException;
+import org.onap.aai.champcore.exceptions.ChampTransactionException;
+import org.onap.aai.champcore.exceptions.ChampUnmarshallingException;
+import org.onap.aai.champcore.model.ChampObject;
+import org.onap.aai.champcore.model.ChampRelationship;
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.eelf.LoggerFactory;
+import org.onap.champ.async.ChampAsyncRequestProcessor;
+import org.onap.champ.entity.ChampObjectDeserializer;
+import org.onap.champ.entity.ChampObjectSerializer;
+import org.onap.champ.entity.ChampRelationshipDeserializer;
+import org.onap.champ.entity.ChampRelationshipSerializer;
+import org.onap.champ.exception.ChampServiceException;
+import org.onap.champ.service.ChampDataService;
+import org.onap.champ.service.logging.ChampMsgs;
+import org.onap.champ.service.logging.LoggingUtil;
+import org.onap.champ.util.ChampProperties;
+import org.onap.champ.util.ChampServiceConstants;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+@Path(value = "/")
+public class ChampRESTAPI {
+
+ private ObjectMapper mapper;
+
+ private ChampDataService champDataService;
+ private String TRANSACTION_METHOD = "method";
+ private Timer timer;
+
+ private Logger logger = LoggerFactory.getInstance().getLogger(ChampRESTAPI.class);
+ Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(ChampRESTAPI.class.getName());
+ private static Logger metricsLogger = LoggerFactory.getInstance().getMetricsLogger(ChampRESTAPI.class.getName());
+
+ public ChampRESTAPI(ChampDataService champDataService, ChampAsyncRequestProcessor champAsyncRequestProcessor) {
+ this.champDataService = champDataService;
+
+ // Async request handling is optional.
+ if (champAsyncRequestProcessor != null) {
+ timer = new Timer("ChampAsyncRequestProcessor-1");
+ timer.schedule(champAsyncRequestProcessor, champAsyncRequestProcessor.getRequestPollingTimeSeconds(),
+ champAsyncRequestProcessor.getRequestPollingTimeSeconds());
+ }
+
+ mapper = new ObjectMapper();
+ SimpleModule module = new SimpleModule();
+ module.addSerializer(ChampObject.class, new ChampObjectSerializer());
+ module.addDeserializer(ChampObject.class, new ChampObjectDeserializer());
+ module.addSerializer(ChampRelationship.class, new ChampRelationshipSerializer());
+ module.addDeserializer(ChampRelationship.class, new ChampRelationshipDeserializer());
+ mapper.registerModule(module);
+ }
+
+ @GET
+ @Path("echo")
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response echo() {
+ return Response.ok().entity("alive").build();
+ }
+
+ @GET
+ @Path("objects/{objectId}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getObject(@PathParam("objectId") String objectId, @QueryParam("transactionId") String tId,
+ @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ logger.info(ChampMsgs.INCOMING_REQUEST, tId, objectId);
+
+ Response response = null;
+ ChampObject retrieved;
+
+ try {
+ ChampTransaction transaction = champDataService.getTransaction(tId);
+
+ if (tId != null && transaction == null) {
+ throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST);
+ }
+ retrieved = champDataService.getObject(objectId, Optional.ofNullable(transaction));
+ if (retrieved == null) {
+ response = Response.status(Status.NOT_FOUND).entity(objectId + " not found").build();
+ } else {
+ response = Response.status(Status.OK).entity(mapper.writeValueAsString(retrieved)).build();
+ }
+
+ } catch (JsonProcessingException e) {
+ response = Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
+ } catch (ChampServiceException ce) {
+ response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
+ } finally {
+ logger.debug(response.getEntity().toString());
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "GET", Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+
+ return response;
+ }
+
+ @DELETE
+ @Path("objects/{objectId}")
+ public Response deleteObject(@PathParam("objectId") String objectId, @QueryParam("transactionId") String tId,
+ @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ logger.info(ChampMsgs.INCOMING_REQUEST, tId, objectId);
+ ChampObject retrieved;
+ Response response = null;
+ try {
+ ChampTransaction transaction = champDataService.getTransaction(tId);
+
+ if (tId != null && transaction == null) {
+ throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST);
+ }
+ champDataService.deleteObject(objectId, Optional.ofNullable(transaction));
+
+ response = Response.status(Status.OK).build();
+ } catch (ChampObjectNotExistsException e) {
+ response = Response.status(Status.NOT_FOUND).entity(objectId + " not found").build();
+ } catch (ChampServiceException ce) {
+ response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
+ } catch (ChampTransactionException | ChampUnmarshallingException e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "DELETE",
+ Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @POST
+ @Path("objects")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response postObject(String champObj, @QueryParam("transactionId") String tId, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo, @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ logger.info(ChampMsgs.INCOMING_REQUEST, tId, champObj);
+ Response response = null;
+ try {
+ ChampTransaction transaction = champDataService.getTransaction(tId);
+ if (tId != null && transaction == null) {
+ throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST);
+ }
+ ChampObject champObject = mapper.readValue(champObj, ChampObject.class);
+
+ ChampObject created = champDataService.storeObject(champObject, Optional.ofNullable(transaction));
+ response = Response.status(Status.CREATED).entity(mapper.writeValueAsString(created)).build();
+ } catch (IOException e) {
+ response = Response.status(Status.BAD_REQUEST).entity("Unable to parse the payload").build();
+ } catch (ChampServiceException ce) {
+ response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
+ } catch (Exception e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ LoggingUtil.logInternalError(logger, e);
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "POST",
+ Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @PUT
+ @Path("objects/{objectId}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response putObject(@PathParam("objectId") String objectId, String champObj,
+ @QueryParam("transactionId") String tId, @Context HttpHeaders headers, @Context UriInfo uriInfo,
+ @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ logger.info(ChampMsgs.INCOMING_REQUEST, tId, objectId + " " + champObj);
+
+ Response response = null;
+ try {
+ ChampTransaction transaction = champDataService.getTransaction(tId);
+ if (tId != null && transaction == null) {
+ throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST);
+ }
+
+ ChampObject co = mapper.readValue(champObj, ChampObject.class);
+ // check if key is present or if it equals the key that is in the URI
+ ChampObject updated = champDataService.replaceObject(co, objectId, Optional.ofNullable(transaction));
+
+ response = Response.status(Status.OK).entity(mapper.writeValueAsString(updated)).build();
+ } catch (IOException e) {
+ response = Response.status(Status.BAD_REQUEST).entity("Unable to parse the payload").build();
+ } catch (ChampServiceException ce) {
+ response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
+ } catch (Exception e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ LoggingUtil.logInternalError(logger, e);
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "PUT", Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @GET
+ @Path("objects/relationships/{oId}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getEdges(@PathParam("oId") String oId, @QueryParam("transactionId") String tId,
+ @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ List<ChampRelationship> retrieved;
+ Optional<ChampObject> rObject;
+ Response response = null;
+ ChampTransaction transaction = null;
+ try {
+
+ retrieved = champDataService.getRelationshipsByObject(oId, Optional.ofNullable(transaction));
+ response = Response.status(Status.OK).entity(mapper.writeValueAsString(retrieved)).build();
+ } catch (JsonProcessingException e) {
+ response = Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
+ } catch (ChampServiceException ce) {
+ response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
+ } catch (Exception e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ LoggingUtil.logInternalError(logger, e);
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "GET", Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @GET
+ @Path("objects/filter/")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response filterObject(@Context HttpHeaders headers, @Context UriInfo uriInfo,
+ @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ String propertiesKey = ChampProperties.get(ChampServiceConstants.CHAMP_COLLECTION_PROPERTIES_KEY);
+ List<ChampObject> objects;
+ Map<String, Object> filter = new HashMap<>();
+
+ for (Map.Entry<String, List<String>> e : uriInfo.getQueryParameters().entrySet()) {
+ if (!e.getKey().equals(propertiesKey)) {
+ filter.put(e.getKey(), e.getValue().get(0));
+ }
+ }
+
+ HashSet<String> properties;
+ if (uriInfo.getQueryParameters().containsKey(propertiesKey)) {
+ properties = new HashSet<>(uriInfo.getQueryParameters().get(propertiesKey));
+ } else {
+ properties = new HashSet<>();
+ }
+
+ Response response = null;
+ try {
+ objects = champDataService.queryObjects(filter, properties);
+ response = Response.status(Status.OK).type(MediaType.APPLICATION_JSON).entity(mapper.writeValueAsString(objects))
+ .build();
+ } catch (JsonProcessingException e) {
+ e.printStackTrace();
+ response = Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
+ } catch (ChampServiceException e1) {
+ response = Response.status(e1.getHttpStatus()).entity(e1.getMessage()).build();
+ } catch (Exception e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ LoggingUtil.logInternalError(logger, e);
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "GET", Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @GET
+ @Path("relationships/{rId}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getRelationship(@PathParam("rId") String rId, @QueryParam("transactionId") String tId,
+ @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ logger.info(ChampMsgs.INCOMING_REQUEST, tId, rId);
+ ChampRelationship retrieved;
+ Response response = null;
+ try {
+ ChampTransaction transaction = champDataService.getTransaction(tId);
+
+ if (tId != null && transaction == null) {
+ throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST);
+ }
+ retrieved = champDataService.getRelationship(rId, Optional.ofNullable(transaction));
+ if (retrieved == null) {
+ response = Response.status(Status.NOT_FOUND).entity(rId + " not found").build();
+ return response;
+ }
+ response = Response.status(Status.OK).entity(mapper.writeValueAsString(retrieved)).build();
+
+ } catch (IOException e) {
+ response = Response.status(Status.BAD_REQUEST).entity("Unable to parse the payload").build();
+ } catch (ChampServiceException ce) {
+ response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
+ } catch (Exception e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ LoggingUtil.logInternalError(logger, e);
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "GET", Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @POST
+ @Path("relationships")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response postRelationships(String relationship, @QueryParam("transactionId") String tId,
+ @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ logger.info(ChampMsgs.INCOMING_REQUEST, tId, relationship);
+ Response response = null;
+ try {
+ ChampTransaction transaction = champDataService.getTransaction(tId);
+ if (tId != null && transaction == null) {
+ throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST);
+ }
+ ChampRelationship r = mapper.readValue(relationship, ChampRelationship.class);
+
+ ChampRelationship created = champDataService.storeRelationship(r, Optional.ofNullable(transaction));
+
+ response = Response.status(Status.CREATED).entity(mapper.writeValueAsString(created)).build();
+ } catch (IOException e) {
+ response = Response.status(Status.BAD_REQUEST).entity("Unable to parse the payload").build();
+ } catch (ChampServiceException ce) {
+ response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
+ } catch (Exception e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ LoggingUtil.logInternalError(logger, e);
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "POST",
+ Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @PUT
+ @Path("relationships/{rId}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response updateRelationship(@PathParam("rId") String rId, String relationship,
+ @QueryParam("transactionId") String tId, @Context HttpHeaders headers, @Context UriInfo uriInfo,
+ @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ logger.info(ChampMsgs.INCOMING_REQUEST, tId, relationship);
+
+ Response response = null;
+ try {
+ ChampTransaction transaction = champDataService.getTransaction(tId);
+ if (tId != null && transaction == null) {
+ throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST);
+ }
+ ChampRelationship r = mapper.readValue(relationship, ChampRelationship.class);
+ ChampRelationship updated = champDataService.updateRelationship(r, rId, Optional.ofNullable(transaction));
+
+ response = Response.status(Status.OK).entity(mapper.writeValueAsString(updated)).build();
+ } catch (IOException e) {
+ response = Response.status(Status.BAD_REQUEST).entity("Unable to parse the payload").build();
+ } catch (ChampServiceException ce) {
+ response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
+ } catch (Exception e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ LoggingUtil.logInternalError(logger, e);
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "PUT", Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @DELETE
+ @Path("relationships/{relationshipId}")
+ public Response deleteRelationship(@PathParam("relationshipId") String relationshipId,
+ @QueryParam("transactionId") String tId, @Context HttpHeaders headers, @Context UriInfo uriInfo,
+ @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ logger.info(ChampMsgs.INCOMING_REQUEST, tId, relationshipId);
+
+ Response response = null;
+ try {
+ ChampTransaction transaction = champDataService.getTransaction(tId);
+ if (tId != null && transaction == null) {
+ throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST);
+ }
+ champDataService.deleteRelationship(relationshipId, Optional.ofNullable(transaction));
+ response = Response.status(Status.OK).build();
+
+ } catch (ChampRelationshipNotExistsException e) {
+ response = Response.status(Status.NOT_FOUND).entity(relationshipId + " not found").build();
+ } catch (ChampServiceException ce) {
+ response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
+ } catch (ChampTransactionException | ChampUnmarshallingException e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "DELETE",
+ Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @GET
+ @Path("relationships/filter/")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response filterMethod(@Context HttpHeaders headers, @Context UriInfo uriInfo,
+ @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ List<ChampRelationship> list;
+ Map<String, Object> filter = new HashMap<>();
+ for (Map.Entry<String, List<String>> e : uriInfo.getQueryParameters().entrySet()) {
+ filter.put(e.getKey(), e.getValue().get(0));
+ }
+ Response response = null;
+ try {
+ list = champDataService.queryRelationships(filter);
+ response = Response.status(Status.OK).type(MediaType.APPLICATION_JSON).entity(mapper.writeValueAsString(list))
+ .build();
+ } catch (JsonProcessingException e) {
+ e.printStackTrace();
+ response = Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
+ } catch (ChampServiceException e1) {
+ response = Response.status(e1.getHttpStatus()).entity(e1.getMessage()).build();
+ } catch (Exception e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ LoggingUtil.logInternalError(logger, e);
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "GET", Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @POST
+ @Path("transaction")
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response openTransaction(@Context HttpHeaders headers, @Context UriInfo uriInfo,
+ @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ Status s;
+ String transaction = champDataService.openTransaction();
+
+ s = Status.OK;
+ Response response = Response.status(s).entity(transaction).build();
+ logger.info(ChampMsgs.PROCESS_EVENT, "Opened Transaction with ID: " + transaction, s.toString());
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "POST", Long.toString(System.currentTimeMillis() - startTimeInMs));
+ return response;
+ }
+
+ @GET
+ @Path("transaction/{tId}")
+ public Response getSpecificTransaction(@PathParam("tId") String tId, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo, @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+
+ Response response = null;
+ ChampTransaction transaction = champDataService.getTransaction(tId);
+ if (transaction == null) {
+ response = Response.status(Status.NOT_FOUND).entity("transaction " + tId + " not found").build();
+ return response;
+ }
+
+ try {
+ response = Response.status(Status.OK).entity(mapper.writeValueAsString(tId + " is OPEN")).build();
+ } catch (JsonProcessingException e) {
+ response = Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
+ } catch (Exception e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ LoggingUtil.logInternalError(logger, e);
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "GET", Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @PUT
+ @Path("transaction/{tId}")
+ @Produces(MediaType.TEXT_PLAIN)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response updateTransaction(String t, @PathParam("tId") String tId, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo, @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ logger.info(ChampMsgs.INCOMING_REQUEST, tId, "COMMIT/ROLLBACK");
+
+ Response response = null;
+ try {
+ JSONObject jsonObj = new JSONObject(t);
+ String method = jsonObj.getString(this.TRANSACTION_METHOD);
+
+ if (method.equals("commit")) {
+ champDataService.commitTransaction(tId);
+ response = Response.status(Status.OK).entity("COMMITTED").build();
+
+ } else if (method.equals("rollback")) {
+ champDataService.rollbackTransaction(tId);
+ response = Response.status(Status.OK).entity("ROLLED BACK").build();
+ } else {
+ response = Response.status(Status.BAD_REQUEST).entity("Invalid Method: " + method).build();
+ return response;
+ }
+
+ } catch (ChampTransactionException e) {
+ response = Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
+ } catch (JSONException e) {
+ response = Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
+ } catch (ChampServiceException e) {
+ response = Response.status(e.getHttpStatus()).entity(e.getMessage()).build();
+ } catch (Exception e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ LoggingUtil.logInternalError(logger, e);
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "PUT", Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/async/ChampAsyncRequestProcessor.java b/champ-service/src/main/java/org/onap/champ/async/ChampAsyncRequestProcessor.java
new file mode 100644
index 0000000..af2ab20
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/async/ChampAsyncRequestProcessor.java
@@ -0,0 +1,327 @@
+/**
+ * ============LICENSE_START=======================================================
+ * Gizmo
+ * ================================================================================
+ * 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 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.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ */
+package org.onap.champ.async;
+
+import java.util.Optional;
+import java.util.TimerTask;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import javax.naming.OperationNotSupportedException;
+import javax.ws.rs.core.Response.Status;
+
+import org.onap.aai.champcore.ChampTransaction;
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.eelf.LoggerFactory;
+import org.onap.champ.ChampRESTAPI;
+import org.onap.champ.event.GraphEvent;
+import org.onap.champ.event.GraphEvent.GraphEventResult;
+import org.onap.champ.event.GraphEventEdge;
+import org.onap.champ.event.GraphEventVertex;
+import org.onap.champ.exception.ChampServiceException;
+import org.onap.champ.service.ChampDataService;
+import org.onap.champ.service.ChampThreadFactory;
+import org.onap.champ.service.logging.ChampMsgs;
+
+import org.onap.aai.event.api.EventConsumer;
+
+/**
+ * This Class polls the Graph events from request topic perform the necessary
+ * CRUD operation by calling champDAO and queues up the response to be consumed
+ * by response handler.
+ */
+public class ChampAsyncRequestProcessor extends TimerTask {
+
+ private Logger logger = LoggerFactory.getInstance().getLogger(ChampAsyncRequestProcessor.class);
+
+ private ChampDataService champDataService;
+
+ /**
+ * Number of events that can be queued up.
+ */
+ private Integer requestProcesserQueueSize;
+
+ /**
+ * Number of event publisher worker threads.
+ */
+ private Integer requestProcesserPoolSize;
+
+ /**
+ * Number of event publisher worker threads.
+ */
+ private Integer requestPollingTimeSeconds;
+
+ /**
+ * Internal queue where outgoing events will be buffered until they can be
+ * serviced by.
+ **/
+ private BlockingQueue<GraphEvent> requestProcesserEventQueue;
+
+ /**
+ * Pool of worker threads that do the work of publishing the events to the
+ * event bus.
+ */
+ private ThreadPoolExecutor requestProcesserPool;
+
+ private ChampAsyncResponsePublisher champAsyncResponsePublisher;
+
+ private EventConsumer asyncRequestConsumer;
+
+ private static final Integer DEFAULT_ASYNC_REQUEST_PROCESS_QUEUE_CAPACITY = 10000;
+
+ private static final Integer DEFAULT_ASYNC_REQUEST_PROCESS_THREAD_POOL_SIZE = 10;
+ private static final Integer DEFAULT_ASYNC_REQUEST_PROCESS_POLLING_SECOND = 30000;
+ private static final String CHAMP_GRAPH_REQUEST_PROCESS_THREAD_NAME = "ChampAsyncGraphRequestEventProcessor";
+ Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(ChampRESTAPI.class.getName());
+
+ public ChampAsyncRequestProcessor(ChampDataService champDataService,
+ ChampAsyncResponsePublisher champAsyncResponsePublisher, EventConsumer asyncRequestConsumer) {
+
+ this.requestProcesserQueueSize = DEFAULT_ASYNC_REQUEST_PROCESS_QUEUE_CAPACITY;
+
+ this.requestProcesserPoolSize = DEFAULT_ASYNC_REQUEST_PROCESS_THREAD_POOL_SIZE;
+
+ this.requestPollingTimeSeconds = DEFAULT_ASYNC_REQUEST_PROCESS_POLLING_SECOND;
+ requestProcesserEventQueue = new ArrayBlockingQueue<GraphEvent>(requestProcesserQueueSize);
+ requestProcesserPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(requestProcesserPoolSize,
+ new ChampThreadFactory(CHAMP_GRAPH_REQUEST_PROCESS_THREAD_NAME));
+
+ for (int i = 0; i < requestProcesserPoolSize; i++) {
+ requestProcesserPool.submit(new ChampProcessorWorker());
+ }
+
+ this.champDataService = champDataService;
+ this.champAsyncResponsePublisher = champAsyncResponsePublisher;
+ this.asyncRequestConsumer = asyncRequestConsumer;
+ logger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO,
+ "ChampAsyncRequestProcessor initialized SUCCESSFULLY! with event consumer "
+ + asyncRequestConsumer.getClass().getName());
+ }
+
+
+
+ public ChampAsyncRequestProcessor(ChampDataService champDataService,
+ ChampAsyncResponsePublisher champAsyncResponsePublisher, EventConsumer asyncRequestConsumer,
+ Integer requestProcesserQueueSize, Integer requestProcesserPoolSize, Integer requestPollingTimeSeconds) {
+
+ this.requestProcesserQueueSize = requestProcesserQueueSize;
+
+ this.requestProcesserPoolSize = requestProcesserPoolSize;
+
+ this.requestPollingTimeSeconds = requestPollingTimeSeconds;
+
+ requestProcesserEventQueue = new ArrayBlockingQueue<GraphEvent>(requestProcesserQueueSize);
+ requestProcesserPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(requestProcesserPoolSize,
+ new ChampThreadFactory(CHAMP_GRAPH_REQUEST_PROCESS_THREAD_NAME));
+
+ for (int i = 0; i < requestProcesserPoolSize; i++) {
+ requestProcesserPool.submit(new ChampProcessorWorker());
+ }
+
+ this.champDataService = champDataService;
+ this.champAsyncResponsePublisher = champAsyncResponsePublisher;
+ this.asyncRequestConsumer = asyncRequestConsumer;
+ logger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO,
+ "ChampAsyncRequestProcessor initialized SUCCESSFULLY! with event consumer "
+ + asyncRequestConsumer.getClass().getName());
+ }
+
+ private class ChampProcessorWorker implements Runnable {
+
+ @Override
+ public void run() {
+
+ while (true) {
+
+ GraphEvent event = null;
+ try {
+ // Get the next event to be published from the queue.
+ event = requestProcesserEventQueue.take();
+ } catch (InterruptedException e) {
+ // Restore the interrupted status.
+ Thread.currentThread().interrupt();
+ }
+
+ // Parse the event and call champ Dao to process , Create the
+ // response event and put it on response queue
+ event.setResult(GraphEventResult.SUCCESS);
+
+ // Check if this request is part of an ongoing DB transaction
+ ChampTransaction transaction = champDataService.getTransaction(event.getDbTransactionId());
+ if ( (event.getDbTransactionId() != null) && (transaction == null) ) {
+ event.setResult(GraphEventResult.FAILURE);
+ event.setErrorMessage("Database transactionId " + event.getDbTransactionId() + " not found");
+ event.setHttpErrorStatus(Status.BAD_REQUEST);
+ }
+
+ if (event.getResult() != GraphEventResult.FAILURE) {
+ try {
+ if (event.getVertex() != null) {
+
+ switch (event.getOperation()) {
+ case CREATE:
+ event.setVertex(GraphEventVertex.fromChampObject(
+ champDataService.storeObject(event.getVertex().toChampObject(), Optional.ofNullable(transaction)),
+ event.getVertex().getModelVersion()));
+ break;
+
+ case UPDATE:
+ event.setVertex(GraphEventVertex.fromChampObject(
+ champDataService.replaceObject(event.getVertex().toChampObject(), event.getVertex().getId(), Optional.ofNullable(transaction)),
+ event.getVertex().getModelVersion()));
+ break;
+ case DELETE:
+ champDataService.deleteObject(event.getVertex().getId(), Optional.ofNullable(transaction));
+ break;
+ default:
+ // log error
+ }
+ } else if (event.getEdge() != null) {
+ switch (event.getOperation()) {
+ case CREATE:
+ event.setEdge(GraphEventEdge.fromChampRelationship(
+ champDataService.storeRelationship(event.getEdge().toChampRelationship(), Optional.ofNullable(transaction)),
+ event.getEdge().getModelVersion()));
+ break;
+
+ case UPDATE:
+ event.setEdge(GraphEventEdge.fromChampRelationship(champDataService
+ .updateRelationship(event.getEdge().toChampRelationship(), event.getEdge().getId(), Optional.ofNullable(transaction)),
+ event.getEdge().getModelVersion()));
+
+ break;
+ case DELETE:
+ champDataService.deleteRelationship(event.getEdge().getId(), Optional.ofNullable(transaction));
+ break;
+ default:
+ logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR,
+ "Invalid operation for event transactionId: " + event.getTransactionId());
+ }
+
+ } else {
+ logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR,
+ "Invalid payload for event transactionId: " + event.getTransactionId());
+ }
+ } catch (ChampServiceException champException) {
+ logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR, champException.getMessage());
+ event.setResult(GraphEventResult.FAILURE);
+ event.setErrorMessage(champException.getMessage());
+ event.setHttpErrorStatus(champException.getHttpStatus());
+
+ } catch (Exception ex) {
+ logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR, ex.getMessage());
+ event.setResult(GraphEventResult.FAILURE);
+ event.setErrorMessage(ex.getMessage());
+ event.setHttpErrorStatus(Status.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ if (event.getResult().equals(GraphEventResult.SUCCESS)) {
+ logger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO,
+ "Event processed of type: " + event.getObjectType() + " with key: " + event.getObjectKey()
+ + " , transaction-id: " + event.getTransactionId() + " , operation: "
+ + event.getOperation().toString() + " , result: " + event.getResult());
+ } else {
+ logger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO,
+ "Event processed of type: " + event.getObjectType() + " with key: " + event.getObjectKey()
+ + " , transaction-id: " + event.getTransactionId() + " , operation: "
+ + event.getOperation().toString() + " , result: " + event.getResult() + " , error: "
+ + event.getErrorMessage());
+ }
+
+ champAsyncResponsePublisher.publishResponseEvent(event);
+
+ }
+ }
+ }
+
+ @Override
+ public void run() {
+
+ logger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO, "Listening for graph events");
+
+ if (asyncRequestConsumer == null) {
+ logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR, "Unable to initialize ChampAsyncRequestProcessor");
+ }
+
+ Iterable<String> events = null;
+ try {
+ events = asyncRequestConsumer.consume();
+ } catch (Exception e) {
+ logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR, e.getMessage());
+ return;
+ }
+
+ if (events == null || !events.iterator().hasNext()) {
+ logger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO, "No events recieved");
+
+ }
+
+ for (String event : events) {
+ try {
+ GraphEvent requestEvent = GraphEvent.fromJson(event);
+ auditLogger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO,
+ "Event received of type: " + requestEvent.getObjectType() + " with key: " + requestEvent.getObjectKey()
+ + " , transaction-id: " + requestEvent.getTransactionId() + " , operation: "
+ + requestEvent.getOperation().toString());
+ logger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO,
+ "Event received of type: " + requestEvent.getObjectType() + " with key: " + requestEvent.getObjectKey()
+ + " , transaction-id: " + requestEvent.getTransactionId() + " , operation: "
+ + requestEvent.getOperation().toString());
+ logger.debug(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO, "Event received with payload:" + event);
+
+ // Try to submit the event to be published to the event bus.
+ if (!requestProcesserEventQueue.offer(requestEvent)) {
+ logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR,
+ "Event could not be published to the event bus due to: Internal buffer capacity exceeded.");
+ }
+
+ } catch (Exception e) {
+ logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR, e.getMessage());
+ }
+ }
+
+ try {
+ asyncRequestConsumer.commitOffsets();
+ } catch(OperationNotSupportedException e) {
+ //Dmaap doesnt support commit with offset
+ logger.debug(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_WARN, e.getMessage());
+ }
+ catch (Exception e) {
+ logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_WARN, e.getMessage());
+ }
+
+ }
+
+
+
+ public Integer getRequestPollingTimeSeconds() {
+ return requestPollingTimeSeconds;
+ }
+
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/async/ChampAsyncResponsePublisher.java b/champ-service/src/main/java/org/onap/champ/async/ChampAsyncResponsePublisher.java
new file mode 100644
index 0000000..8c31a53
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/async/ChampAsyncResponsePublisher.java
@@ -0,0 +1,160 @@
+/**
+ * ============LICENSE_START=======================================================
+ *
+ * ================================================================================
+ * 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 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.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ */
+package org.onap.champ.async;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.eelf.LoggerFactory;
+import org.onap.champ.event.GraphEvent;
+import org.onap.champ.event.GraphEvent.GraphEventResult;
+import org.onap.champ.service.ChampThreadFactory;
+import org.onap.champ.service.logging.ChampMsgs;
+
+import org.onap.aai.event.api.EventPublisher;
+
+public class ChampAsyncResponsePublisher {
+
+ private EventPublisher asyncResponsePublisher;
+
+ /**
+ * Number of events that can be queued up.
+ */
+ private Integer responsePublisherQueueSize;
+
+ /**
+ * Number of event publisher worker threads.
+ */
+ private Integer responsePublisherPoolSize;
+
+ /**
+ * Internal queue where outgoing events will be buffered.
+ **/
+ private BlockingQueue<GraphEvent> responsePublisherEventQueue;
+
+ /**
+ * Pool of worker threads that do the work of publishing the events to the
+ * event bus.
+ */
+ private ThreadPoolExecutor responsePublisherPool;
+
+ private static final Integer DEFAULT_ASYNC_RESPONSE_PUBLISH_QUEUE_CAPACITY = 10000;
+
+ private static final Integer DEFAULT_ASYNC_RESPONSE_PUBLISH_THREAD_POOL_SIZE = 10;
+ private static final String CHAMP_GRAPH_RESPONSE_PUBLISH_THREAD_NAME = "ChampAsyncGraphResponseEventPublisher";
+
+ private static Logger logger = LoggerFactory.getInstance().getLogger(ChampAsyncRequestProcessor.class.getName());
+
+ public ChampAsyncResponsePublisher(EventPublisher asyncResponsePublisher, Integer responsePublisherQueueSize,
+ Integer responsePublisherPoolSize) {
+ this.responsePublisherQueueSize = responsePublisherQueueSize;
+
+ this.responsePublisherPoolSize = responsePublisherPoolSize;
+
+ responsePublisherEventQueue = new ArrayBlockingQueue<GraphEvent>(responsePublisherQueueSize);
+ responsePublisherPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(responsePublisherPoolSize,
+ new ChampThreadFactory(CHAMP_GRAPH_RESPONSE_PUBLISH_THREAD_NAME));
+
+ for (int i = 0; i < responsePublisherPoolSize; i++) {
+ responsePublisherPool.submit(new GizmoResponsePublisherWorker());
+ }
+ this.asyncResponsePublisher = asyncResponsePublisher;
+
+ logger.info(ChampMsgs.CHAMP_ASYNC_RESPONSE_PUBLISHER_INFO,
+ "ChampAsyncResponsePublisher initialized SUCCESSFULLY! with event publisher "
+ + asyncResponsePublisher.getClass().getName());
+ }
+
+ public ChampAsyncResponsePublisher(EventPublisher asyncResponsePublisher) {
+ responsePublisherQueueSize = DEFAULT_ASYNC_RESPONSE_PUBLISH_QUEUE_CAPACITY;
+
+ responsePublisherPoolSize = DEFAULT_ASYNC_RESPONSE_PUBLISH_THREAD_POOL_SIZE;
+
+ responsePublisherEventQueue = new ArrayBlockingQueue<GraphEvent>(responsePublisherQueueSize);
+ responsePublisherPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(responsePublisherPoolSize,
+ new ChampThreadFactory(CHAMP_GRAPH_RESPONSE_PUBLISH_THREAD_NAME));
+
+ for (int i = 0; i < responsePublisherPoolSize; i++) {
+ responsePublisherPool.submit(new GizmoResponsePublisherWorker());
+ }
+ this.asyncResponsePublisher = asyncResponsePublisher;
+
+ logger.info(ChampMsgs.CHAMP_ASYNC_RESPONSE_PUBLISHER_INFO,
+ "CrudAsyncResponsePublisher initialized SUCCESSFULLY! with event publisher "
+ + asyncResponsePublisher.getClass().getName());
+ }
+
+ public void publishResponseEvent(GraphEvent event) {
+ responsePublisherEventQueue.offer(event);
+
+ }
+
+ private class GizmoResponsePublisherWorker implements Runnable {
+
+ @Override
+ public void run() {
+
+ while (true) {
+
+ GraphEvent event = null;
+ try {
+
+ // Get the next event to be published from the queue.
+ event = responsePublisherEventQueue.take();
+
+ } catch (InterruptedException e) {
+
+ // Restore the interrupted status.
+ Thread.currentThread().interrupt();
+ }
+ // Publish the response
+
+ try {
+ event.setTimestamp(System.currentTimeMillis());
+ asyncResponsePublisher.sendSync(event.toJson());
+ if (event.getResult().equals(GraphEventResult.SUCCESS)) {
+ logger.info(ChampMsgs.CHAMP_ASYNC_RESPONSE_PUBLISHER_INFO,
+ "Response published for Event of type: " + event.getObjectType() + " with key: " + event.getObjectKey()
+ + " , transaction-id: " + event.getTransactionId() + " , operation: "
+ + event.getOperation().toString() + " , result: " + event.getResult());
+ } else {
+ logger.info(ChampMsgs.CHAMP_ASYNC_RESPONSE_PUBLISHER_INFO,
+ "Response published for Event of type: " + event.getObjectType() + " with key: " + event.getObjectKey()
+ + " , transaction-id: " + event.getTransactionId() + " , operation: "
+ + event.getOperation().toString() + " , result: " + event.getResult() + " , error: "
+ + event.getErrorMessage());
+ }
+ } catch (Exception ex) {
+ logger.error(ChampMsgs.CHAMP_ASYNC_RESPONSE_PUBLISHER_ERROR, ex.getMessage());
+ }
+
+ }
+ }
+ }
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/entity/ChampObjectDeserializer.java b/champ-service/src/main/java/org/onap/champ/entity/ChampObjectDeserializer.java
new file mode 100644
index 0000000..cee7763
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/entity/ChampObjectDeserializer.java
@@ -0,0 +1,67 @@
+/**
+ * ============LICENSE_START==========================================
+ * org.onap.aai
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ===================================================================
+ * 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.
+ * ============LICENSE_END============================================
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.champ.entity;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.onap.aai.champcore.model.ChampObject;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+
+public class ChampObjectDeserializer extends StdDeserializer<ChampObject> {
+
+ private static final long serialVersionUID = -3625275249560680339L;
+
+ public ChampObjectDeserializer() {
+ this(null);
+ }
+
+ protected ChampObjectDeserializer(Class<ChampObject> t) {
+ super(t);
+ }
+
+ public ChampObject deserialize(JsonParser jparser, DeserializationContext dctx)
+ throws IOException, JsonProcessingException {
+
+ JsonNode node = jparser.getCodec().readTree(jparser);
+ JsonNode type = node.get("type");
+ JsonNode key = node.get("key");
+ Map<String, Object> props = new HashMap<>();
+ JsonNode propNode = node.get("properties");
+ propNode.fields().forEachRemaining((x)->props.put(x.getKey(), x.getValue().asText()));
+
+ ChampObject.Builder builder = new ChampObject.Builder(type.asText()).properties(props);
+
+ if(key != null){
+ builder.key(key.asText());
+ }
+
+ return builder.build();
+ }
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/entity/ChampObjectSerializer.java b/champ-service/src/main/java/org/onap/champ/entity/ChampObjectSerializer.java
new file mode 100644
index 0000000..c43b6bf
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/entity/ChampObjectSerializer.java
@@ -0,0 +1,54 @@
+/**
+ * ============LICENSE_START==========================================
+ * org.onap.aai
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ===================================================================
+ * 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.
+ * ============LICENSE_END============================================
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.champ.entity;
+
+import java.io.IOException;
+
+import org.onap.aai.champcore.model.ChampObject;
+
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+
+public class ChampObjectSerializer extends StdSerializer<ChampObject> {
+
+ private static final long serialVersionUID = -4057960968983473983L;
+
+ public ChampObjectSerializer() {
+ this(null);
+ }
+
+ protected ChampObjectSerializer(Class<ChampObject> t) {
+ super(t);
+ }
+
+ public void serialize(ChampObject co, JsonGenerator jgen, SerializerProvider ser)
+ throws IOException, JsonGenerationException {
+ jgen.writeStartObject();
+ jgen.writeStringField("key", co.getKeyValue().toString());
+ jgen.writeStringField("type", co.getType());
+ jgen.writeObjectField("properties", co.getProperties());
+ jgen.writeEndObject();
+ }
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipDeserializer.java b/champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipDeserializer.java
new file mode 100644
index 0000000..63b9e0c
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipDeserializer.java
@@ -0,0 +1,73 @@
+/**
+ * ============LICENSE_START==========================================
+ * org.onap.aai
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ===================================================================
+ * 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.
+ * ============LICENSE_END============================================
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.champ.entity;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+
+import org.onap.aai.champcore.model.ChampObject;
+import org.onap.aai.champcore.model.ChampRelationship;
+
+public class ChampRelationshipDeserializer extends StdDeserializer<ChampRelationship> {
+
+ private static final long serialVersionUID = -3625275249560680339L;
+
+ public ChampRelationshipDeserializer() {
+ this(null);
+ }
+
+ protected ChampRelationshipDeserializer(Class<ChampRelationship> t) {
+ super(t);
+ }
+
+ public ChampRelationship deserialize(JsonParser jparser, DeserializationContext dctx)
+ throws IOException, JsonProcessingException {
+
+ JsonNode node = jparser.getCodec().readTree(jparser);
+ JsonNode type = node.get("type");
+ JsonNode key = node.get("key");
+ Map<String, Object> props = new HashMap<>();
+ JsonNode propNode = node.get("properties");
+ propNode.fields().forEachRemaining((x)->props.put(x.getKey(), x.getValue().asText()));
+
+ JsonNode srcNode = node.get("source");
+ JsonNode targetNode = node.get("target");
+
+ ChampObject src = jparser.getCodec ().treeToValue ( srcNode, ChampObject.class );
+ ChampObject target = jparser.getCodec ().treeToValue ( targetNode, ChampObject.class );
+
+ ChampRelationship.Builder builder = new ChampRelationship.Builder(src, target, type.asText()).properties(props);
+
+ if(key != null){
+ builder.key(key.asText());
+ }
+
+ return builder.build();
+ }
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipSerializer.java b/champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipSerializer.java
new file mode 100644
index 0000000..5d21aa5
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipSerializer.java
@@ -0,0 +1,55 @@
+/**
+ * ============LICENSE_START==========================================
+ * org.onap.aai
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ===================================================================
+ * 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.
+ * ============LICENSE_END============================================
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.champ.entity;
+
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import org.onap.aai.champcore.model.ChampRelationship;
+
+import java.io.IOException;
+
+public class ChampRelationshipSerializer extends StdSerializer<ChampRelationship> {
+
+ private static final long serialVersionUID = -4057960968983473983L;
+
+ public ChampRelationshipSerializer() {
+ this(null);
+ }
+
+ protected ChampRelationshipSerializer(Class<ChampRelationship> t) {
+ super(t);
+ }
+
+ public void serialize( ChampRelationship cr, JsonGenerator jgen, SerializerProvider ser)
+ throws IOException, JsonGenerationException {
+ jgen.writeStartObject();
+ jgen.writeStringField("key", cr.getKeyValue().toString());
+ jgen.writeStringField("type", cr.getType());
+ jgen.writeObjectField("properties", cr.getProperties());
+ jgen.writeObjectField ("source", cr.getSource());
+ jgen.writeObjectField ("target", cr.getTarget ());
+ jgen.writeEndObject();
+ }
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/event/GraphEvent.java b/champ-service/src/main/java/org/onap/champ/event/GraphEvent.java
new file mode 100644
index 0000000..d649a3e
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/event/GraphEvent.java
@@ -0,0 +1,245 @@
+/**
+ * ============LICENSE_START=======================================================
+ * Gizmo
+ * ================================================================================
+ * 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 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.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ */
+package org.onap.champ.event;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.onap.champ.exception.ChampServiceException;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.annotations.SerializedName;
+
+public class GraphEvent {
+
+ public enum GraphEventOperation {
+ CREATE, UPDATE, DELETE
+ }
+
+ public enum GraphEventResult {
+ SUCCESS, FAILURE
+ }
+
+ private GraphEventOperation operation;
+
+ @SerializedName("transaction-id")
+ private String transactionId;
+
+ @SerializedName("database-transaction-id")
+ private String dbTransactionId;
+
+ private long timestamp;
+
+ private GraphEventVertex vertex;
+
+ private GraphEventEdge edge;
+
+ private GraphEventResult result;
+
+ @SerializedName("error-message")
+ private String errorMessage;
+
+ private Status httpErrorStatus;
+
+ /**
+ * Marshaller/unmarshaller for converting to/from JSON.
+ */
+ private static final Gson gson = new GsonBuilder().disableHtmlEscaping()
+ .setPrettyPrinting().create();
+
+ public static Builder builder(GraphEventOperation operation) {
+ return new Builder(operation);
+ }
+
+ public GraphEventOperation getOperation() {
+ return operation;
+ }
+
+ public String getTransactionId() {
+ return transactionId;
+ }
+
+ public String getDbTransactionId() {
+ return dbTransactionId;
+ }
+
+ public void setDbTransactionId(String id) {
+ dbTransactionId = id;
+ }
+
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ public GraphEventVertex getVertex() {
+ return vertex;
+ }
+
+ public GraphEventEdge getEdge() {
+ return edge;
+ }
+
+ public GraphEventResult getResult() {
+ return result;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ public void setResult(GraphEventResult result) {
+ this.result = result;
+ }
+
+
+ public Status getHttpErrorStatus() {
+ return httpErrorStatus;
+ }
+
+ public void setHttpErrorStatus(Status httpErrorStatus) {
+ this.httpErrorStatus = httpErrorStatus;
+ }
+
+ public void setTimestamp(long timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public void setErrorMessage(String errorMessage) {
+ this.errorMessage = errorMessage;
+ }
+
+ public void setVertex(GraphEventVertex vertex) {
+ this.vertex = vertex;
+ }
+
+ public void setEdge(GraphEventEdge edge) {
+ this.edge = edge;
+ }
+
+ /**
+ * Unmarshalls this Vertex object into a JSON string.
+ *
+ * @return - A JSON format string representation of this Vertex.
+ */
+ public String toJson() {
+ return gson.toJson(this);
+ }
+
+ /**
+ * Marshalls the provided JSON string into a Vertex object.
+ *
+ * @param json - The JSON string to produce the Vertex from.
+ * @return - A Vertex object.
+ * @throws SpikeException
+ */
+ public static GraphEvent fromJson(String json) throws ChampServiceException {
+
+ try {
+
+ // Make sure that we were actually provided a non-empty string
+ // before we
+ // go any further.
+ if (json == null || json.isEmpty()) {
+ throw new ChampServiceException("Empty or null JSON string.", Status.BAD_REQUEST);
+ }
+
+ // Marshall the string into a Vertex object.
+ return gson.fromJson(json, GraphEvent.class);
+
+ } catch (Exception ex) {
+ throw new ChampServiceException("Unable to parse JSON string: ", Status.BAD_REQUEST);
+ }
+ }
+
+ @Override
+ public String toString() {
+
+ return toJson();
+ }
+
+ public String getObjectKey() {
+ if (this.getVertex() != null) {
+ return this.getVertex().getId();
+ } else if (this.getEdge() != null) {
+ return this.getEdge().getId();
+ }
+
+ return null;
+ }
+
+ public String getObjectType() {
+ if (this.getVertex() != null) {
+ return "vertex->" + this.getVertex().getType();
+ } else if (this.getEdge() != null) {
+ return "edge->" + this.getEdge().getType();
+ }
+
+ return null;
+ }
+
+ public static class Builder {
+
+ GraphEvent event = null;
+
+ public Builder(GraphEventOperation operation) {
+ event = new GraphEvent();
+ event.operation = operation;
+ }
+
+ public Builder vertex(GraphEventVertex vertex) {
+ event.vertex = vertex;
+ return this;
+ }
+
+ public Builder edge(GraphEventEdge edge) {
+ event.edge = edge;
+ return this;
+ }
+
+ public Builder result(GraphEventResult result) {
+ event.result = result;
+ return this;
+ }
+
+ public Builder errorMessage(String errorMessage) {
+ event.errorMessage = errorMessage;
+ return this;
+ }
+
+ public Builder httpErrorStatus(Status httpErrorStatus) {
+ event.httpErrorStatus = httpErrorStatus;
+ return this;
+ }
+
+ public GraphEvent build() {
+
+ event.timestamp = System.currentTimeMillis();
+ event.transactionId = java.util.UUID.randomUUID().toString();
+
+ return event;
+ }
+ }
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/event/GraphEventEdge.java b/champ-service/src/main/java/org/onap/champ/event/GraphEventEdge.java
new file mode 100644
index 0000000..1ab4804
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/event/GraphEventEdge.java
@@ -0,0 +1,221 @@
+/**
+ * ============LICENSE_START=======================================================
+ * Gizmo
+ * ================================================================================
+ * 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 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.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ */
+package org.onap.champ.event;
+
+import java.util.Map;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.onap.aai.champcore.model.ChampObject;
+import org.onap.aai.champcore.model.ChampRelationship;
+import org.onap.champ.exception.ChampServiceException;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.annotations.SerializedName;
+import com.google.gson.reflect.TypeToken;
+
+/**
+ * This class provides a generic representation of an Edge as provided by the
+ * graph data store.
+ */
+public class GraphEventEdge {
+
+ /**
+ * The unique identifier used to identify this edge in the graph data store.
+ */
+ @SerializedName("key")
+ private String id;
+
+ @SerializedName("schema-version")
+ private String modelVersion;
+
+ /**
+ * Type label assigned to this vertex.
+ */
+ private String type;
+
+ /**
+ * Source vertex for our edge.
+ */
+ private GraphEventVertex source;
+
+ /**
+ * Target vertex for our edge.
+ */
+ private GraphEventVertex target;
+
+ /**
+ * Map of all of the properties assigned to this vertex.
+ */
+ private JsonElement properties;
+
+ /**
+ * Marshaller/unmarshaller for converting to/from JSON.
+ */
+ private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();
+
+ public GraphEventEdge(String id, String modelVersion, String type, GraphEventVertex source,
+ GraphEventVertex target, JsonElement properties) {
+ this.id = id;
+ this.modelVersion = modelVersion;
+ this.type = type;
+ this.source = source;
+ this.target = target;
+ this.properties = properties;
+ }
+
+ public GraphEventEdge() {
+
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public GraphEventVertex getSource() {
+ return source;
+ }
+
+ public void setSource(GraphEventVertex source) {
+ this.source = source;
+ }
+
+ public GraphEventVertex getTarget() {
+ return target;
+ }
+
+ public void setTarget(GraphEventVertex target) {
+ this.target = target;
+ }
+
+ public JsonElement getProperties() {
+ return properties;
+ }
+
+ public void setProperties(JsonElement properties) {
+ this.properties = properties;
+ }
+
+ public String getModelVersion() {
+ return modelVersion;
+ }
+
+ public void setModelVersion(String modelVersion) {
+ this.modelVersion = modelVersion;
+ }
+
+ /**
+ * Unmarshalls this Edge object into a JSON string.
+ *
+ * @return - A JSON format string representation of this Edge.
+ */
+ public String toJson() {
+ return gson.toJson(this);
+ }
+
+ /**
+ * Marshalls the provided JSON string into a Edge object.
+ *
+ * @param json - The JSON string to produce the Edge from.
+ * @return - A Edge object.
+ * @throws SpikeException
+ */
+ public static GraphEventEdge fromJson(String json) throws ChampServiceException {
+
+ try {
+
+ // Make sure that we were actually provided a non-empty string
+ // before we
+ // go any further.
+ if (json == null || json.isEmpty()) {
+ throw new ChampServiceException("Unable to parse JSON string: ", Status.BAD_REQUEST);
+ }
+
+ // Marshall the string into an Edge object.
+ return gson.fromJson(json, GraphEventEdge.class);
+
+ } catch (Exception ex) {
+ throw new ChampServiceException("Unable to parse JSON string: ", Status.BAD_REQUEST);
+ }
+ }
+
+ public static GraphEventEdge fromChampRelationship(ChampRelationship edge, String modelVersion) {
+
+ java.lang.reflect.Type mapType = new TypeToken<Map<String, Object>>() {}.getType();
+ JsonObject props = gson.toJsonTree(edge.getProperties(), mapType).getAsJsonObject();
+
+ GraphEventEdge graphEventEdge = new GraphEventEdge(edge.getKey().orElse("").toString(), modelVersion,
+ edge.getType(), new GraphEventVertex(edge.getSource().getKey().orElse("").toString(), null,
+ edge.getSource().getType(), null), new GraphEventVertex(edge.getTarget().getKey().orElse("").toString(),
+ null, edge.getTarget().getType(), null), props);
+
+ return graphEventEdge;
+
+ }
+
+ public ChampRelationship toChampRelationship() {
+ ChampObject sourceChampObject=null;
+ ChampObject targetChampObject=null;
+ if (this.getSource() != null) {
+ sourceChampObject = new ChampObject.Builder(this.getSource().getType()).key(this.getSource().getId())
+ .build();
+ }
+ if (this.getTarget() != null) {
+ targetChampObject = new ChampObject.Builder(this.getTarget().getType()).key(this.getTarget().getId())
+ .build();
+ }
+
+ ChampRelationship.Builder builder = new ChampRelationship.Builder(sourceChampObject, targetChampObject, type);
+ if(this.getId()!=null && !this.getId().isEmpty()){
+ builder.key(this.getId());
+ }
+
+
+ if (this.getProperties() != null) {
+ java.lang.reflect.Type mapType = new TypeToken<Map<String, Object>>() {}.getType();
+ Map<String, Object> propertiesMap = gson.fromJson(this.getProperties(), mapType);
+ for (String key : propertiesMap.keySet()) {
+ builder.property(key, propertiesMap.get(key));
+ }
+ }
+ return builder.build();
+
+ }
+}
diff --git a/champ-service/src/main/java/org/onap/champ/event/GraphEventVertex.java b/champ-service/src/main/java/org/onap/champ/event/GraphEventVertex.java
new file mode 100644
index 0000000..553ba46
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/event/GraphEventVertex.java
@@ -0,0 +1,187 @@
+/**
+ * ============LICENSE_START=======================================================
+ * Gizmo
+ * ================================================================================
+ * 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 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.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ */
+package org.onap.champ.event;
+
+import java.util.Map;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.onap.aai.champcore.model.ChampObject;
+import org.onap.champ.exception.ChampServiceException;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.annotations.SerializedName;
+import com.google.gson.reflect.TypeToken;
+
+/**
+ * This class provides a generic representation of a Vertex as provided by the
+ * graph data store.
+ */
+public class GraphEventVertex {
+
+ /**
+ * The unique identifier used to identify this vertex in the graph data
+ * store.
+ */
+ @SerializedName("key")
+ private String id;
+
+ @SerializedName("schema-version")
+ private String modelVersion;
+
+ /**
+ * Type label assigned to this vertex.
+ */
+ private String type;
+
+ /**
+ * Map of all of the properties assigned to this vertex.
+ */
+ private JsonElement properties;
+
+ /**
+ * Marshaller/unmarshaller for converting to/from JSON.
+ */
+ private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();
+
+ public GraphEventVertex(String id, String modelVersion, String type, JsonElement properties) {
+ this.id = id;
+ this.modelVersion = modelVersion;
+ this.type = type;
+ this.properties = properties;
+ }
+
+ public GraphEventVertex() {
+
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+
+ public JsonElement getProperties() {
+ return properties;
+ }
+
+ public void setProperties(JsonElement properties) {
+ this.properties = properties;
+ }
+
+ public String getModelVersion() {
+ return modelVersion;
+ }
+
+ public void setModelVersion(String modelVersion) {
+ this.modelVersion = modelVersion;
+ }
+
+ /**
+ * Unmarshalls this Vertex object into a JSON string.
+ *
+ * @return - A JSON format string representation of this Vertex.
+ */
+ public String toJson() {
+ return gson.toJson(this);
+ }
+
+ /**
+ * Marshalls the provided JSON string into a Vertex object.
+ *
+ * @param json - The JSON string to produce the Vertex from.
+ * @return - A Vertex object.
+ * @throws SpikeException
+ */
+ public static GraphEventVertex fromJson(String json) throws ChampServiceException {
+
+ try {
+
+ // Make sure that we were actually provided a non-empty string
+ // before we
+ // go any further.
+ if (json == null || json.isEmpty()) {
+ throw new ChampServiceException("Empty or null JSON string.", Status.BAD_REQUEST);
+ }
+
+ // Marshall the string into a Vertex object.
+ return gson.fromJson(json, GraphEventVertex.class);
+
+ } catch (Exception ex) {
+ throw new ChampServiceException("Unable to parse JSON string: ", Status.BAD_REQUEST);
+ }
+ }
+
+ @Override
+ public String toString() {
+
+ return toJson();
+ }
+
+
+ public static GraphEventVertex fromChampObject(ChampObject champObject, String modelVersion) {
+
+ java.lang.reflect.Type mapType = new TypeToken<Map<String, Object>>() {}.getType();
+ JsonObject props = gson.toJsonTree(champObject.getProperties(), mapType).getAsJsonObject();
+ GraphEventVertex graphEventVertex = new GraphEventVertex(champObject.getKey().orElse("").toString(),
+ modelVersion, champObject.getType(), props);
+ return graphEventVertex;
+
+ }
+
+
+ public ChampObject toChampObject() {
+ ChampObject.Builder builder = new ChampObject.Builder(this.getType());
+ if(this.getId()!=null && !this.getId().isEmpty()){
+ builder.key(this.getId());
+ }
+
+ if (this.getProperties() != null) {
+ java.lang.reflect.Type mapType = new TypeToken<Map<String, Object>>() {}.getType();
+ Map<String, Object> propertiesMap = gson.fromJson(this.getProperties(), mapType);
+ for (String key : propertiesMap.keySet()) {
+ builder.property(key, propertiesMap.get(key));
+ }
+ }
+
+ return builder.build();
+
+ }
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/exception/ChampServiceException.java b/champ-service/src/main/java/org/onap/champ/exception/ChampServiceException.java
new file mode 100644
index 0000000..6e5e8c2
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/exception/ChampServiceException.java
@@ -0,0 +1,62 @@
+/**
+ * ============LICENSE_START=======================================================
+ * Gizmo
+ * ================================================================================
+ * 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 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.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.champ.exception;
+
+import javax.ws.rs.core.Response.Status;
+
+public class ChampServiceException extends Exception {
+
+ private static final long serialVersionUID = 8162385108397238865L;
+
+ private Status httpStatus;
+
+ public ChampServiceException() {
+ }
+
+ public ChampServiceException(String message, Status httpStatus) {
+ super(message);
+ this.setHttpStatus(httpStatus);
+ }
+
+ public ChampServiceException(Throwable cause) {
+ super(cause);
+ }
+
+ public ChampServiceException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ChampServiceException(String message, Throwable cause, boolean enableSuppression,
+ boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+
+ public Status getHttpStatus() {
+ return httpStatus;
+ }
+
+ public void setHttpStatus(Status httpStatus) {
+ this.httpStatus = httpStatus;
+ }
+}
diff --git a/champ-service/src/main/java/org/onap/champ/service/ChampDataService.java b/champ-service/src/main/java/org/onap/champ/service/ChampDataService.java
new file mode 100644
index 0000000..7826fa2
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/service/ChampDataService.java
@@ -0,0 +1,355 @@
+package org.onap.champ.service;
+
+import org.onap.aai.champcore.ChampGraph;
+import org.onap.aai.champcore.ChampTransaction;
+import org.onap.aai.champcore.exceptions.ChampMarshallingException;
+import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException;
+import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException;
+import org.onap.aai.champcore.exceptions.ChampSchemaViolationException;
+import org.onap.aai.champcore.exceptions.ChampTransactionException;
+import org.onap.aai.champcore.exceptions.ChampUnmarshallingException;
+import org.onap.aai.champcore.model.ChampElement;
+import org.onap.aai.champcore.model.ChampObject;
+import org.onap.aai.champcore.model.ChampRelationship;
+import org.onap.aai.champcore.model.fluent.object.ObjectBuildOrPropertiesStep;
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.eelf.LoggerFactory;
+import org.onap.champ.exception.ChampServiceException;
+import org.onap.champ.service.logging.ChampMsgs;
+import org.onap.champ.util.ChampProperties;
+import org.onap.champ.util.ChampServiceConstants;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import javax.ws.rs.core.Response.Status;
+
+public class ChampDataService {
+ private ChampUUIDService champUUIDService;
+
+ private ChampGraph graphImpl;
+ private ChampTransactionCache cache;
+ private static final String KEY_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_KEY_NAME);
+ private static final String SOT_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_SOT_NAME);
+ private static final String CREATED_TS_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_CREATED_TS_NAME);
+ private static final String LAST_MOD_TS_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_LAST_MOD_TS_NAME);
+ private Logger logger = LoggerFactory.getInstance().getLogger(ChampDataService.class);
+
+
+ public ChampDataService(ChampUUIDService champUUIDService, ChampGraph graphImpl, ChampTransactionCache cache) {
+
+ this.champUUIDService = champUUIDService;
+ this.graphImpl = graphImpl;
+ this.cache = cache;
+ }
+
+ public ChampObject getObject(String id, Optional<ChampTransaction> transaction) throws ChampServiceException {
+
+ Optional<ChampObject> retrieved = Optional.empty();
+ try {
+ retrieved = champUUIDService.getObjectbyUUID(id, transaction.orElse(null));
+ } catch (ChampUnmarshallingException | ChampTransactionException e) {
+ throw new ChampServiceException("Error: " + e.getMessage(), Status.INTERNAL_SERVER_ERROR);
+ }
+ if (retrieved.isPresent()) {
+ return (ChampObject) champUUIDService.populateUUIDKey(retrieved.get());
+ } else {
+ return null;
+ }
+ }
+
+ public ChampObject storeObject(ChampObject object, Optional<ChampTransaction> transaction)
+ throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException,
+ ChampTransactionException, ChampServiceException {
+
+ if (object.getProperty(KEY_NAME).isPresent() || object.getKey().isPresent()) {
+ throw new ChampServiceException(KEY_NAME + " can't be updated", Status.BAD_REQUEST);
+ }
+
+ champUUIDService.populateUUIDProperty(object, java.util.UUID.randomUUID().toString());
+ addTimestamps(object, null);
+ ChampObject created = graphImpl.storeObject(object, transaction);
+ return (ChampObject) champUUIDService.populateUUIDKey(created);
+ }
+
+ public ChampObject replaceObject(ChampObject object, String objectId, Optional<ChampTransaction> transaction)
+ throws ChampServiceException, ChampUnmarshallingException, ChampTransactionException, ChampMarshallingException,
+ ChampSchemaViolationException, ChampObjectNotExistsException {
+ if (object.getKey().isPresent() && (!object.getKeyValue().equals(objectId))) {
+ throw new ChampServiceException("Object Id in the URI doesn't match the body.", Status.BAD_REQUEST);
+ }
+
+ if (object.getProperty(KEY_NAME).isPresent() && !object.getProperty(KEY_NAME).get().toString().equals(objectId)) {
+ throw new ChampServiceException(KEY_NAME + " can't be updated", Status.BAD_REQUEST);
+ }
+
+ Optional<ChampObject> retrieved = champUUIDService.getObjectbyUUID(objectId, transaction.orElse(null));
+ if (!retrieved.isPresent()) {
+ throw new ChampServiceException(objectId + " not found", Status.NOT_FOUND);
+ }
+ ObjectBuildOrPropertiesStep payloadBuilder = ChampObject.create().from(object).withKey(retrieved.get().getKey().get())
+ .withProperty(KEY_NAME, objectId);
+ if (retrieved.get().getProperty(SOT_NAME).isPresent()){
+ payloadBuilder = payloadBuilder.withProperty(SOT_NAME, retrieved.get().getProperty(SOT_NAME).get());
+ }
+
+ if (object.getProperty(CREATED_TS_NAME).isPresent() && retrieved.get().getProperty(CREATED_TS_NAME).isPresent()) {
+ // the timestamps in object are parsed as strings regardless of how the input json is. Convert retrieved to string for easy comparison
+ if (!retrieved.get().getProperty(CREATED_TS_NAME).get().toString().equals(object.getProperty(CREATED_TS_NAME).get())) {
+ throw new ChampServiceException(CREATED_TS_NAME + " can't be updated", Status.BAD_REQUEST);
+ }
+ }
+
+ if (object.getProperty(LAST_MOD_TS_NAME).isPresent() && retrieved.get().getProperty(LAST_MOD_TS_NAME).isPresent()) {
+ if (!retrieved.get().getProperty(LAST_MOD_TS_NAME).get().toString().equals(object.getProperty(LAST_MOD_TS_NAME).get())) {
+ throw new ChampServiceException(LAST_MOD_TS_NAME + " can't be updated", Status.BAD_REQUEST);
+ }
+ }
+
+ ChampObject payload = payloadBuilder.build();
+ addTimestamps(payload, (Long)retrieved.get().getProperty(CREATED_TS_NAME).orElse(null));
+ ChampObject updated = graphImpl.replaceObject(payload, transaction);
+ return (ChampObject) champUUIDService.populateUUIDKey(updated);
+ }
+
+ public void deleteObject(String objectId, Optional<ChampTransaction> transaction) throws ChampServiceException,
+ ChampObjectNotExistsException, ChampTransactionException, ChampUnmarshallingException {
+ Optional<ChampObject> retrieved = champUUIDService.getObjectbyUUID(objectId, transaction.orElse(null));
+ if (!retrieved.isPresent()) {
+ throw new ChampServiceException(objectId + " not found", Status.NOT_FOUND);
+ }
+ Stream<ChampRelationship> relationships = graphImpl.retrieveRelationships(retrieved.get(), transaction);
+
+ if (relationships.count() > 0) {
+ throw new ChampServiceException("Attempt to delete vertex with id " + objectId + " which has incident edges.",
+ Status.BAD_REQUEST);
+ }
+ graphImpl.deleteObject(retrieved.get().getKey().get(), transaction);
+
+ }
+
+ public ChampRelationship storeRelationship(ChampRelationship r, Optional<ChampTransaction> transaction)
+ throws ChampMarshallingException, ChampObjectNotExistsException, ChampSchemaViolationException,
+ ChampRelationshipNotExistsException, ChampUnmarshallingException, ChampTransactionException,
+ ChampServiceException {
+
+ if (r.getSource() == null || !r.getSource().getKey().isPresent() || r.getTarget() == null
+ || !r.getTarget().getKey().isPresent()) {
+ logger.error(ChampMsgs.CHAMP_DATA_SERVICE_ERROR, "Source/Target Object key must be provided");
+ throw new ChampServiceException("Source/Target Object key must be provided", Status.BAD_REQUEST);
+ }
+
+ if (r.getProperty(KEY_NAME).isPresent() || r.getKey().isPresent()) {
+ logger.error(ChampMsgs.CHAMP_DATA_SERVICE_ERROR, "key or " + KEY_NAME + " not allowed while creating new Objects");
+ throw new ChampServiceException("key or " + KEY_NAME + " not allowed while creating new Objects", Status.BAD_REQUEST);
+
+ }
+
+ Optional<ChampObject> source = champUUIDService.getObjectbyUUID(r.getSource().getKey().get().toString(),
+ transaction.orElse(null));
+ Optional<ChampObject> target = champUUIDService.getObjectbyUUID(r.getTarget().getKey().get().toString(),
+ transaction.orElse(null));
+
+ if (!source.isPresent() || !target.isPresent()) {
+ logger.error(ChampMsgs.CHAMP_DATA_SERVICE_ERROR, "Source/Target object not found");
+ throw new ChampServiceException("Source/Target object not found", Status.BAD_REQUEST);
+ }
+
+ champUUIDService.populateUUIDProperty(r, java.util.UUID.randomUUID().toString());
+
+ ChampRelationship payload = new ChampRelationship.Builder(source.get(), target.get(), r.getType())
+ .properties(r.getProperties()).build();
+ addTimestamps(payload, null);
+ ChampRelationship created = graphImpl.storeRelationship(payload, transaction);
+ return (ChampRelationship) champUUIDService.populateUUIDKey(created);
+ }
+
+ public ChampRelationship updateRelationship(ChampRelationship r, String rId, Optional<ChampTransaction> transaction)
+ throws ChampServiceException, ChampUnmarshallingException, ChampTransactionException, ChampMarshallingException,
+ ChampSchemaViolationException, ChampRelationshipNotExistsException {
+ if (r.getKey().isPresent() && (!r.getKeyValue().equals(rId))) {
+
+ throw new ChampServiceException("Relationship Id in the URI \"" + rId + "\" doesn't match the URI in the body"
+ + " \"" + r.getKeyValue() + "\"", Status.BAD_REQUEST);
+
+ }
+
+ if (r.getProperty(KEY_NAME).isPresent() && !r.getProperty(KEY_NAME).get().toString().equals(rId)) {
+ throw new ChampServiceException(KEY_NAME + " can't be updated", Status.BAD_REQUEST);
+ }
+
+ Optional<ChampRelationship> retrieved = champUUIDService.getRelationshipbyUUID(rId, transaction.orElse(null));
+ if (!retrieved.isPresent()) {
+ throw new ChampServiceException(rId + " not found", Status.NOT_FOUND);
+ }
+ // check if key is present or if it equals the key that is in the URI
+ if (r.getSource() == null || !r.getSource().getKey().isPresent() || r.getTarget() == null
+ || !r.getTarget().getKey().isPresent()) {
+ throw new ChampServiceException("Source/Target Object key must be provided", Status.BAD_REQUEST);
+ }
+ ChampObject source = retrieved.get().getSource();
+ ChampObject target = retrieved.get().getTarget();
+
+ if (!source.getProperty(KEY_NAME).get().toString().equals(r.getSource().getKey().get().toString())
+ || !target.getProperty(KEY_NAME).get().toString().equals(r.getTarget().getKey().get().toString())) {
+ throw new ChampServiceException("Source/Target cannot be updated", Status.BAD_REQUEST);
+ }
+
+ if (r.getProperty(CREATED_TS_NAME).isPresent() && retrieved.get().getProperty(CREATED_TS_NAME).isPresent()) {
+ if (!retrieved.get().getProperty(CREATED_TS_NAME).get().toString().equals(r.getProperty(CREATED_TS_NAME).get())) {
+ throw new ChampServiceException(CREATED_TS_NAME + " can't be updated", Status.BAD_REQUEST);
+ }
+ }
+
+ if (r.getProperty(LAST_MOD_TS_NAME).isPresent() && retrieved.get().getProperty(LAST_MOD_TS_NAME).isPresent()) {
+ if (!retrieved.get().getProperty(LAST_MOD_TS_NAME).get().toString().equals(r.getProperty(LAST_MOD_TS_NAME).get())) {
+ throw new ChampServiceException(LAST_MOD_TS_NAME + " can't be updated", Status.BAD_REQUEST);
+ }
+ }
+
+ ChampRelationship payload = new ChampRelationship.Builder(source, target, r.getType())
+ .key(retrieved.get().getKey().get()).properties(r.getProperties()).property(KEY_NAME, rId).build();
+ addTimestamps(payload, (Long)retrieved.get().getProperty(CREATED_TS_NAME).orElse(null));
+ ChampRelationship updated = graphImpl.replaceRelationship(payload, transaction);
+ return (ChampRelationship) champUUIDService.populateUUIDKey(updated);
+ }
+
+ public void deleteRelationship(String relationshipId, Optional<ChampTransaction> transaction)
+ throws ChampServiceException, ChampRelationshipNotExistsException, ChampTransactionException,
+ ChampUnmarshallingException {
+ Optional<ChampRelationship> retrieved = champUUIDService.getRelationshipbyUUID(relationshipId,
+ transaction.orElse(null));
+ if (!retrieved.isPresent()) {
+ throw new ChampServiceException(relationshipId + " not found", Status.NOT_FOUND);
+ }
+
+ graphImpl.deleteRelationship(retrieved.get(), transaction);
+
+ }
+
+
+ public List<ChampRelationship> getRelationshipsByObject(String objectId, Optional<ChampTransaction> transaction)
+ throws ChampServiceException {
+ try {
+ Optional<ChampObject> retrievedObject = champUUIDService.getObjectbyUUID(objectId, transaction.orElse(null));
+ if (!retrievedObject.isPresent()) {
+ throw new ChampServiceException(objectId + " not found", Status.NOT_FOUND);
+ }
+ List<ChampRelationship> relations = new ArrayList<ChampRelationship>();
+
+ Stream<ChampRelationship> retrieved = graphImpl.retrieveRelationships(retrievedObject.get(), transaction);
+ relations = champUUIDService.populateUUIDKey(retrieved.collect(Collectors.toList()));
+ return relations;
+ } catch (ChampObjectNotExistsException e) {
+ throw new ChampServiceException(" obj not found", Status.NOT_FOUND);
+ } catch (ChampUnmarshallingException | ChampTransactionException e) {
+ throw new ChampServiceException("Internal Error", Status.INTERNAL_SERVER_ERROR);
+ }
+
+ }
+
+ /**
+ * Gets the ChampObjects that pass filter
+ * @param filter key/value pairs that must be present in the returned objects
+ * @param properties properties that will show up in the object
+ * @return
+ * @throws ChampServiceException
+ */
+ public List<ChampObject> queryObjects(Map<String, Object> filter, HashSet<String> properties) throws ChampServiceException {
+ try {
+
+ Stream<ChampObject> retrieved = graphImpl.queryObjects(filter);
+ List<ChampObject> objects = champUUIDService.populateUUIDKey(retrieved.collect(Collectors.toList()));
+
+ if (!properties.contains("all")) {
+ for (ChampObject champObject : objects) {
+ champObject.dropProperties(properties);
+ }
+ }
+
+ return objects;
+ } catch (ChampTransactionException e) {
+ throw new ChampServiceException("Internal Error", Status.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ public List<ChampRelationship> queryRelationships(Map<String, Object> filter) throws ChampServiceException {
+ try {
+ List<ChampRelationship> relations = new ArrayList<ChampRelationship>();
+ Stream<ChampRelationship> retrieved;
+
+ retrieved = graphImpl.queryRelationships(filter);
+
+ relations = champUUIDService.populateUUIDKey(retrieved.collect(Collectors.toList()));
+ return relations;
+ } catch (ChampTransactionException e) {
+ throw new ChampServiceException("Internal Error", Status.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ public ChampRelationship getRelationship(String id, Optional<ChampTransaction> transaction)
+ throws ChampServiceException {
+
+ Optional<ChampRelationship> retrieved = Optional.empty();
+ try {
+ retrieved = champUUIDService.getRelationshipbyUUID(id, transaction.orElse(null));
+ } catch (ChampUnmarshallingException | ChampTransactionException e) {
+ throw new ChampServiceException("Error: " + e.getMessage(), Status.INTERNAL_SERVER_ERROR);
+ }
+ if (retrieved.isPresent()) {
+ return (ChampRelationship) champUUIDService.populateUUIDKey(retrieved.get());
+ } else {
+ return null;
+ }
+ }
+
+ public String openTransaction() {
+ ChampTransaction transaction = graphImpl.openTransaction();
+ String transacId = transaction.id();
+ cache.put(transacId, transaction);
+ return transacId;
+
+ }
+
+ public void commitTransaction(String tId) throws ChampServiceException, ChampTransactionException {
+ ChampTransaction transaction = cache.get(tId);
+ if (transaction == null) {
+ throw new ChampServiceException("Transaction Not found: " + tId, Status.NOT_FOUND);
+ }
+ graphImpl.commitTransaction(transaction);
+ cache.invalidate(tId);
+ cache.invalidate(transaction.id());
+
+ }
+
+ public void rollbackTransaction(String tId) throws ChampServiceException, ChampTransactionException {
+ ChampTransaction transaction = cache.get(tId);
+ if (transaction == null) {
+ throw new ChampServiceException("Transaction Not found: " + tId, Status.NOT_FOUND);
+ }
+ graphImpl.rollbackTransaction(transaction);
+ cache.invalidate(tId);
+ cache.invalidate(transaction.id());
+
+ }
+
+ public ChampTransaction getTransaction(String id) {
+ return cache.get(id);
+ }
+
+ private void addTimestamps(ChampElement e, Long oldCreated) {
+ Long timestamp = System.currentTimeMillis();
+
+ if (oldCreated == null) {
+ e.getProperties().put(CREATED_TS_NAME, timestamp);
+ } else {
+ e.getProperties().put(CREATED_TS_NAME, oldCreated);
+ }
+
+ e.getProperties().put(LAST_MOD_TS_NAME, timestamp);
+ }
+}
diff --git a/champ-service/src/main/java/org/onap/champ/service/ChampThreadFactory.java b/champ-service/src/main/java/org/onap/champ/service/ChampThreadFactory.java
new file mode 100644
index 0000000..25fe65e
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/service/ChampThreadFactory.java
@@ -0,0 +1,47 @@
+/**
+ * ============LICENSE_START=======================================================
+ * Gizmo
+ * ================================================================================
+ * 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 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.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ */
+package org.onap.champ.service;
+
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Thread factory for workers.
+ */
+public class ChampThreadFactory implements ThreadFactory {
+
+ private AtomicInteger threadNumber = new AtomicInteger(1);
+
+ private String threadPrefix;
+
+
+ public ChampThreadFactory(String threadPrefix) {
+ this.threadPrefix = threadPrefix;
+ }
+
+ public Thread newThread(Runnable runnable) {
+ return new Thread(runnable, threadPrefix + "-" + threadNumber.getAndIncrement());
+ }
+}
diff --git a/champ-service/src/main/java/org/onap/champ/service/ChampTransactionCache.java b/champ-service/src/main/java/org/onap/champ/service/ChampTransactionCache.java
new file mode 100644
index 0000000..bb95147
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/service/ChampTransactionCache.java
@@ -0,0 +1,77 @@
+
+package org.onap.champ.service;
+
+import java.util.concurrent.TimeUnit;
+
+import org.onap.aai.champcore.ChampGraph;
+import org.onap.aai.champcore.ChampTransaction;
+import org.onap.aai.champcore.exceptions.ChampTransactionException;
+import org.onap.champ.service.logging.ChampMsgs;
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.eelf.LoggerFactory;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.RemovalCause;
+import com.google.common.cache.RemovalListener;
+import com.google.common.cache.RemovalNotification;
+
+/**
+ * Self expiring Cache to hold request transactionIds . Events are expired
+ * automatically after configured interval
+ */
+public class ChampTransactionCache {
+ private static Logger logger = LoggerFactory.getInstance().getLogger(ChampTransactionCache
+ .class.getName());
+
+
+ private ChampGraph graphImpl;
+ private Cache<String, ChampTransaction> cache;
+
+
+
+ public ChampTransactionCache(long txTimeOutInSec,ChampGraph graphImpl) {
+ CacheBuilder builder = CacheBuilder.newBuilder().expireAfterWrite(txTimeOutInSec, TimeUnit.SECONDS)
+ .removalListener(new RemovalListener() {
+
+ public void onRemoval(RemovalNotification notification) {
+ if(notification.getCause()==RemovalCause.EXPIRED){
+ logger.info(ChampMsgs.CHAMP_TX_CACHE, "Following transaction: "+notification.getKey()+" is being evicted from cache due to timeout of " + txTimeOutInSec+" seconds");
+ try {
+ graphImpl.rollbackTransaction((ChampTransaction) notification.getValue());
+ logger.info(ChampMsgs.CHAMP_TX_CACHE, "Transaction rolledback successfully :" + notification.getKey());
+ } catch (ChampTransactionException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+ });
+ cache = builder.build();
+
+ this.graphImpl = graphImpl;
+
+ }
+
+ public void put(String txId, ChampTransaction tx) {
+ cache.put(txId, tx);
+
+ }
+
+ public ChampTransaction get(String txId) {
+ if (txId==null)
+ return null;
+ if(cache.getIfPresent(txId)==null){
+ //cleanup cache so that removalListener is called
+ cache.cleanUp();
+ }
+ return cache.getIfPresent(txId);
+ }
+
+ public void invalidate(String txId) {
+ cache.invalidate(txId);
+ }
+
+
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/service/ChampUUIDService.java b/champ-service/src/main/java/org/onap/champ/service/ChampUUIDService.java
new file mode 100644
index 0000000..39c775b
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/service/ChampUUIDService.java
@@ -0,0 +1,115 @@
+package org.onap.champ.service;
+
+import org.onap.aai.champcore.ChampGraph;
+import org.onap.aai.champcore.ChampTransaction;
+import org.onap.aai.champcore.exceptions.ChampTransactionException;
+import org.onap.aai.champcore.exceptions.ChampUnmarshallingException;
+import org.onap.aai.champcore.model.ChampElement;
+import org.onap.aai.champcore.model.ChampObject;
+import org.onap.aai.champcore.model.ChampRelationship;
+import org.onap.champ.exception.ChampServiceException;
+import org.onap.champ.util.ChampProperties;
+import org.onap.champ.util.ChampServiceConstants;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+public class ChampUUIDService {
+ private ChampGraph graphImpl;
+ private static final String KEY_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_KEY_NAME);
+
+
+ public ChampUUIDService(ChampGraph graphImpl) {
+ this.graphImpl = graphImpl;
+ }
+
+ public List populateUUIDKey(List<ChampElement> elements) {
+ {
+ List response = new ArrayList();
+ for (ChampElement e : elements) {
+ ChampElement item = populateUUIDKey(e);
+ if (item != null) {
+ response.add(item);
+ }
+ }
+ return response;
+ }
+
+ }
+
+ public ChampElement populateUUIDKey(ChampElement e) {
+ {
+ ChampElement response = null;
+
+ if (e.isObject()) {
+ if (e.asObject().getProperty(KEY_NAME).isPresent()) {
+ response = (ChampObject.create().from(e.asObject())
+ .withKey(e.asObject().getProperty(KEY_NAME).get().toString()).build());
+ }
+ } else {
+ if (e.asRelationship().getProperty(KEY_NAME).isPresent()
+ && e.asRelationship().getSource().getProperty(KEY_NAME).isPresent()
+ && e.asRelationship().getTarget().getProperty(KEY_NAME).isPresent()) {
+ ChampObject source = ChampObject.create().from(e.asRelationship().getSource())
+ .withKey(e.asRelationship().getSource().getProperty(KEY_NAME).get().toString()).build();
+ ChampObject target = ChampObject.create().from(e.asRelationship().getTarget())
+ .withKey(e.asRelationship().getTarget().getProperty(KEY_NAME).get().toString()).build();
+ ChampRelationship rel = new ChampRelationship.Builder(source, target, e.asRelationship().getType())
+ .key(e.asRelationship().getProperty(KEY_NAME).get().toString())
+ .properties(e.asRelationship().getProperties()).build();
+ response = rel;
+ }
+
+ }
+
+ return response;
+ }
+
+ }
+
+ public void populateUUIDProperty(ChampElement e, String uuid) {
+ e.getProperties().put(KEY_NAME, uuid);
+ }
+
+
+ public Optional<ChampObject> getObjectbyUUID(String uuid, ChampTransaction transaction)
+ throws ChampUnmarshallingException, ChampTransactionException, ChampServiceException {
+ Optional<ChampObject> response = Optional.empty();
+
+ Stream<ChampObject> s;
+ Map<String, Object> filter = new HashMap<>();
+ filter.put(KEY_NAME, uuid);
+
+ s = graphImpl.queryObjects(filter, Optional.ofNullable(transaction));
+ Object[] objs = s.toArray();
+ if (objs.length == 0) {
+ return response;
+ }
+ response = graphImpl.retrieveObject(((ChampObject) objs[0]).getKey().get(), Optional.ofNullable(transaction));
+ return response;
+ }
+
+ public Optional<ChampRelationship> getRelationshipbyUUID(String uuid, ChampTransaction transaction)
+ throws ChampUnmarshallingException, ChampTransactionException, ChampServiceException {
+ Optional<ChampRelationship> response = Optional.empty();
+
+
+ Stream<ChampRelationship> s;
+ Map<String, Object> filter = new HashMap<>();
+ filter.put(KEY_NAME, uuid);
+
+ s = graphImpl.queryRelationships(filter, Optional.ofNullable(transaction));
+ Object[] objs = s.toArray();
+ if (objs.length == 0) {
+ return response;
+ }
+ response = graphImpl.retrieveRelationship(((ChampRelationship) objs[0]).getKey().get(),
+ Optional.ofNullable(transaction));
+ return response;
+ }
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/service/EchoService.java b/champ-service/src/main/java/org/onap/champ/service/EchoService.java
new file mode 100644
index 0000000..c8236b1
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/service/EchoService.java
@@ -0,0 +1,54 @@
+/**
+ * ============LICENSE_START==========================================
+ * org.onap.aai
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ===================================================================
+ * 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.
+ * ============LICENSE_END============================================
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.champ.service;
+
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.eelf.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
+
+
+public class EchoService {
+
+ private static Logger logger = LoggerFactory.getInstance()
+ .getLogger(EchoService.class.getName());
+ private static Logger auditLogger = LoggerFactory.getInstance()
+ .getAuditLogger(EchoService.class.getName());
+
+ @GET
+ @Path("echo/{input}")
+ @Produces("text/plain")
+ public String ping(@PathParam("input") String input,
+ @Context HttpHeaders headers,
+ @Context UriInfo info,
+ @Context HttpServletRequest req) {
+
+ return "Hello, " + input + ".";
+ }
+} \ No newline at end of file
diff --git a/champ-service/src/main/java/org/onap/champ/service/logging/ChampMsgs.java b/champ-service/src/main/java/org/onap/champ/service/logging/ChampMsgs.java
new file mode 100644
index 0000000..2ddbff4
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/service/logging/ChampMsgs.java
@@ -0,0 +1,130 @@
+/**
+ * ============LICENSE_START==========================================
+ * org.onap.aai
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ===================================================================
+ * 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.
+ * ============LICENSE_END============================================
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.champ.service.logging;
+
+import com.att.eelf.i18n.EELFResourceManager;
+import org.onap.aai.cl.eelf.LogMessageEnum;
+
+public enum ChampMsgs implements LogMessageEnum {
+
+ /**
+ * Received request {0} {1} from {2}. Sending response: {3}
+ *
+ * <p>
+ * Arguments: {0} = operation {1} = target URL {2} = source {3} = response
+ * code
+ */
+ PROCESS_REST_REQUEST,
+ /**
+ * Processed event {0}. Result: {1}.
+ *
+ * Arguments: {0} = event {1} = result
+ */
+ PROCESS_EVENT,
+
+ /**
+ * Query: {0}
+ * Arguments: {0} = query
+ */
+ QUERY,
+
+ /**
+ * Arguments: {0} = transactionID, {1} = request
+ */
+ INCOMING_REQUEST,
+
+ /**
+ * Arguments: {0} = HTTP request type, {1} = time to process in milliseconds
+ */
+ PROCESSED_REQUEST,
+
+ /**
+ * Arguments: {0} = transaction ID
+ */
+ TRANSACTION_NOT_FOUND,
+
+ /**
+ * Arguments: {0} = request, {1} = Error
+ */
+ BAD_REQUEST,
+
+ /**
+ * Arguments: {0} = Info
+ */
+ CHAMP_TX_CACHE,
+
+ /**
+ * Any info log related to CHAMP_ASYNC_REQUEST_PROCESSOR_INFO
+ *
+ * <p>Arguments:
+ * {0} - Info.
+ */
+ CHAMP_ASYNC_REQUEST_PROCESSOR_INFO,
+ CHAMP_ASYNC_REQUEST_PROCESSOR_WARN,
+
+ /**
+ * Any error log related to CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR
+ *
+ * <p>Arguments:
+ * {0} - Error.
+ */
+ CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR,
+
+ /**
+ * Any info log related to CHAMP_DATA_SERVICE_INFO
+ *
+ * <p>Arguments:
+ * {0} - Info.
+ */
+ CHAMP_DATA_SERVICE_INFO,
+
+ /**
+ * Any error log related to CHAMP_DATA_SERVICE_INFO
+ *
+ * <p>Arguments:
+ * {0} - Error.
+ */
+ CHAMP_DATA_SERVICE_ERROR,
+
+
+ /**
+ * Any info log related to CHAMP_ASYNC_RESPONSE_PUBLISHER_INFO
+ *
+ * <p>Arguments:
+ * {0} - Info.
+ */
+ CHAMP_ASYNC_RESPONSE_PUBLISHER_INFO,
+
+ /**
+ * Any error log related to CHAMP_ASYNC_RESPONSE_PUBLISHER_ERROR
+ *
+ * <p>Arguments:
+ * {0} - Error.
+ */
+ CHAMP_ASYNC_RESPONSE_PUBLISHER_ERROR;
+ /**
+ * Static initializer to ensure the resource bundles for this class are loaded...
+ */
+ static {
+ EELFResourceManager.loadMessageBundle("logging/ChampMsgs");
+ }
+}
diff --git a/champ-service/src/main/java/org/onap/champ/service/logging/LoggingUtil.java b/champ-service/src/main/java/org/onap/champ/service/logging/LoggingUtil.java
new file mode 100644
index 0000000..b7f0e77
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/service/logging/LoggingUtil.java
@@ -0,0 +1,92 @@
+/**
+ * ============LICENSE_START=======================================================
+ * Gizmo
+ * ================================================================================
+ * 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 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.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.champ.service.logging;
+
+import org.onap.aai.cl.api.LogFields;
+import org.onap.aai.cl.api.LogLine;
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.mdc.MdcContext;
+
+import org.slf4j.MDC;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+
+public class LoggingUtil {
+ /**
+ * Initializes mdc context.
+ */
+ public static void initMdcContext(HttpServletRequest httpReq, HttpHeaders headers) {
+ String fromIp = httpReq.getRemoteAddr();
+ String fromAppId = "";
+ String transId = null;
+
+ if (headers.getRequestHeaders().getFirst("X-FromAppId") != null) {
+ fromAppId = headers.getRequestHeaders().getFirst("X-FromAppId");
+ }
+
+ if ((headers.getRequestHeaders().getFirst("X-TransactionId") == null)
+ || headers.getRequestHeaders().getFirst("X-TransactionId").isEmpty()) {
+ transId = java.util.UUID.randomUUID().toString();
+ } else {
+ transId = headers.getRequestHeaders().getFirst("X-TransactionId");
+ }
+
+ MdcContext.initialize(transId, "ChampService", "", fromAppId, fromIp);
+ }
+
+ /**
+ * Logs the rest request.
+ */
+ public static void logRestRequest(Logger logger, Logger auditLogger, HttpServletRequest req, Response response) {
+ String respStatusString = "";
+ if (Response.Status.fromStatusCode(response.getStatus()) != null) {
+ respStatusString = Response.Status.fromStatusCode(response.getStatus()).toString();
+ }
+
+ // Generate error log
+ logger.info(ChampMsgs.PROCESS_REST_REQUEST, req.getMethod(), req.getRequestURL().toString(),
+ req.getRemoteHost(), Integer.toString(response.getStatus()));
+
+ // Generate audit log.
+ auditLogger.info(ChampMsgs.PROCESS_REST_REQUEST,
+ new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, response.getStatus())
+ .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, respStatusString),
+ (req != null) ? req.getMethod() : "Unknown", (req != null) ? req.getRequestURL().toString() : "Unknown",
+ (req != null) ? req.getRemoteHost() : "Unknown", Integer.toString(response.getStatus()) + " payload: "
+ + (response.getEntity() == null ? "" : response.getEntity().toString()));
+ MDC.clear();
+ }
+
+ public static void logInternalError(Logger logger, Exception ex) {
+ StringWriter writer = new StringWriter();
+ PrintWriter printWriter = new PrintWriter(writer);
+ ex.printStackTrace(printWriter);
+ logger.error(ChampMsgs.CHAMP_DATA_SERVICE_ERROR, "Internal error: " + ex.getMessage() + "\n" + writer.toString());
+ }
+}
diff --git a/champ-service/src/main/java/org/onap/champ/util/ChampProperties.java b/champ-service/src/main/java/org/onap/champ/util/ChampProperties.java
new file mode 100644
index 0000000..178da97
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/util/ChampProperties.java
@@ -0,0 +1,53 @@
+package org.onap.champ.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+public class ChampProperties {
+
+ private static Properties properties;
+
+ static {
+ properties = new Properties();
+ File file = new File(ChampServiceConstants.CHAMP_CONFIG_FILE);
+ try {
+ properties.load(new FileInputStream(file));
+ } catch (IOException e) {
+ e.printStackTrace();
+ Runtime.getRuntime().halt(1);
+ }
+ }
+
+ public static String get(String key) {
+ return properties.getProperty(key);
+ }
+
+ public static String get(String key, String defaultValue) {
+ return properties.getProperty(key, defaultValue);
+ }
+
+ public static void put(String key, String value) {
+ properties.setProperty(key, value);
+ FileOutputStream fileOut = null;
+ try {
+ fileOut = new FileOutputStream(new File(ChampServiceConstants.CHAMP_CONFIG_FILE));
+ properties.store(fileOut, "Added property: " + key);
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+
+ try {
+ fileOut.close();
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ }
+
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/util/ChampServiceConstants.java b/champ-service/src/main/java/org/onap/champ/util/ChampServiceConstants.java
new file mode 100644
index 0000000..94a9972
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/util/ChampServiceConstants.java
@@ -0,0 +1,14 @@
+package org.onap.champ.util;
+
+public class ChampServiceConstants {
+ public static final String CHAMP_FILESEP = (System.getProperty("file.separator") == null) ? "/"
+ : System.getProperty("file.separator");
+
+ public static final String CHAMP_SPECIFIC_CONFIG = System.getProperty("CONFIG_HOME") + CHAMP_FILESEP;
+ public static final String CHAMP_CONFIG_FILE = CHAMP_SPECIFIC_CONFIG + "champ-api.properties";
+ public static final String CHAMP_KEY_NAME = "keyName";
+ public static final String CHAMP_SOT_NAME = "sourceOfTruthName";
+ public static final String CHAMP_CREATED_TS_NAME = "createdTsName";
+ public static final String CHAMP_LAST_MOD_TS_NAME = "lastModTsName";
+ public static final String CHAMP_COLLECTION_PROPERTIES_KEY = "collectionPropertiesKey";
+} \ No newline at end of file
diff --git a/champ-service/src/main/resources/META-INF/services/javax.ws.rs.client.ClientBuilder b/champ-service/src/main/resources/META-INF/services/javax.ws.rs.client.ClientBuilder
new file mode 100644
index 0000000..48b9fa5
--- /dev/null
+++ b/champ-service/src/main/resources/META-INF/services/javax.ws.rs.client.ClientBuilder
@@ -0,0 +1 @@
+org.glassfish.jersey.client.JerseyClientBuilder \ No newline at end of file
diff --git a/champ-service/src/main/resources/logging/ChampMsgs.properties b/champ-service/src/main/resources/logging/ChampMsgs.properties
new file mode 100644
index 0000000..776b178
--- /dev/null
+++ b/champ-service/src/main/resources/logging/ChampMsgs.properties
@@ -0,0 +1,78 @@
+#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_REST_REQUEST=\
+ CS0005I|\
+ Received request {0} {1} from {2}. Sending response: {3}|\
+ None. Received the specified REST request from the source specified.|\
+ Received the specified REST request from the source specified, and the CHAMP service sent the specified response.
+
+PROCESS_EVENT=\
+ CS0001I|\
+ Processed event {0} Result: {1}
+
+QUERY=\
+ CS0002I|\
+ Query Recieved: {0}
+
+INCOMING_REQUEST=\
+ CS0003I|\
+ Incoming Request with Transaction ID {0} and request {1}
+
+PROCESSED_REQUEST=\
+ CS0004I|\
+ Processed Champ {0} request in {1} ms
+
+TRANSACTION_NOT_FOUND=\
+ CS0001E|\
+ Transaction with ID {0} was not found.
+
+BAD_REQUEST=\
+ CS0002E|\
+ Bad Request {0}. Error is {1}
+
+CHAMP_TX_CACHE=\
+ CS0006I|\
+ ChampTransactionCache: {0}
+CHAMP_DATA_SERVICE_ERROR=\
+ CRD0510E|\
+ ChampDataService Error: {0}
+CHAMP_DATA_CACHE_INFO=\
+ CRD0511I|\
+ ChampDataService: {0}
+CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR=\
+ CRD0512E|\
+ ChampAsyncRequestProcessor Error: {0}
+CHAMP_ASYNC_REQUEST_PROCESSOR_WARN=\
+ CRD0514E|\
+ ChampAsyncRequestProcessor Warning: {0}
+CHAMP_ASYNC_REQUEST_PROCESSOR_INFO=\
+ CRD0512I|\
+ ChampAsyncRequestProcessor: {0}
+CHAMP_ASYNC_RESPONSE_PUBLISHER_ERROR=\
+ CRD0513E|\
+ ChampAsyncRequestProcessor Error: {0}
+CHAMP_ASYNC_RESPONSE_PUBLISHER_INFO=\
+ CRD0513I|\
+ ChampAsyncRequestProcessor: {0}
+
+
+
diff --git a/champ-service/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context b/champ-service/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context
new file mode 100644
index 0000000..8514196
--- /dev/null
+++ b/champ-service/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context
@@ -0,0 +1 @@
+{"context":{"contextClass":"ajsc.Context","contextId":"__module_ajsc_namespace_name__:__module_ajsc_namespace_version__","contextName":"__module_ajsc_namespace_name__","contextVersion":"__module_ajsc_namespace_version__","description":"__module_ajsc_namespace_name__ Context"}} \ No newline at end of file
diff --git a/champ-service/src/main/runtime/context/default#0.context b/champ-service/src/main/runtime/context/default#0.context
new file mode 100644
index 0000000..d1b5ab4
--- /dev/null
+++ b/champ-service/src/main/runtime/context/default#0.context
@@ -0,0 +1 @@
+{"context":{"contextClass":"ajsc.Context","contextId":"default:0","contextName":"default","contextVersion":"0","description":"Default Context"}} \ No newline at end of file
diff --git a/champ-service/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json b/champ-service/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json
new file mode 100644
index 0000000..d0954cf
--- /dev/null
+++ b/champ-service/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json
@@ -0,0 +1 @@
+{"deploymentPackage":{"Class":"ajsc.DeploymentPackage","Id":"__module.ajsc.namespace.name__:__module_ajsc_namespace_version__","namespace":"__module_ajsc_namespace_name__","namespaceVersion":"__module_ajsc_namespace_version__","description":"__module_ajsc_namespace_name__ __module_ajsc_namespace_version__ - default description","userId":"ajsc"}} \ No newline at end of file
diff --git a/champ-service/src/main/runtime/shiroRole/ajscadmin.json b/champ-service/src/main/runtime/shiroRole/ajscadmin.json
new file mode 100644
index 0000000..f5e981e
--- /dev/null
+++ b/champ-service/src/main/runtime/shiroRole/ajscadmin.json
@@ -0,0 +1 @@
+{"shiroRoleClass":"ajsc.auth.ShiroRole","shiroRoleId":"ajscadmin","name":"ajscadmin","permissions":"[ajscadmin:*, ajsc:*]"} \ No newline at end of file
diff --git a/champ-service/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json b/champ-service/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json
new file mode 100644
index 0000000..2dae9f5
--- /dev/null
+++ b/champ-service/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json
@@ -0,0 +1 @@
+{"shiroRoleClass":"ajsc.auth.ShiroRole","shiroRoleId":"contextadmin:__module_ajsc_namespace_name__","name":"contextadmin:__module_ajsc_namespace_name__","permissions":"[]"} \ No newline at end of file
diff --git a/champ-service/src/main/runtime/shiroRole/contextadmin#default.json b/champ-service/src/main/runtime/shiroRole/contextadmin#default.json
new file mode 100644
index 0000000..5de814e
--- /dev/null
+++ b/champ-service/src/main/runtime/shiroRole/contextadmin#default.json
@@ -0,0 +1 @@
+{"shiroRoleClass":"ajsc.auth.ShiroRole","shiroRoleId":"contextadmin:default","name":"contextadmin:default","permissions":"[]"} \ No newline at end of file
diff --git a/champ-service/src/main/runtime/shiroUser/ajsc.json b/champ-service/src/main/runtime/shiroUser/ajsc.json
new file mode 100644
index 0000000..f4c7855
--- /dev/null
+++ b/champ-service/src/main/runtime/shiroUser/ajsc.json
@@ -0,0 +1 @@
+{"shiroUserClass":"ajsc.auth.ShiroUser","shiroUserId":"ajsc","passwordHash":"9471697417008c880720ba54c6038791ad7e98f3b88136fe34f4d31a462dd27a","permissions":"[*:*]","username":"ajsc"} \ No newline at end of file
diff --git a/champ-service/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json b/champ-service/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json
new file mode 100644
index 0000000..cb8d483
--- /dev/null
+++ b/champ-service/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json
@@ -0,0 +1 @@
+{"shiroUserRoleClass":"ajsc.auth.ShiroUserRole","shiroUserRoleId":"ajsc:ajscadmin","roleId":"ajscadmin","userId":"ajsc"} \ No newline at end of file
diff --git a/champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json b/champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json
new file mode 100644
index 0000000..95d2361
--- /dev/null
+++ b/champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json
@@ -0,0 +1 @@
+{"shiroUserRoleClass":"ajsc.auth.ShiroUserRole","shiroUserRoleId":"ajsc:contextadmin:__module_ajsc_namespace_name__","roleId":"contextadmin:__module_ajsc_namespace_name__","userId":"ajsc"} \ No newline at end of file
diff --git a/champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json b/champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json
new file mode 100644
index 0000000..2bd5063
--- /dev/null
+++ b/champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json
@@ -0,0 +1 @@
+{"shiroUserRoleClass":"ajsc.auth.ShiroUserRole","shiroUserRoleId":"ajsc:contextadmin:default","roleId":"contextadmin:default","userId":"ajsc"} \ No newline at end of file