diff options
author | michaere <michaere@amdocs.com> | 2018-03-05 16:33:32 +0000 |
---|---|---|
committer | michaere <michaere@amdocs.com> | 2018-03-07 11:17:22 +0000 |
commit | c74f7b13b573386e70c10721fc391624ee792ed6 (patch) | |
tree | b44995474ff938b4b03c9b234f95b71bc75d6b79 /champ-service | |
parent | 9fc28cff11a4b570618c0f533ce9de6209a5dd0c (diff) |
Port champ-microservice project restructure
Includes project restructure and introduction of a parent pom. The
original source folder and core functionality is now held within champ-lib, with champ-service
forming the ajsc microservice from which it injects champ-lib core
functionality.
Issue-ID: AAI-813
Change-Id: I2ce0c4a70e485665276e7955572de23969deb706
Signed-off-by: michaere <michaere@amdocs.com>
Diffstat (limited to 'champ-service')
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 Binary files differnew file mode 100644 index 0000000..aeca770 --- /dev/null +++ b/champ-service/src/main/config/ajsc-chef.jks 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 Binary files differnew file mode 100644 index 0000000..48cdbff --- /dev/null +++ b/champ-service/src/main/config/ajscJetty.jks 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 |