diff options
68 files changed, 3528 insertions, 2157 deletions
@@ -33,3 +33,11 @@ debug-logs/ docs/Makefile docs/_build docs/conf.py + +#VSCODE +.VSCODE +.attach_pid* + + +#jmeter +jmeter.log diff --git a/distribution/music/Dockerfile b/distribution/music/Dockerfile index c3253ae0..fcfb05fd 100644 --- a/distribution/music/Dockerfile +++ b/distribution/music/Dockerfile @@ -21,7 +21,7 @@ FROM openjdk:8 LABEL purpose="Springboot for MUSIC" -RUN apt update && apt install -y netcat telnet vim vim-common +RUN apt-get update && apt-get install -y netcat telnet vim vim-common curl RUN groupadd --gid 1000 music && useradd --gid 1000 --uid 1000 music RUN mkdir -p /opt/app/music/logs/MUSIC COPY MUSIC.jar /opt/app/music diff --git a/distribution/music/build.sh b/distribution/music/build.sh deleted file mode 100644 index 21e45268..00000000 --- a/distribution/music/build.sh +++ /dev/null @@ -1,10 +0,0 @@ -if [ "${1}" ]; then - -docker build -t dockercentral.it.att.com:5100/com.att.music/music-sb:${1} . -docker tag dockercentral.it.att.com:5100/com.att.music/music-sb:${1} dockercentral.it.att.com:5100/com.att.music/music-sb:latest -docker push dockercentral.it.att.com:5100/com.att.music/music-sb:latest -docker push dockercentral.it.att.com:5100/com.att.music/music-sb:${1} -else -echo "Missing version" - -fi diff --git a/distribution/music/startup.sh b/distribution/music/startup.sh index 420436c0..a6d8308e 100644 --- a/distribution/music/startup.sh +++ b/distribution/music/startup.sh @@ -32,5 +32,11 @@ else PASSWORD=changeit echo "#### Using Default Password for Certs" >> ${LOGFILE} fi +if [ ${EXTAP} ]; then + if [ "${EXTAP_FILE}" != "" ]; then + EXTAP_OPTION="--spring.config.location=file:${EXTAP_FILE}" + fi +fi +echo "java -jar MUSIC.jar ${EXTAP_OPTION} --server.ssl.key-store-password=${PASSWORD} --aaf_password=enc:${PASSWORD} 2>&1 | tee ${LOGFILE}" +java -jar MUSIC.jar ${EXTAP_OPTION} --server.ssl.key-store-password="${PASSWORD}" --aaf_password="enc:${PASSWORD}" 2>&1 | tee ${LOGFILE} -java -jar MUSIC.jar --server.ssl.key-store-password="${PASSWORD}" --aaf_password="enc:${PASSWORD}" 2>&1 | tee ${LOGFILE} diff --git a/docs/release-notes.rst b/docs/release-notes.rst index 0d1e1794..33f2a95e 100644 --- a/docs/release-notes.rst +++ b/docs/release-notes.rst @@ -4,38 +4,34 @@ Release Notes ============= -Initial Release for Casablanca +Initial Release for Dublin -Version: 3.0.24 +Version: 3.2.18 --------------- -:Release Date: 2018-11-30 +:Release Date: 2019-06-06 **New Features** -- MUSIC as a Service: while MUSIC was consumed internally by components in the Beijing release, in Casablanca MUSIC can be deployed as an independent multi-site clustered service +- MUSIC now uses Cassandra only as its locking service. In previous releases, MUSIC had a dependency on Zookeeper for locking. -- Designed MUSIC to be a fully sharded, scale out system, where as many ONAP sites/component replicas can be added as required for performance +- For the Dublin release, MUSIC now leverages Spring Boot for improved start up capabilities and performance. -- Automated failure detection and consistent failover across sites for ONAP components using MUSIC through the PROM recipe +- By leveraging CADI, MUSIC is able to more quickly and accurately authenticate it's clients. - Continued adherence to ONAP S3P requirements **Bug Fixes** - - `MUSIC-176 <https://jira.onap.org/projects/MUSIC/issues/MUSIC-176>`_ nc: bad address + - `MUSIC-386 <https://jira.onap.org/projects/MUSIC/issues/MUSIC-386>`_ Music fails health check - - `MUSIC-154 <https://jira.onap.org/projects/MUSIC/issues/MUSIC-154>`_ Helm charts using latest tag name - - - `MUSIC-152 <https://jira.onap.org/projects/MUSIC/issues/MUSIC-152>`_ MUSIC tomcat returning HTTP 401 - - - `MUSIC-147 <https://jira.onap.org/projects/MUSIC/issues/MUSIC-147>`_ Cassandra-job is failing - - - `MUSIC-143 <https://jira.onap.org/projects/MUSIC/issues/MUSIC-143>`_ Translator Service not picking records from controller + - `MUSIC-368 <https://jira.onap.org/projects/MUSIC/issues/MUSIC-368`_ MUSIC responding with 500 error - `MUSIC-78 <https://jira.onap.org/projects/MUSIC/issues/MUSIC-78>`_ Build failed to find artifact org.onap.music:MUSIC:jar:2.5.5 + - `MUSIC-264 <https://jira.onap.org/projects/MUSIC/issues/MUSIC-264>`_ Fails to create keyspace + **Known Issues** @@ -48,10 +44,10 @@ MUSIC code has been formally scanned during build time using NexusIQ and all Cri Quick Links: - `MUSIC project page <https://wiki.onap.org/display/DW/MUSIC+Project>`_ -- `MUSIC Casablanca Release <https://wiki.onap.org/display/DW/MUSIC+Casablanca+Release>`_ +- `MUSIC Dublin Release <https://wiki.onap.org/display/DW/MUSIC+%28R4%29+Dublin+Release>`_ - `Passing Badge information for MUSIC <https://bestpractices.coreinfrastructure.org/en/projects/1722>`_ -- `MUSIC Architecture Page <https://onap.readthedocs.io/en/casablanca/submodules/music.git/docs/architecture.html>`_ -- `Project Vulnerability Review Table for MUSIC <https://wiki.onap.org/pages/viewpage.action?pageId=45285410>`_ +- `MUSIC Architecture Page <https://onap.readthedocs.io/en/dublin/submodules/music.git/docs/architecture.html>`_ +- `Project Vulnerability Review Table for MUSIC <https://wiki.onap.org/pages/viewpage.action?pageId=64004601>`_ **Upgrade Notes** diff --git a/examples/VotingApp/src/main/java/main/MusicConnector.java b/examples/VotingApp/src/main/java/main/MusicConnector.java index ab4d895d..7772c9f2 100644 --- a/examples/VotingApp/src/main/java/main/MusicConnector.java +++ b/examples/VotingApp/src/main/java/main/MusicConnector.java @@ -26,8 +26,7 @@ package main; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; -import java.util.Random; - +import java.security.SecureRandom; public class MusicConnector { //change this to point to relevant cluster @@ -38,7 +37,7 @@ public class MusicConnector { } private String getMusicNodeIp(){ - Random r = new Random(); + SecureRandom r = new SecureRandom(); int index = r.nextInt(musicNodes.length); return musicNodes[index]; } diff --git a/jar/pom.xml b/jar/pom.xml index c4e4294f..81f0d8f6 100755 --- a/jar/pom.xml +++ b/jar/pom.xml @@ -25,7 +25,7 @@ <groupId>org.onap.music</groupId> <artifactId>MUSIC</artifactId> <packaging>jar</packaging> - <version>2.5.9</version> + <version>2.5.10-SNAPSHOT</version> <description> This is the MUSIC REST interface, packaged as a war file. </description> @@ -311,7 +311,32 @@ <dependency> <groupId>io.netty</groupId> <artifactId>netty-handler</artifactId> - <version>4.0.56.Final</version> + <version>4.1.33.Final</version> + </dependency> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-buffer</artifactId> + <version>4.1.33.Final</version> + </dependency> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-codec</artifactId> + <version>4.1.33.Final</version> + </dependency> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-common</artifactId> + <version>4.1.33.Final</version> + </dependency> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-resolver</artifactId> + <version>4.1.33.Final</version> + </dependency> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-transport</artifactId> + <version>4.1.33.Final</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> @@ -334,10 +359,15 @@ <version>19.0</version> </dependency> <dependency> + <groupId>de.svenkubiak</groupId> + <artifactId>jBCrypt</artifactId> + <version>0.4.1</version> + </dependency> + <!-- <dependency> <groupId>org.mindrot</groupId> <artifactId>jbcrypt</artifactId> <version>0.4</version> - </dependency> + </dependency>--> <!-- https://mvnrepository.com/artifact/commons-codec/commons-codec --> <dependency> <groupId>commons-codec</groupId> diff --git a/jar/src/main/java/org/onap/music/datastore/MusicDataStore.java b/jar/src/main/java/org/onap/music/datastore/MusicDataStore.java index 2fbca444..3cd8baeb 100644 --- a/jar/src/main/java/org/onap/music/datastore/MusicDataStore.java +++ b/jar/src/main/java/org/onap/music/datastore/MusicDataStore.java @@ -168,20 +168,18 @@ public class MusicDataStore { .setConnectionsPerHost(HostDistance.REMOTE, 2, 4); while (it.hasNext()) { try { - if(MusicUtil.getCassName() != null && MusicUtil.getCassPwd() != null) { - logger.info(EELFLoggerDelegate.applicationLogger, - "Building with credentials "+MusicUtil.getCassName()+" & "+MusicUtil.getCassPwd()); + if(MusicUtil.getCassName() != null && MusicUtil.getCassPwd() != null) { cluster = Cluster.builder().withPort(MusicUtil.getCassandraPort()) - .withCredentials(MusicUtil.getCassName(), MusicUtil.getCassPwd()) + .withCredentials(MusicUtil.getCassName(), MusicUtil.getCassPwd()) //.withLoadBalancingPolicy(new RoundRobinPolicy()) - .withoutJMXReporting() - .withPoolingOptions(poolingOptions) - .addContactPoints(addresses).build(); + .withoutJMXReporting() + .withPoolingOptions(poolingOptions) + .addContactPoints(addresses).build(); } else cluster = Cluster.builder().withPort(MusicUtil.getCassandraPort()) //.withLoadBalancingPolicy(new RoundRobinPolicy()) - .addContactPoints(addresses).build(); + .addContactPoints(addresses).build(); Metadata metadata = cluster.getMetadata(); logger.info(EELFLoggerDelegate.applicationLogger, "Connected to cassa cluster " @@ -213,19 +211,15 @@ public class MusicDataStore { addresses = address.split(","); PoolingOptions poolingOptions = new PoolingOptions(); poolingOptions - .setConnectionsPerHost(HostDistance.LOCAL, 4, 10) - .setConnectionsPerHost(HostDistance.REMOTE, 2, 4); + .setConnectionsPerHost(HostDistance.LOCAL, 4, 10) + .setConnectionsPerHost(HostDistance.REMOTE, 2, 4); if(MusicUtil.getCassName() != null && MusicUtil.getCassPwd() != null) { - logger.info(EELFLoggerDelegate.applicationLogger, - "Building with credentials "+MusicUtil.getCassName()+" & "+MusicUtil.getCassPwd()); cluster = Cluster.builder().withPort(MusicUtil.getCassandraPort()) - .withCredentials(MusicUtil.getCassName(), MusicUtil.getCassPwd()) - //.withLoadBalancingPolicy(new RoundRobinPolicy()) - .withoutJMXReporting() - .withPoolingOptions(poolingOptions) - .addContactPoints(addresses).build(); - } - else { + .withCredentials(MusicUtil.getCassName(), MusicUtil.getCassPwd()) + .withoutJMXReporting() + .withPoolingOptions(poolingOptions) + .addContactPoints(addresses).build(); + } else { cluster = Cluster.builder().withPort(MusicUtil.getCassandraPort()) //.withLoadBalancingPolicy(new RoundRobinPolicy()) .withoutJMXReporting() @@ -238,7 +232,9 @@ public class MusicDataStore { try { session = cluster.connect(); } catch (Exception ex) { - logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(),AppMessages.CASSANDRACONNECTIVITY, ErrorSeverity.ERROR, ErrorTypes.SERVICEUNAVAILABLE); + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), + AppMessages.CASSANDRACONNECTIVITY, + ErrorSeverity.ERROR, ErrorTypes.SERVICEUNAVAILABLE); throw new MusicServiceException( "Error while connecting to Cassandra cluster.. " + ex.getMessage()); } diff --git a/jar/src/main/java/org/onap/music/main/MusicUtil.java b/jar/src/main/java/org/onap/music/main/MusicUtil.java index 686b0d04..4acc3c5a 100755 --- a/jar/src/main/java/org/onap/music/main/MusicUtil.java +++ b/jar/src/main/java/org/onap/music/main/MusicUtil.java @@ -82,7 +82,7 @@ public class MusicUtil { "all.pubic.ips", "cassandra.user", "cassandra.password", "aaf.endpoint.url" }; private static String cassName = "cassandra"; - private static String cassPwd = "cassandra"; + private static String cassPwd = ""; private static String aafEndpointUrl = null; private static int cassandraPort = 9042; diff --git a/jar/src/main/java/org/onap/music/main/PropertiesListener.java b/jar/src/main/java/org/onap/music/main/PropertiesListener.java index beb88af6..724d3d45 100755 --- a/jar/src/main/java/org/onap/music/main/PropertiesListener.java +++ b/jar/src/main/java/org/onap/music/main/PropertiesListener.java @@ -81,7 +81,7 @@ public class PropertiesListener implements ServletContextListener { break; case "debug": MusicUtil.setDebug(Boolean - .getBoolean(prop.getProperty(key).toLowerCase())); + .parseBoolean(prop.getProperty(key).toLowerCase())); break; case "version": MusicUtil.setVersion(prop.getProperty(key)); diff --git a/jar/src/main/java/org/onap/music/rest/RestMusicDataAPI.java b/jar/src/main/java/org/onap/music/rest/RestMusicDataAPI.java index fc31cd9e..4b29f9a1 100755 --- a/jar/src/main/java/org/onap/music/rest/RestMusicDataAPI.java +++ b/jar/src/main/java/org/onap/music/rest/RestMusicDataAPI.java @@ -218,12 +218,16 @@ public class RestMusicDataAPI { try { queryObject = new PreparedQueryObject(); - queryObject.appendQueryString("CREATE ROLE IF NOT EXISTS '" + userId - + "' WITH PASSWORD = '" + password + "' AND LOGIN = true;"); +// queryObject.appendQueryString("CREATE ROLE IF NOT EXISTS '" + userId +// + "' WITH PASSWORD = '" + password + "' AND LOGIN = true;"); + queryObject.appendQueryString("CREATE ROLE IF NOT EXISTS ? " + + " WITH PASSWORD = ? AND LOGIN = true;"); + queryObject.addValue(userId); + queryObject.addValue(password); MusicCore.nonKeyRelatedPut(queryObject, consistency); queryObject = new PreparedQueryObject(); queryObject.appendQueryString("GRANT ALL PERMISSIONS on KEYSPACE " + keyspaceName - + " to '" + userId + "'"); + + " to '" + userId + "'"); queryObject.appendQueryString(";"); MusicCore.nonKeyRelatedPut(queryObject, consistency); } catch (Exception e) { @@ -235,8 +239,8 @@ public class RestMusicDataAPI { String hashedpwd = BCrypt.hashpw(password, BCrypt.gensalt()); queryObject = new PreparedQueryObject(); queryObject.appendQueryString( - "INSERT into admin.keyspace_master (uuid, keyspace_name, application_name, is_api, " - + "password, username, is_aaf) values (?,?,?,?,?,?,?)"); + "INSERT into admin.keyspace_master (uuid, keyspace_name, application_name, is_api, " + + "password, username, is_aaf) values (?,?,?,?,?,?,?)"); queryObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), newAid)); queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), keyspaceName)); queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), ns)); @@ -27,7 +27,7 @@ <groupId>org.onap.music</groupId> <artifactId>MUSIC</artifactId> <packaging>jar</packaging> - <version>3.2.29-SNAPSHOT</version> + <version>3.2.34-SNAPSHOT</version> <description> This is the MUSIC REST interface, packaged as a Springboot jar file. </description> @@ -45,7 +45,7 @@ <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> <version>2.0.3.RELEASE</version> - </dependency> --> + </dependency> --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> @@ -141,6 +141,7 @@ <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> + <version>2.1.1.RELEASE</version> <configuration> <mainClass>org.onap.music.MusicApplication</mainClass> <outputDirectory>./distribution/music/</outputDirectory> @@ -244,39 +245,22 @@ <scope>test</scope> </dependency> <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-actuator</artifactId> + <groupId>org.springframework</groupId> + <artifactId>spring-aop</artifactId> + <scope>compile</scope> </dependency> - <dependency> - <groupId>org.springframework</groupId> - <artifactId>spring-aop</artifactId> - <scope>compile</scope> - </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <dependency> - <groupId>org.springframework</groupId> - <artifactId>spring-aop</artifactId> - <scope>compile</scope> - </dependency> - <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <scope>compile</scope> </dependency> <!-- Springboot --> <!-- Development --> - <dependency> - <groupId>org.aspectj</groupId> - <artifactId>aspectjweaver</artifactId> - <scope>compile</scope> - </dependency> - - <!-- Springboot --> - <!-- Development --> - <dependency> + <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.4</version> @@ -323,21 +307,16 @@ </exclusion> <exclusion> <groupId>org.powermock</groupId> - <artifactId>powermock-module-junit4</artifactId> + <artifactId>powermock-module-junit4</artifactId> </exclusion> </exclusions> </dependency> <!-- End Logging --> <!-- Cassandra --> <dependency> - <groupId>io.dropwizard.metrics</groupId> - <artifactId>metrics-core</artifactId> - <version>4.1.0-rc3</version> - </dependency> - <dependency> - <groupId>com.datastax.cassandra</groupId> - <artifactId>cassandra-driver-core</artifactId> - <version>3.6.0</version> + <groupId>io.dropwizard.metrics</groupId> + <artifactId>metrics-core</artifactId> + <version>4.1.0-rc3</version> </dependency> <dependency> <groupId>com.datastax.cassandra</groupId> @@ -383,6 +362,7 @@ <artifactId>commons-lang3</artifactId> <version>3.8</version> </dependency> + <!-- Testing --> <dependency> <groupId>junit</groupId> @@ -397,6 +377,22 @@ <scope>test</scope> <exclusions> <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + </exclusion> + <exclusion> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-core</artifactId> + </exclusion> + <exclusion> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + </exclusion> + <exclusion> + <groupId>org.cassandraunit</groupId> + <artifactId>cassandra-unit</artifactId> + </exclusion> + <exclusion> <groupId>io.dropwizard.metrics</groupId> <artifactId>metrics-core</artifactId> </exclusion> @@ -405,60 +401,27 @@ <artifactId>reporter-config-base</artifactId> </exclusion> </exclusions> - </dependency> + </dependency> <dependency> - <groupId>org.cassandraunit</groupId> - <artifactId>cassandra-unit-spring</artifactId> - <version>3.5.0.1</version> - <scope>test</scope> - <exclusions> - <exclusion> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-log4j12</artifactId> - </exclusion> - <exclusion> - <groupId>ch.qos.logback</groupId> - <artifactId>logback-core</artifactId> - </exclusion> - <exclusion> - <groupId>ch.qos.logback</groupId> - <artifactId>logback-classic</artifactId> - </exclusion> - <exclusion> - <groupId>org.cassandraunit</groupId> - <artifactId>cassandra-unit</artifactId> - </exclusion> - <exclusion> - <groupId>io.dropwizard.metrics</groupId> - <artifactId>metrics-core</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> <groupId>org.cassandraunit</groupId> <artifactId>cassandra-unit-shaded</artifactId> <version>3.5.0.1</version> <scope>test</scope> </dependency> <dependency> - <groupId>io.dropwizard.metrics</groupId> - <artifactId>metrics-core</artifactId> - <version>3.1.0</version> - </dependency> - <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>2.23.4</version> <scope>test</scope> </dependency> <!-- /Testing --> + <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.datatype/jackson-datatype-jsr310 --> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> <version>2.9.8</version> </dependency> - <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> @@ -478,16 +441,10 @@ <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency> - -<!-- <dependency> - <groupId>io.swagger</groupId> - <artifactId>swagger-jersey2-jaxrs</artifactId> - <version>1.5.18</version> - </dependency> --> <dependency> <groupId>io.swagger</groupId> <artifactId>swagger-jersey-jaxrs</artifactId> - <version>1.5.21</version> + <version>1.5.22</version> </dependency> <dependency> <groupId>com.google.guava</groupId> @@ -498,11 +455,6 @@ <artifactId>jBCrypt</artifactId> <version>0.4.1</version> </dependency> - <!-- <dependency> - <groupId>org.mindrot</groupId> - <artifactId>jbcrypt</artifactId> - <version>0.4</version> - </dependency>--> <dependency> <groupId>io.netty</groupId> <artifactId>netty-handler</artifactId> @@ -533,28 +485,27 @@ <artifactId>netty-transport</artifactId> <version>4.1.33.Final</version> </dependency> - <dependency> - <groupId>org.onap.aaf.authz</groupId> - <artifactId>aaf-cadi-aaf</artifactId> - <version>2.1.7</version> - <exclusions> - <exclusion> - <groupId>log4j</groupId> - <artifactId>log4j</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>org.onap.aaf.authz</groupId> - <artifactId>aaf-cadi-client</artifactId> - <version>2.1.7</version> - </dependency> - <dependency> - <groupId>org.onap.aaf.authz</groupId> - <artifactId>aaf-cadi-core</artifactId> - <version>2.1.7</version> - </dependency> - + <dependency> + <groupId>org.onap.aaf.authz</groupId> + <artifactId>aaf-cadi-aaf</artifactId> + <version>2.1.7</version> + <exclusions> + <exclusion> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.onap.aaf.authz</groupId> + <artifactId>aaf-cadi-client</artifactId> + <version>2.1.7</version> + </dependency> + <dependency> + <groupId>org.onap.aaf.authz</groupId> + <artifactId>aaf-cadi-core</artifactId> + <version>2.1.7</version> + </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> @@ -689,13 +640,6 @@ </profile> <profile> <id>default</id> - <repositories> - <repository> - <id>nexus</id> - <name>attarch-releases</name> - <url>http://mavencentral.it.att.com:8084/nexus/content/repositories/attarch-releases</url> - </repository> - </repositories> </profile> </profiles> <distributionManagement> diff --git a/src/main/java/org/onap/music/JerseyConfig.java b/src/main/java/org/onap/music/JerseyConfig.java index fbf71f3a..b64e7044 100755 --- a/src/main/java/org/onap/music/JerseyConfig.java +++ b/src/main/java/org/onap/music/JerseyConfig.java @@ -1,17 +1,23 @@ /* - * Copyright 2012-2015 the original author or authors. - * - * 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_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 AT&T Intellectual Property + * =================================================================== + * 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============================================= + * ==================================================================== */ package org.onap.music; diff --git a/src/main/java/org/onap/music/MusicApplication.java b/src/main/java/org/onap/music/MusicApplication.java index 8f5f773e..22c9e7bf 100755 --- a/src/main/java/org/onap/music/MusicApplication.java +++ b/src/main/java/org/onap/music/MusicApplication.java @@ -42,30 +42,29 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.FilterRegistrationBean; -//import org.springframework.boot.web.support.SpringBootServletInitializer; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; -import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.DependsOn; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.web.context.request.RequestContextListener; -@SpringBootApplication(scanBasePackages = { "org.onap.music.rest" }) +@SpringBootApplication(scanBasePackages = { "org.onap.music.rest"}) @EnableAutoConfiguration(exclude = { CassandraDataAutoConfiguration.class }) @ComponentScan(value = { "org.onap.music" }) @EnableScheduling public class MusicApplication extends SpringBootServletInitializer { + private static final String KEYSPACE_PATTERN = "/v2/keyspaces/*"; + private static final String LOCKS_PATTERN = "/v2/locks/*"; + private static final String Q_PATTERN = "/v2/priorityq/*"; + @Autowired private PropertiesLoader propertyLoader; private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicApplication.class); + public static void main(String[] args) { - System.setProperty("AFT_DME2_CLIENT_IGNORE_SSL_CONFIG", "false"); - System.setProperty("AFT_DME2_CLIENT_KEYSTORE", "/opt/app/music/etc/truststore2018.jks"); - System.setProperty("AFT_DME2_CLIENT_KEYSTORE_PASSWORD", "changeit"); - System.setProperty("AFT_DME2_CLIENT_SSL_INCLUDE_PROTOCOLS", "TLSv1.1,TLSv1.2"); new MusicApplication().configure(new SpringApplicationBuilder(MusicApplication.class)).run(args); } @@ -80,8 +79,6 @@ public class MusicApplication extends SpringBootServletInitializer { propertyLoader.loadProperties(); } - @Autowired - private ApplicationContext appContext; @Bean @DependsOn("loadProperties") @@ -100,9 +97,7 @@ public class MusicApplication extends SpringBootServletInitializer { propertyLoader.loadProperties(); if (MusicUtil.getIsCadi()) { PropAccess propAccess = propAccess(); - CadiAuthFilter cadiFilter = new CadiAuthFilter(propAccess); - - return cadiFilter; + return new CadiAuthFilter(propAccess); } else { return (ServletRequest request, ServletResponse response, FilterChain chain) -> { // do nothing for now. @@ -128,15 +123,14 @@ public class MusicApplication extends SpringBootServletInitializer { FilterRegistrationBean<Filter> frb = new FilterRegistrationBean<>(); frb.setFilter(new MusicLoggingServletFilter()); frb.addUrlPatterns( - "/v2/keyspaces/*", - "/v2/locks/*", - "/v2/priorityq/*" + KEYSPACE_PATTERN, + LOCKS_PATTERN, + Q_PATTERN ); frb.setName("logFilter"); frb.setOrder(1); return frb; } - @Bean @DependsOn("loadProperties") @@ -144,14 +138,11 @@ public class MusicApplication extends SpringBootServletInitializer { logger.info("cadiFilterRegistration called for cadi filter.."); FilterRegistrationBean<Filter> frb = new FilterRegistrationBean<>(); frb.setFilter(cadiFilter()); - - // The Following Patterns are used to control what APIs will be secure - // TODO: Make this a configurable item. Build this from an array? if (MusicUtil.getIsCadi()) { frb.addUrlPatterns( - "/v2/keyspaces/*", - "/v2/locks/*", - "/v2/priorityq/*" + KEYSPACE_PATTERN, + LOCKS_PATTERN, + Q_PATTERN ); } else { frb.addUrlPatterns("/v0/test"); @@ -179,10 +170,10 @@ public class MusicApplication extends SpringBootServletInitializer { if (MusicUtil.getIsCadi()) { frb.addUrlPatterns( - "/v2/keyspaces/*", - "/v2/locks/*", - "/v2/priorityq/*" - ); + KEYSPACE_PATTERN, + LOCKS_PATTERN, + Q_PATTERN + ); } else { frb.addUrlPatterns("/v0/test"); } @@ -196,8 +187,7 @@ public class MusicApplication extends SpringBootServletInitializer { public Filter cadiMusicAuthFilter() throws ServletException { propertyLoader.loadProperties(); if (MusicUtil.getIsCadi()) { - MusicAuthorizationFilter authFilter = new MusicAuthorizationFilter(); - return authFilter; + return new MusicAuthorizationFilter(); } else { return (ServletRequest request, ServletResponse response, FilterChain chain) -> { // do nothing for now. @@ -210,4 +200,4 @@ public class MusicApplication extends SpringBootServletInitializer { public RequestContextListener requestContextListener() { return new RequestContextListener(); } -}
\ No newline at end of file +} diff --git a/src/main/java/org/onap/music/authentication/AuthUtil.java b/src/main/java/org/onap/music/authentication/AuthUtil.java index 51e3dac0..223fa74e 100644 --- a/src/main/java/org/onap/music/authentication/AuthUtil.java +++ b/src/main/java/org/onap/music/authentication/AuthUtil.java @@ -37,14 +37,16 @@ import org.onap.aaf.cadi.CadiWrap; import org.onap.aaf.cadi.Permission; import org.onap.aaf.cadi.aaf.AAFPermission; import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.exceptions.MusicAuthenticationException; public class AuthUtil { - private static final String decodeValueOfForwardSlash = "2f"; - private static final String decodeValueOfHyphen = "2d"; - private static final String decodeValueOfAsterisk = "2a"; private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AuthUtil.class); + private AuthUtil() { + throw new IllegalStateException("Utility class"); + } + /** * Get the list of permissions from the Request object. * @@ -88,7 +90,7 @@ public class AuthUtil { private static List<AAFPermission> filterNameSpacesAAFPermissions(String nameSpace, List<AAFPermission> allPermissionsList) { List<AAFPermission> list = new ArrayList<>(); - for (Iterator iterator = allPermissionsList.iterator(); iterator.hasNext();) { + for (Iterator<AAFPermission> iterator = allPermissionsList.iterator(); iterator.hasNext();) { AAFPermission aafPermission = (AAFPermission) iterator.next(); if(aafPermission.getType().indexOf(nameSpace) == 0) { list.add(aafPermission); @@ -104,20 +106,23 @@ public class AuthUtil { * @return returns the decoded string. * @throws Exception throws excpetion */ - public static String decodeFunctionCode(String str) throws Exception { + public static String decodeFunctionCode(String str) throws MusicAuthenticationException { + final String DECODEVALUE_FORWARDSLASH = "2f"; + final String DECODEVALUE_HYPHEN = "2d"; + final String DECODEVALUE_ASTERISK = "2a"; String decodedString = str; List<Pattern> decodingList = new ArrayList<>(); - decodingList.add(Pattern.compile(decodeValueOfForwardSlash)); - decodingList.add(Pattern.compile(decodeValueOfHyphen)); - decodingList.add(Pattern.compile(decodeValueOfAsterisk)); + decodingList.add(Pattern.compile(DECODEVALUE_FORWARDSLASH)); + decodingList.add(Pattern.compile(DECODEVALUE_HYPHEN)); + decodingList.add(Pattern.compile(DECODEVALUE_ASTERISK)); for (Pattern xssInputPattern : decodingList) { try { decodedString = decodedString.replaceAll("%" + xssInputPattern, new String(Hex.decodeHex(xssInputPattern.toString().toCharArray()))); } catch (DecoderException e) { - logger.error(EELFLoggerDelegate.applicationLogger, + logger.error(EELFLoggerDelegate.securityLogger, "AuthUtil Decode Failed! for instance: " + str); - throw new Exception("decode failed", e); + throw new MusicAuthenticationException("Decode failed", e); } } @@ -132,44 +137,42 @@ public class AuthUtil { * @return boolean value if the access is allowed * @throws Exception throws exception */ - public static boolean isAccessAllowed(ServletRequest request, String nameSpace) throws Exception { + public static boolean isAccessAllowed(ServletRequest request, String nameSpace) throws MusicAuthenticationException { if (request==null) { - throw new Exception("Request cannot be null"); + throw new MusicAuthenticationException("Request cannot be null"); } if (nameSpace==null || nameSpace.isEmpty()) { - throw new Exception("NameSpace not Declared!"); + throw new MusicAuthenticationException("NameSpace not Declared!"); } boolean isauthorized = false; List<AAFPermission> aafPermsList = getAAFPermissions(request); - //logger.info(EELFLoggerDelegate.applicationLogger, - // "AAFPermission of the requested MechId for all the namespaces: " + aafPermsList); - - logger.debug(EELFLoggerDelegate.applicationLogger, "Requested nameSpace: " + nameSpace); - + logger.info(EELFLoggerDelegate.securityLogger, + "AAFPermission of the requested MechId for all the namespaces: " + aafPermsList); + logger.debug(EELFLoggerDelegate.securityLogger, "Requested nameSpace: " + nameSpace); List<AAFPermission> aafPermsFinalList = filterNameSpacesAAFPermissions(nameSpace, aafPermsList); - logger.debug(EELFLoggerDelegate.applicationLogger, - "AuthUtil list of AAFPermission for the specific namespace ::::::::::::::::::::::::::::::::::::::::::::" + logger.debug(EELFLoggerDelegate.securityLogger, + "AuthUtil list of AAFPermission for the specific namespace :::" + aafPermsFinalList); HttpServletRequest httpRequest = (HttpServletRequest) request; String requestUri = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length() + 1); - logger.debug(EELFLoggerDelegate.applicationLogger, - "AuthUtil requestUri ::::::::::::::::::::::::::::::::::::::::::::" + requestUri); + logger.debug(EELFLoggerDelegate.securityLogger, + "AuthUtil requestUri :::" + requestUri); - for (Iterator iterator = aafPermsFinalList.iterator(); iterator.hasNext();) { + for (Iterator<AAFPermission> iterator = aafPermsFinalList.iterator(); iterator.hasNext();) { AAFPermission aafPermission = (AAFPermission) iterator.next(); if(!isauthorized) { - isauthorized = isMatchPatternWithInstanceAndAction(aafPermission, requestUri, httpRequest.getMethod()); + isauthorized = isMatchPattern(aafPermission, requestUri, httpRequest.getMethod()); } } - logger.debug(EELFLoggerDelegate.applicationLogger, + logger.debug(EELFLoggerDelegate.securityLogger, "isAccessAllowed for the request uri: " + requestUri + "is :" + isauthorized); return isauthorized; } @@ -205,23 +208,21 @@ public class AuthUtil { * @return returns a boolean * @throws Exception - throws an exception */ - private static boolean isMatchPatternWithInstanceAndAction( + private static boolean isMatchPattern( AAFPermission aafPermission, String requestUri, - String method) throws Exception { + String method) throws MusicAuthenticationException { if (null == aafPermission || null == requestUri || null == method) { return false; } String permKey = aafPermission.getKey(); - logger.info(EELFLoggerDelegate.applicationLogger, "isMatchPattern permKey: " + logger.debug(EELFLoggerDelegate.securityLogger, "isMatchPattern permKey: " + permKey + ", requestUri " + requestUri + " ," + method); String[] keyArray = permKey.split("\\|"); String[] subPath = null; - //String type = null; - //type = keyArray[0]; String instance = keyArray[1]; String action = keyArray[2]; @@ -251,13 +252,7 @@ public class AuthUtil { subPath = path[i].split("\\."); for (int j = 0; j < subPath.length; j++) { if (instanceList.contains(subPath[j])) { - if ("*".equals(action) || "ALL".equalsIgnoreCase(action)) { - return true; - } else if (method.equalsIgnoreCase(action)) { - return true; - } else { - return false; - } + return checkAction(method,action); } else { continue; } @@ -265,4 +260,15 @@ public class AuthUtil { } return false; } + + private static boolean checkAction(String method, String action) { + if ("*".equals(action) || "ALL".equalsIgnoreCase(action)) { + return true; + } else { + return (method.equalsIgnoreCase(action)); + } + } + + + }
\ No newline at end of file diff --git a/src/main/java/org/onap/music/authentication/CadiAuthFilter.java b/src/main/java/org/onap/music/authentication/CadiAuthFilter.java index 765face7..d043e6d6 100644 --- a/src/main/java/org/onap/music/authentication/CadiAuthFilter.java +++ b/src/main/java/org/onap/music/authentication/CadiAuthFilter.java @@ -57,14 +57,9 @@ public class CadiAuthFilter extends CadiFilter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - logger.info(EELFLoggerDelegate.applicationLogger, "Request is entering cadifilter"); - + logger.info(EELFLoggerDelegate.securityLogger, "Request is entering cadifilter"); long startTime = System.currentTimeMillis(); request.setAttribute("startTime", startTime); - super.doFilter(request, response, chain); - - //Commented by saumya (sp931a) on 04/11/19 for auth filter - //chain.doFilter(request, response); } }
\ No newline at end of file diff --git a/src/main/java/org/onap/music/authentication/MusicAuthorizationFilter.java b/src/main/java/org/onap/music/authentication/MusicAuthorizationFilter.java index b1db1083..bde3e205 100644 --- a/src/main/java/org/onap/music/authentication/MusicAuthorizationFilter.java +++ b/src/main/java/org/onap/music/authentication/MusicAuthorizationFilter.java @@ -25,10 +25,6 @@ package org.onap.music.authentication; import java.io.IOException; -import java.util.Base64; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; import javax.servlet.Filter; import javax.servlet.FilterChain; @@ -36,13 +32,11 @@ import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.onap.music.eelf.logging.EELFLoggerDelegate; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.PropertySource; - +import org.onap.music.exceptions.MusicAuthenticationException; +import org.onap.music.main.MusicUtil; import com.fasterxml.jackson.databind.ObjectMapper; /** @@ -51,11 +45,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; * @author sp931a * */ -@PropertySource(value = {"file:/opt/app/music/etc/music.properties"}) +//@PropertySource(value = {"file:/opt/app/music/etc/music.properties"}) public class MusicAuthorizationFilter implements Filter { - @Value("${music.aaf.ns}") - private String musicNS; + private String musicNS = MusicUtil.getMusicAafNs(); private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicAuthorizationFilter.class); @@ -65,26 +58,18 @@ public class MusicAuthorizationFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { - + // Do Nothing } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) - throws IOException, ServletException { - - logger.debug(EELFLoggerDelegate.applicationLogger, - "In MusicAuthorizationFilter doFilter start() ::::::::::::::::::::::::"); - + throws IOException, ServletException { HttpServletResponse httpResponse = null; boolean isAuthAllowed = false; if (null != servletRequest && null != servletResponse) { httpResponse = (HttpServletResponse) servletResponse; - - logger.debug(EELFLoggerDelegate.applicationLogger, - "Music NS defined in music property file --------------------------" + musicNS); - long startTime = 0; if( null != servletRequest.getAttribute("startTime")) { startTime = ((Long)servletRequest.getAttribute("startTime")).longValue(); @@ -94,20 +79,23 @@ public class MusicAuthorizationFilter implements Filter { try { isAuthAllowed = AuthUtil.isAccessAllowed(servletRequest, musicNS); - } catch (Exception e) { - logger.error(EELFLoggerDelegate.applicationLogger, - "Error while checking authorization :::" + e.getMessage()); + } catch (MusicAuthenticationException e) { + logger.error(EELFLoggerDelegate.securityLogger, + "Error while checking authorization Music Namespace: " + musicNS + " : " + e.getMessage(),e); + } catch ( Exception e) { + logger.error(EELFLoggerDelegate.securityLogger, + "Error while checking authorization Music Namespace: " + musicNS + " : " + e.getMessage(),e); } long endTime = System.currentTimeMillis(); //startTime set in <code>CadiAuthFilter</code> doFilter - logger.debug(EELFLoggerDelegate.applicationLogger, - "Time took for authentication & authorization : " - + (endTime - startTime) + " milliseconds"); + logger.debug(EELFLoggerDelegate.securityLogger, + "Time took for authentication & authorization : " + + (endTime - startTime) + " milliseconds"); if (!isAuthAllowed) { - logger.debug(EELFLoggerDelegate.applicationLogger, + logger.info(EELFLoggerDelegate.securityLogger, "Unauthorized Access"); AuthorizationError authError = new AuthorizationError(); authError.setResponseCode(HttpServletResponse.SC_UNAUTHORIZED); @@ -124,47 +112,11 @@ public class MusicAuthorizationFilter implements Filter { filterChain.doFilter(servletRequest, servletResponse); } } - logger.debug(EELFLoggerDelegate.applicationLogger, - "In MusicAuthorizationFilter doFilter exit() ::::::::::::::::::::::::"); } private byte[] restResponseBytes(AuthorizationError eErrorResponse) throws IOException { String serialized = new ObjectMapper().writeValueAsString(eErrorResponse); return serialized.getBytes(); } - - private Map<String, String> getHeadersInfo(HttpServletRequest request) { - - Map<String, String> map = new HashMap<String, String>(); - - Enumeration headerNames = request.getHeaderNames(); - while (headerNames.hasMoreElements()) { - String key = (String) headerNames.nextElement(); - String value = request.getHeader(key); - map.put(key, value); - } - - return map; - } - - private static String getUserNamefromRequest(HttpServletRequest httpRequest) { - String authHeader = httpRequest.getHeader("Authorization"); - String username = null; - if (authHeader != null) { - String[] split = authHeader.split("\\s+"); - if (split.length > 0) { - String basic = split[0]; - - if ("Basic".equalsIgnoreCase(basic)) { - byte[] decodedBytes = Base64.getDecoder().decode(split[1]); - String decodedString = new String(decodedBytes); - int p = decodedString.indexOf(":"); - if (p != -1) { - username = decodedString.substring(0, p); - } - } - } - } - return username; - } } + diff --git a/src/main/java/org/onap/music/datastore/MusicDataStore.java b/src/main/java/org/onap/music/datastore/MusicDataStore.java index c771d80a..6195dbef 100755 --- a/src/main/java/org/onap/music/datastore/MusicDataStore.java +++ b/src/main/java/org/onap/music/datastore/MusicDataStore.java @@ -35,15 +35,14 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import org.apache.commons.jcs.access.CacheAccess; import org.onap.music.eelf.logging.EELFLoggerDelegate; import org.onap.music.eelf.logging.format.AppMessages; import org.onap.music.eelf.logging.format.ErrorSeverity; import org.onap.music.eelf.logging.format.ErrorTypes; import org.onap.music.exceptions.MusicQueryException; import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.main.CipherUtil; import org.onap.music.main.MusicUtil; -import com.codahale.metrics.JmxReporter; import com.datastax.driver.core.Cluster; import com.datastax.driver.core.ColumnDefinitions; import com.datastax.driver.core.ColumnDefinitions.Definition; @@ -53,7 +52,6 @@ import com.datastax.driver.core.HostDistance; import com.datastax.driver.core.KeyspaceMetadata; import com.datastax.driver.core.Metadata; import com.datastax.driver.core.PoolingOptions; -import com.datastax.driver.core.PreparedStatement; import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.Row; import com.datastax.driver.core.Session; @@ -62,7 +60,6 @@ import com.datastax.driver.core.TableMetadata; import com.datastax.driver.core.exceptions.AlreadyExistsException; import com.datastax.driver.core.exceptions.InvalidQueryException; import com.datastax.driver.core.exceptions.NoHostAvailableException; -import com.sun.jersey.core.util.Base64; /** * @author nelson24 @@ -177,10 +174,11 @@ public class MusicDataStore { while (it.hasNext()) { try { if(MusicUtil.getCassName() != null && MusicUtil.getCassPwd() != null) { + String cassPwd = CipherUtil.decryptPKC(MusicUtil.getCassPwd()); logger.info(EELFLoggerDelegate.applicationLogger, "Building with credentials "+MusicUtil.getCassName()+" & "+MusicUtil.getCassPwd()); cluster = Cluster.builder().withPort(MusicUtil.getCassandraPort()) - .withCredentials(MusicUtil.getCassName(), MusicUtil.getCassPwd()) + .withCredentials(MusicUtil.getCassName(), cassPwd) //.withLoadBalancingPolicy(new RoundRobinPolicy()) .withoutJMXReporting() .withPoolingOptions(poolingOptions) @@ -225,10 +223,11 @@ public class MusicDataStore { .setConnectionsPerHost(HostDistance.LOCAL, 4, 10) .setConnectionsPerHost(HostDistance.REMOTE, 2, 4); if(MusicUtil.getCassName() != null && MusicUtil.getCassPwd() != null) { + String cassPwd = CipherUtil.decryptPKC(MusicUtil.getCassPwd()); logger.info(EELFLoggerDelegate.applicationLogger, - "Building with credentials "+MusicUtil.getCassName()+" & "+MusicUtil.getCassPwd()); + "Building with credentials "+MusicUtil.getCassName()+" & "+ MusicUtil.getCassPwd()); cluster = Cluster.builder().withPort(MusicUtil.getCassandraPort()) - .withCredentials(MusicUtil.getCassName(), MusicUtil.getCassPwd()) + .withCredentials(MusicUtil.getCassName(), cassPwd) //.withLoadBalancingPolicy(new RoundRobinPolicy()) .withoutJMXReporting() .withPoolingOptions(poolingOptions) @@ -410,7 +409,7 @@ public class MusicDataStore { throw new MusicQueryException("Ill formed queryObject for the request = " + "[" + queryObject.getQuery() + "]"); } - logger.info(EELFLoggerDelegate.applicationLogger, + logger.debug(EELFLoggerDelegate.applicationLogger, "In preprared Execute Put: the actual insert query:" + queryObject.getQuery() + "; the values" + queryObject.getValues()); @@ -442,18 +441,19 @@ public class MusicDataStore { } catch (AlreadyExistsException ae) { - logger.error(EELFLoggerDelegate.errorLogger, ae.getMessage(),AppMessages.SESSIONFAILED+ " [" + - queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR, ae); - throw new MusicServiceException(ae.getMessage()); - } - catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.SESSIONFAILED + " [" - + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR, e); + // logger.error(EELFLoggerDelegate.errorLogger,"AlreadExistsException: " + ae.getMessage(),AppMessages.QUERYERROR, + // ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicQueryException("AlreadyExistsException: " + ae.getMessage(),ae); + } catch ( InvalidQueryException e ) { + // logger.error(EELFLoggerDelegate.errorLogger,"InvalidQueryException: " + e.getMessage(),AppMessages.SESSIONFAILED + " [" + // + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicQueryException("InvalidQueryException: " + e.getMessage(),e); + } catch (Exception e) { + // logger.error(EELFLoggerDelegate.errorLogger,e.getClass().toString() + ":" + e.getMessage(),AppMessages.SESSIONFAILED + " [" + // + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR, e); throw new MusicServiceException("Executing Session Failure for Request = " + "[" - + queryObject.getQuery() + "]" + " Reason = " + e.getMessage()); + + queryObject.getQuery() + "]" + " Reason = " + e.getMessage(),e); } - - return result; } @@ -556,9 +556,9 @@ public class MusicDataStore { results = session.execute(statement); } catch (Exception ex) { - logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(),AppMessages.UNKNOWNERROR+ "[" + queryObject + logger.error(EELFLoggerDelegate.errorLogger, "Execute Get Error" + ex.getMessage(),AppMessages.UNKNOWNERROR+ "[" + queryObject .getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR, ex); - throw new MusicServiceException(ex.getMessage()); + throw new MusicServiceException("Execute Get Error" + ex.getMessage()); } return results; diff --git a/src/main/java/org/onap/music/datastore/MusicDataStoreHandle.java b/src/main/java/org/onap/music/datastore/MusicDataStoreHandle.java index d546a016..92457d07 100644 --- a/src/main/java/org/onap/music/datastore/MusicDataStoreHandle.java +++ b/src/main/java/org/onap/music/datastore/MusicDataStoreHandle.java @@ -38,13 +38,13 @@ import com.datastax.driver.core.TableMetadata; public class MusicDataStoreHandle { + private static MusicDataStore mDstoreHandle = null; + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicDataStoreHandle.class); + private MusicDataStoreHandle(){ throw new IllegalStateException("Utility class"); } - private static MusicDataStore mDstoreHandle = null; - private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicDataStoreHandle.class); - /** * * @param remoteIp diff --git a/src/main/java/org/onap/music/datastore/PreparedQueryObject.java b/src/main/java/org/onap/music/datastore/PreparedQueryObject.java index db317eb8..d65096a7 100644 --- a/src/main/java/org/onap/music/datastore/PreparedQueryObject.java +++ b/src/main/java/org/onap/music/datastore/PreparedQueryObject.java @@ -2,7 +2,7 @@ * ============LICENSE_START========================================== * org.onap.music * =================================================================== - * Copyright (c) 2017 AT&T Intellectual Property + * Copyright (c) 2017-2019 AT&T Intellectual Property * =================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,6 +42,35 @@ public class PreparedQueryObject { private String primaryKeyValue; + /** + * Create PreparedQueryObject + */ + public PreparedQueryObject() { + this.values = new ArrayList<>(); + this.query = new StringBuilder(); + } + + /** + * Create PreparedQueryObject + * @param query query portion of the prepared query + */ + public PreparedQueryObject(String query) { + this.values = new ArrayList<>(); + this.query = new StringBuilder(query); + } + + /** + * Create PreparedQueryObject + * @param query query portion of the prepared query + * @param values to be added to the query string as prepared query + */ + public PreparedQueryObject(String query, Object...values) { + this.query = new StringBuilder(query); + this.values = new ArrayList<>(); + for (Object value: values) { + this.values.add(value); + } + } public String getKeyspaceName() { return keyspaceName; @@ -83,28 +112,29 @@ public class PreparedQueryObject { this.consistency = consistency; } - /** - * - */ - public PreparedQueryObject() { - - this.values = new ArrayList<>(); - this.query = new StringBuilder(); - } - /** - * @return + * @return values to be set as part of the prepared query */ public List<Object> getValues() { return values; } /** - * @param o + * @param o object to be added as a value to the prepared query, in order */ public void addValue(Object o) { this.values.add(o); } + + /** + * Add values to the preparedQuery + * @param objs ordered list of objects to be added as values to the prepared query + */ + public void addValues(Object... objs) { + for (Object obj: objs) { + this.values.add(obj); + } + } /** * @param s @@ -117,7 +147,7 @@ public class PreparedQueryObject { } /** - * @return + * @return the query */ public String getQuery() { return this.query.toString(); diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/AAFResponse.java b/src/main/java/org/onap/music/datastore/jsonobjects/AAFResponse.java deleted file mode 100644 index 3544e068..00000000 --- a/src/main/java/org/onap/music/datastore/jsonobjects/AAFResponse.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * ============LICENSE_START========================================== - * org.onap.music - * =================================================================== - * Copyright (c) 2017 AT&T Intellectual Property - * =================================================================== - * Modifications Copyright (c) 2018 IBM - * =================================================================== - * 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============================================= - * ==================================================================== - */ - -package org.onap.music.datastore.jsonobjects; - -import java.util.List; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; - -@ApiModel(value = "JsonTable", description = "Reponse class for AAF request") -public class AAFResponse { - - private List<NameSpace> ns = null; - - @ApiModelProperty(value = "Namespace value") - public List<NameSpace> getNs() { - return ns; - } - - public void setNs(List<NameSpace> ns) { - this.ns = ns; - } - -} diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/JsonDelete.java b/src/main/java/org/onap/music/datastore/jsonobjects/JsonDelete.java index b9b82e08..7ea691f0 100644 --- a/src/main/java/org/onap/music/datastore/jsonobjects/JsonDelete.java +++ b/src/main/java/org/onap/music/datastore/jsonobjects/JsonDelete.java @@ -6,6 +6,8 @@ * =================================================================== * Modifications Copyright (c) 2019 Samsung * =================================================================== + * Modifications Copyright (C) 2019 IBM + * =================================================================== * 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 @@ -27,6 +29,22 @@ package org.onap.music.datastore.jsonobjects; import java.util.List; import java.util.Map; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response.Status; + +import org.onap.music.datastore.Condition; +import org.onap.music.datastore.MusicDataStoreHandle; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.main.MusicUtil; + +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.TableMetadata; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import io.swagger.annotations.ApiModel; @@ -36,11 +54,17 @@ import io.swagger.annotations.ApiModelProperty; @JsonIgnoreProperties(ignoreUnknown = true) public class JsonDelete { + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonDelete.class); + private List<String> columns = null; private Map<String, String> consistencyInfo; private Map<String, Object> conditions; private String ttl; private String timestamp; + private String keyspaceName; + private String tableName; + private StringBuilder rowIdString; + private String primarKeyValue; @ApiModelProperty(value = "Conditions") @@ -88,4 +112,209 @@ public class JsonDelete { public void setTimestamp(String timestamp) { this.timestamp = timestamp; } + + public String getKeyspaceName() { + return keyspaceName; + } + + public void setKeyspaceName(String keyspaceName) { + this.keyspaceName = keyspaceName; + } + + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + + public StringBuilder getRowIdString() { + return rowIdString; + } + + public void setRowIdString(StringBuilder rowIdString) { + this.rowIdString = rowIdString; + } + + public String getPrimarKeyValue() { + return primarKeyValue; + } + + public void setPrimarKeyValue(String primarKeyValue) { + this.primarKeyValue = primarKeyValue; + } + + + public PreparedQueryObject genDeletePreparedQueryObj(MultivaluedMap<String, String> rowParams) throws MusicQueryException { + if (logger.isDebugEnabled()) { + logger.debug("Coming inside genUpdatePreparedQueryObj method " + this.getKeyspaceName()); + logger.debug("Coming inside genUpdatePreparedQueryObj method " + this.getTableName()); + } + + PreparedQueryObject queryObject = new PreparedQueryObject(); + + if((this.getKeyspaceName() == null || this.getKeyspaceName().isEmpty()) + || (this.getTableName() == null || this.getTableName().isEmpty())){ + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + .setError("one or more path parameters are not set, please check and try again") + .toMap()).build();*/ + + throw new MusicQueryException("one or more path parameters are not set, please check and try again", + Status.BAD_REQUEST.getStatusCode()); + } + + EELFLoggerDelegate.mdcPut("keyspace", "( "+this.getKeyspaceName()+" ) "); + + if(this == null) { + logger.error(EELFLoggerDelegate.errorLogger,"Required HTTP Request body is missing.", AppMessages.MISSINGDATA ,ErrorSeverity.WARN, ErrorTypes.DATAERROR); + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Required HTTP Request body is missing.").toMap()).build();*/ + + throw new MusicQueryException("Required HTTP Request body is missing.", + Status.BAD_REQUEST.getStatusCode()); + } + StringBuilder columnString = new StringBuilder(); + + int counter = 0; + List<String> columnList = this.getColumns(); + if (columnList != null) { + for (String column : columnList) { + columnString.append(column); + if (counter != columnList.size() - 1) + columnString.append(","); + counter = counter + 1; + } + } + + // get the row specifier + RowIdentifier rowId = null; + try { + rowId = getRowIdentifier(this.getKeyspaceName(), this.getTableName(), rowParams, queryObject); + this.setRowIdString(rowId.rowIdString); + this.setPrimarKeyValue(rowId.primarKeyValue); + if(rowId == null || rowId.primarKeyValue.isEmpty()) { + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + .setError("Mandatory WHERE clause is missing. Please check the input request.").toMap()).build();*/ + + throw new MusicQueryException("Mandatory WHERE clause is missing. Please check the input request.", + Status.BAD_REQUEST.getStatusCode()); + } + } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes + .GENERALSERVICEERROR, ex); + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();*/ + throw new MusicQueryException(AppMessages.UNKNOWNERROR.toString(), Status.BAD_REQUEST.getStatusCode()); + } + String rowSpec = rowId.rowIdString.toString(); + + if ((columnList != null) && (!rowSpec.isEmpty())) { + queryObject.appendQueryString("DELETE " + columnString + " FROM " + this.getKeyspaceName() + "." + + this.getTableName() + " WHERE " + rowSpec + ";"); + } + + if ((columnList == null) && (!rowSpec.isEmpty())) { + queryObject.appendQueryString("DELETE FROM " + this.getKeyspaceName() + "." + this.getTableName() + " WHERE " + + rowSpec + ";"); + } + + if ((columnList != null) && (rowSpec.isEmpty())) { + queryObject.appendQueryString( + "DELETE " + columnString + " FROM " + this.getKeyspaceName() + "." + rowSpec + ";"); + } + // get the conditional, if any + Condition conditionInfo; + if (this.getConditions() == null) { + conditionInfo = null; + } else { + // to avoid parsing repeatedly, just send the select query to + // obtain row + PreparedQueryObject selectQuery = new PreparedQueryObject(); + selectQuery.appendQueryString("SELECT * FROM " + this.getKeyspaceName() + "." + this.getTableName() + " WHERE " + + rowId.rowIdString + ";"); + selectQuery.addValue(rowId.primarKeyValue); + conditionInfo = new Condition(this.getConditions(), selectQuery); + } + + String consistency = this.getConsistencyInfo().get("type"); + + + if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && this.getConsistencyInfo().get("consistency")!=null) { + if(MusicUtil.isValidConsistency(this.getConsistencyInfo().get("consistency"))) { + queryObject.setConsistency(this.getConsistencyInfo().get("consistency")); + } else { + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR) + .setError("Invalid Consistency type").toMap()).build();*/ + throw new MusicQueryException("Invalid Consistency type", Status.BAD_REQUEST.getStatusCode()); + } + } + + queryObject.setOperation("delete"); + + return queryObject; + } + + + /** + * + * @param keyspace + * @param tablename + * @param rowParams + * @param queryObject + * @return + * @throws MusicServiceException + */ + private RowIdentifier getRowIdentifier(String keyspace, String tablename, + MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject) + throws MusicServiceException { + StringBuilder rowSpec = new StringBuilder(); + int counter = 0; + TableMetadata tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename); + if (tableInfo == null) { + logger.error(EELFLoggerDelegate.errorLogger, + "Table information not found. Please check input for table name= " + + keyspace + "." + tablename); + throw new MusicServiceException( + "Table information not found. Please check input for table name= " + + keyspace + "." + tablename); + } + StringBuilder primaryKey = new StringBuilder(); + for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) { + String keyName = entry.getKey(); + List<String> valueList = entry.getValue(); + String indValue = valueList.get(0); + DataType colType = null; + Object formattedValue = null; + try { + colType = tableInfo.getColumn(entry.getKey()).getType(); + formattedValue = MusicUtil.convertToActualDataType(colType, indValue); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e); + } + if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey())) { + primaryKey.append(indValue); + } + rowSpec.append(keyName + "= ?"); + queryObject.addValue(formattedValue); + if (counter != rowParams.size() - 1) { + rowSpec.append(" AND "); + } + counter = counter + 1; + } + return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject); + } + + private class RowIdentifier { + public String primarKeyValue; + public StringBuilder rowIdString; + @SuppressWarnings("unused") + public PreparedQueryObject queryObject; // the string with all the row + // identifiers separated by AND + + public RowIdentifier(String primaryKeyValue, StringBuilder rowIdString, + PreparedQueryObject queryObject) { + this.primarKeyValue = primaryKeyValue; + this.rowIdString = rowIdString; + this.queryObject = queryObject; + } + } } diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/JsonIndex.java b/src/main/java/org/onap/music/datastore/jsonobjects/JsonIndex.java new file mode 100644 index 00000000..a06e8ea9 --- /dev/null +++ b/src/main/java/org/onap/music/datastore/jsonobjects/JsonIndex.java @@ -0,0 +1,120 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Modifications Copyright (c) 2019 IBM + * =================================================================== + * 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============================================= + * ==================================================================== + */ +package org.onap.music.datastore.jsonobjects; + +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.eelf.logging.EELFLoggerDelegate; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@ApiModel(value = "JsonIndex", description = "Index Object") +public class JsonIndex { + + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonIndex.class); + + private String indexName; + private String keyspaceName; + private String tableName; + private String fieldName; + + public JsonIndex(String indexName,String keyspaceName,String tableName,String fieldName) { + this.indexName = indexName; + this.keyspaceName= keyspaceName; + this.tableName = tableName; + this.fieldName = fieldName; + } + + @ApiModelProperty(value = "Index Name") + public String getIndexName() { + return indexName; + } + + public JsonIndex setIndexName(String indexName) { + this.indexName = indexName; + return this; + } + + @ApiModelProperty(value = "Keyspace name") + public String getKeyspaceName() { + return keyspaceName; + } + + public JsonIndex setKeyspaceName(String keyspaceName) { + this.keyspaceName = keyspaceName; + return this; + } + + public JsonIndex setTableName(String tableName) { + this.tableName = tableName; + return this; + } + + @ApiModelProperty(value = "Table name") + public String getTableName() { + return tableName; + } + + public JsonIndex setFieldName(String fieldName) { + this.fieldName = fieldName; + return this; + } + + @ApiModelProperty(value = "Field name") + public String getFieldName() { + return fieldName; + } + + public PreparedQueryObject genCreateIndexQuery() { + + if (logger.isDebugEnabled()) { + logger.debug("Came inside genCreateIndexQuery method"); + } + + logger.info("genCreateIndexQuery indexName ::" + indexName); + logger.info("genCreateIndexQuery keyspaceName ::" + keyspaceName); + logger.info("genCreateIndexQuery tableName ::" + tableName); + logger.info("genCreateIndexQuery fieldName ::" + fieldName); + + long start = System.currentTimeMillis(); + + PreparedQueryObject query = new PreparedQueryObject(); + query.appendQueryString("Create index if not exists " + this.getIndexName() + " on " + this.getKeyspaceName() + "." + + this.getTableName() + " (" + this.getFieldName() + ");"); + + long end = System.currentTimeMillis(); + + logger.info(EELFLoggerDelegate.applicationLogger, + "Time taken for setting up query in create index:" + (end - start)); + + logger.info(EELFLoggerDelegate.applicationLogger, + " create index query :" + query.getQuery()); + + return query; + } + +} diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java b/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java index 09cd65dc..8e8404b7 100644 --- a/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java +++ b/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java @@ -3,7 +3,7 @@ * org.onap.music * =================================================================== * Copyright (c) 2017 AT&T Intellectual Property - * Modifications Copyright (C) 2018 IBM. + * Modifications Copyright (C) 2019 IBM * =================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,19 +28,32 @@ import java.io.IOException; import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.nio.ByteBuffer; +import java.util.List; import java.util.Map; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response.Status; +import org.onap.music.datastore.MusicDataStoreHandle; +import org.onap.music.datastore.PreparedQueryObject; import org.onap.music.eelf.logging.EELFLoggerDelegate; import org.onap.music.eelf.logging.format.AppMessages; import org.onap.music.eelf.logging.format.ErrorSeverity; import org.onap.music.eelf.logging.format.ErrorTypes; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.main.MusicUtil; +import org.onap.music.main.ReturnType; + +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.TableMetadata; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; -@ApiModel(value = "JsonTable", description = "Json model for table vlaues insert") +@ApiModel(value = "InsertTable", description = "Json model for table vlaues insert") @JsonIgnoreProperties(ignoreUnknown = true) public class JsonInsert implements Serializable { private static final long serialVersionUID = 1L; @@ -52,9 +65,10 @@ public class JsonInsert implements Serializable { private transient Map<String, Object> rowSpecification; private Map<String, String> consistencyInfo; private Map<String, byte[]> objectMap; + private String primaryKeyVal; private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonInsert.class); - @ApiModelProperty(value = "objectMap") + @ApiModelProperty(value = "objectMap",hidden = true) public Map<String, byte[]> getObjectMap() { return objectMap; } @@ -90,7 +104,10 @@ public class JsonInsert implements Serializable { this.consistencyInfo = consistencyInfo; } - @ApiModelProperty(value = "Time to live information") + @ApiModelProperty(value = "Columns and tables support an optional " + + "expiration period called TTL (time-to-live) in seconds.", + notes="TTL precision is one second, which is calculated by the coordinator " + + "node. When using TTL, ensure that all nodes in the cluster have synchronized clocks.",allowEmptyValue = true) public String getTtl() { return ttl; } @@ -99,7 +116,10 @@ public class JsonInsert implements Serializable { this.ttl = ttl; } - @ApiModelProperty(value = "Time stamp") + @ApiModelProperty(value = "Time stamp (epoch_in_microseconds)", + notes = "Marks inserted data (write time) with TIMESTAMP. " + + "Enter the time since epoch (January 1, 1970) in microseconds." + + "By default, the actual time of write is used.", allowEmptyValue = true) public String getTimestamp() { return timestamp; } @@ -108,7 +128,9 @@ public class JsonInsert implements Serializable { this.timestamp = timestamp; } - @ApiModelProperty(value = "values returned") + @ApiModelProperty(value = "Json Object of key/values", notes="Where key is the column name and value is the data value for that column.", + example = "{'emp_id': 'df98a3d40cd6','emp_name': 'john'," + + "'emp_salary': 50,'address':{'street' : '1 Some way','city' : 'New York'}}") public Map<String, Object> getValues() { return values; } @@ -117,7 +139,7 @@ public class JsonInsert implements Serializable { this.values = values; } - @ApiModelProperty(value = "Information for selecting specific rows for insert") + @ApiModelProperty(value = "Information for selecting specific rows for insert",hidden = true) public Map<String, Object> getRowSpecification() { return rowSpecification; } @@ -125,6 +147,14 @@ public class JsonInsert implements Serializable { public void setRowSpecification(Map<String, Object> rowSpecification) { this.rowSpecification = rowSpecification; } + + public String getPrimaryKeyVal() { + return primaryKeyVal; + } + + public void setPrimaryKeyVal(String primaryKeyVal) { + this.primaryKeyVal = primaryKeyVal; + } public byte[] serialize() { ByteArrayOutputStream bos = new ByteArrayOutputStream(); @@ -137,5 +167,267 @@ public class JsonInsert implements Serializable { } return bos.toByteArray(); } + + /** + * Generate TableInsertQuery + * @return + * @throws MusicQueryException + */ + public PreparedQueryObject genInsertPreparedQueryObj() throws MusicQueryException { + if (logger.isDebugEnabled()) { + logger.debug("Coming inside genTableInsertQuery method " + this.getKeyspaceName()); + logger.debug("Coming inside genTableInsertQuery method " + this.getTableName()); + } + + PreparedQueryObject queryObject = new PreparedQueryObject(); + TableMetadata tableInfo = null; + try { + tableInfo = MusicDataStoreHandle.returnColumnMetadata(this.getKeyspaceName(), this.getTableName()); + if(tableInfo == null) { + //return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Table name doesn't exists. Please check the table name.").toMap()).build(); + throw new MusicQueryException("Table name doesn't exists. Please check the table name.", + Status.BAD_REQUEST.getStatusCode()); + } + } catch (MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger, e, AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + //return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); + throw new MusicQueryException(e.getMessage(),Status.BAD_REQUEST.getStatusCode()); + + } + String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName(); + StringBuilder fieldsString = new StringBuilder("(vector_ts,"); + String vectorTs = + String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis()); + StringBuilder valueString = new StringBuilder("(" + "?" + ","); + queryObject.addValue(vectorTs); + + Map<String, Object> valuesMap = this.getValues(); + if (valuesMap==null) { + //return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + //.setError("Nothing to insert. No values provided in request.").toMap()).build(); + throw new MusicQueryException("Nothing to insert. No values provided in request.", + Status.BAD_REQUEST.getStatusCode()); + } + int counter = 0; + String primaryKey = ""; + for (Map.Entry<String, Object> entry : valuesMap.entrySet()) { + fieldsString.append("" + entry.getKey()); + Object valueObj = entry.getValue(); + if (primaryKeyName.equals(entry.getKey())) { + primaryKey = entry.getValue() + ""; + primaryKey = primaryKey.replace("'", "''"); + } + DataType colType = null; + try { + colType = tableInfo.getColumn(entry.getKey()).getType(); + } catch(NullPointerException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() +" Invalid column name : "+entry.getKey + (), AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR, ex); + //return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap()).build(); + throw new MusicQueryException("Invalid column name : " + entry.getKey(), + Status.BAD_REQUEST.getStatusCode()); + } + + Object formattedValue = null; + try { + formattedValue = MusicUtil.convertToActualDataType(colType, valueObj); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e); + } + valueString.append("?"); + + queryObject.addValue(formattedValue); + + if (counter == valuesMap.size() - 1) { + fieldsString.append(")"); + valueString.append(")"); + } else { + fieldsString.append(","); + valueString.append(","); + } + counter = counter + 1; + } + + //blobs.. + Map<String, byte[]> objectMap = this.getObjectMap(); + if(objectMap != null) { + for (Map.Entry<String, byte[]> entry : objectMap.entrySet()) { + if(counter > 0) { + fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ","); + valueString.replace(valueString.length()-1, valueString.length(), ","); + } + fieldsString.append("" + entry.getKey()); + byte[] valueObj = entry.getValue(); + if (primaryKeyName.equals(entry.getKey())) { + primaryKey = entry.getValue() + ""; + primaryKey = primaryKey.replace("'", "''"); + } + DataType colType = tableInfo.getColumn(entry.getKey()).getType(); + ByteBuffer formattedValue = null; + if(colType.toString().toLowerCase().contains("blob")) { + formattedValue = MusicUtil.convertToActualDataType(colType, valueObj); + } + valueString.append("?"); + queryObject.addValue(formattedValue); + counter = counter + 1; + fieldsString.append(","); + valueString.append(","); + } + } + this.setPrimaryKeyVal(primaryKey); + if(primaryKey == null || primaryKey.length() <= 0) { + logger.error(EELFLoggerDelegate.errorLogger, "Some required partition key parts are missing: "+primaryKeyName ); + //return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Some required partition key parts are missing: "+primaryKeyName).toMap()).build(); + throw new MusicQueryException("Some required partition key parts are missing: " + primaryKeyName, + Status.BAD_REQUEST.getStatusCode()); + } + + fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ")"); + valueString.replace(valueString.length()-1, valueString.length(), ")"); + + queryObject.appendQueryString("INSERT INTO " + this.getKeyspaceName() + "." + this.getTableName() + " " + + fieldsString + " VALUES " + valueString); + + String ttl = this.getTtl(); + String timestamp = this.getTimestamp(); + + if ((ttl != null) && (timestamp != null)) { + logger.info(EELFLoggerDelegate.applicationLogger, "both there"); + queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?"); + queryObject.addValue(Integer.parseInt(ttl)); + queryObject.addValue(Long.parseLong(timestamp)); + } + + if ((ttl != null) && (timestamp == null)) { + logger.info(EELFLoggerDelegate.applicationLogger, "ONLY TTL there"); + queryObject.appendQueryString(" USING TTL ?"); + queryObject.addValue(Integer.parseInt(ttl)); + } + + if ((ttl == null) && (timestamp != null)) { + logger.info(EELFLoggerDelegate.applicationLogger, "ONLY timestamp there"); + queryObject.appendQueryString(" USING TIMESTAMP ?"); + queryObject.addValue(Long.parseLong(timestamp)); + } + + queryObject.appendQueryString(";"); + + ReturnType result = null; + String consistency = this.getConsistencyInfo().get("type"); + if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && this.getConsistencyInfo().get("consistency") != null) { + if(MusicUtil.isValidConsistency(this.getConsistencyInfo().get("consistency"))) { + queryObject.setConsistency(this.getConsistencyInfo().get("consistency")); + } else { + // return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build(); + throw new MusicQueryException("Invalid Consistency type", Status.BAD_REQUEST.getStatusCode()); + } + } + queryObject.setOperation("insert"); + + logger.info("Data insert Query ::::: " + queryObject.getQuery()); + + return queryObject; + } + + /** + * + * @param rowParams + * @return + * @throws MusicQueryException + */ + public PreparedQueryObject genSelectCriticalPreparedQueryObj(MultivaluedMap<String, String> rowParams) throws MusicQueryException { + + PreparedQueryObject queryObject = new PreparedQueryObject(); + + if((this.getKeyspaceName() == null || this.getKeyspaceName().isEmpty()) + || (this.getTableName() == null || this.getTableName().isEmpty())){ + /* return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + .setError("one or more path parameters are not set, please check and try again") + .toMap()).build();*/ + throw new MusicQueryException("one or more path parameters are not set, please check and try again", + Status.BAD_REQUEST.getStatusCode()); + } + EELFLoggerDelegate.mdcPut("keyspace", "( "+this.getKeyspaceName()+" ) "); + RowIdentifier rowId = null; + try { + rowId = getRowIdentifier(this.getKeyspaceName(), this.getTableName(), rowParams, queryObject); + this.setPrimaryKeyVal(rowId.primarKeyValue); + } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes + .GENERALSERVICEERROR, ex); + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();*/ + throw new MusicQueryException(ex.getMessage(), Status.BAD_REQUEST.getStatusCode()); + } + + queryObject.appendQueryString( + "SELECT * FROM " + this.getKeyspaceName() + "." + this.getTableName() + " WHERE " + rowId.rowIdString + ";"); + + return queryObject; + } + + private class RowIdentifier { + public String primarKeyValue; + public StringBuilder rowIdString; + @SuppressWarnings("unused") + public PreparedQueryObject queryObject; // the string with all the row + // identifiers separated by AND + + public RowIdentifier(String primaryKeyValue, StringBuilder rowIdString, + PreparedQueryObject queryObject) { + this.primarKeyValue = primaryKeyValue; + this.rowIdString = rowIdString; + this.queryObject = queryObject; + } + } + + /** + * + * @param keyspace + * @param tablename + * @param rowParams + * @param queryObject + * @return + * @throws MusicServiceException + */ + private RowIdentifier getRowIdentifier(String keyspace, String tablename, + MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject) + throws MusicServiceException { + StringBuilder rowSpec = new StringBuilder(); + int counter = 0; + TableMetadata tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename); + if (tableInfo == null) { + logger.error(EELFLoggerDelegate.errorLogger, + "Table information not found. Please check input for table name= " + + keyspace + "." + tablename); + throw new MusicServiceException( + "Table information not found. Please check input for table name= " + + keyspace + "." + tablename); + } + StringBuilder primaryKey = new StringBuilder(); + for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) { + String keyName = entry.getKey(); + List<String> valueList = entry.getValue(); + String indValue = valueList.get(0); + DataType colType = null; + Object formattedValue = null; + try { + colType = tableInfo.getColumn(entry.getKey()).getType(); + formattedValue = MusicUtil.convertToActualDataType(colType, indValue); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e); + } + if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey())) { + primaryKey.append(indValue); + } + rowSpec.append(keyName + "= ?"); + queryObject.addValue(formattedValue); + if (counter != rowParams.size() - 1) { + rowSpec.append(" AND "); + } + counter = counter + 1; + } + return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject); + } + } diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/JsonKeySpace.java b/src/main/java/org/onap/music/datastore/jsonobjects/JsonKeySpace.java index f2232ffd..cada1c00 100644 --- a/src/main/java/org/onap/music/datastore/jsonobjects/JsonKeySpace.java +++ b/src/main/java/org/onap/music/datastore/jsonobjects/JsonKeySpace.java @@ -4,6 +4,8 @@ * =================================================================== * Copyright (c) 2017 AT&T Intellectual Property * =================================================================== + * Modifications Copyright (C) 2019 IBM + * =================================================================== * 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 @@ -24,6 +26,16 @@ package org.onap.music.datastore.jsonobjects; import java.util.Map; +import javax.ws.rs.core.Response.Status; + +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.main.MusicUtil; + import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import io.swagger.annotations.ApiModel; @@ -32,6 +44,7 @@ import io.swagger.annotations.ApiModelProperty; @ApiModel(value = "JsonTable", description = "Json model creating new keyspace") @JsonIgnoreProperties(ignoreUnknown = true) public class JsonKeySpace { + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonKeySpace.class); private String keyspaceName; private Map<String, Object> replicationInfo; private String durabilityOfWrites; @@ -73,6 +86,78 @@ public class JsonKeySpace { this.keyspaceName = keyspaceName; } + /** + * Will generate query to create Keyspacce. + * + * @throws MusicQueryException + */ + @SuppressWarnings("deprecation") + public PreparedQueryObject genCreateKeyspaceQuery() throws MusicQueryException { + + if (logger.isDebugEnabled()) { + logger.debug("Came inside createKeyspace method"); + } + + String keyspaceName = this.getKeyspaceName(); + String durabilityOfWrites = this.getDurabilityOfWrites(); + String consistency = MusicUtil.EVENTUAL; + + logger.info("genCreateKeyspaceQuery keyspaceName ::" + keyspaceName); + logger.info("genCreateKeyspaceQuery class :: " + this.getReplicationInfo().get("class")); + logger.info("genCreateKeyspaceQuery replication_factor :: " + this.getReplicationInfo().get("replication_factor")); + logger.info("genCreateKeyspaceQuery durabilityOfWrites :: " + durabilityOfWrites); + + PreparedQueryObject queryObject = new PreparedQueryObject(); + + if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && this.getConsistencyInfo().get("consistency") != null) { + if(MusicUtil.isValidConsistency(this.getConsistencyInfo().get("consistency"))) { + queryObject.setConsistency(this.getConsistencyInfo().get("consistency")); + }else { + throw new MusicQueryException("Invalid Consistency type",Status.BAD_REQUEST.getStatusCode()); + } + } + + long start = System.currentTimeMillis(); + Map<String, Object> replicationInfo = this.getReplicationInfo(); + String repString = null; + try { + repString = "{" + MusicUtil.jsonMaptoSqlString(replicationInfo, ",") + "}"; + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), AppMessages.MISSINGDATA, + ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); + } + queryObject.appendQueryString("CREATE KEYSPACE " + keyspaceName + " WITH replication = " + repString); + if (this.getDurabilityOfWrites() != null) { + queryObject.appendQueryString(" AND durable_writes = " + this.getDurabilityOfWrites()); + } + queryObject.appendQueryString(";"); + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger, + "Time taken for setting up query in create keyspace:" + (end - start)); + + return queryObject; + } + + /** + * Will generate Query to drop a keyspace. + * + * @return + */ + public PreparedQueryObject genDropKeyspaceQuery() { + if (logger.isDebugEnabled()) { + logger.debug("Coming inside genDropKeyspaceQuery method "+this.getKeyspaceName()); + } + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString("DROP KEYSPACE " + this.getKeyspaceName() + ";"); + + return queryObject; + } + + @Override + public String toString() { + return "CassaKeyspaceObject [keyspaceName=" + keyspaceName + ", replicationInfo=" + replicationInfo + + "durabilityOfWrites=" + durabilityOfWrites + "]"; + } } diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/JsonLeasedLock.java b/src/main/java/org/onap/music/datastore/jsonobjects/JsonLeasedLock.java index edb30857..86bbe3dc 100644 --- a/src/main/java/org/onap/music/datastore/jsonobjects/JsonLeasedLock.java +++ b/src/main/java/org/onap/music/datastore/jsonobjects/JsonLeasedLock.java @@ -27,11 +27,10 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; -@ApiModel(value = "JsonTable", description = "model for leased lock") +@ApiModel(value = "Json Leasesd Lock", description = "model for leased lock") @JsonIgnoreProperties(ignoreUnknown = true) public class JsonLeasedLock { private long leasePeriod; - private String notifyUrl; @ApiModelProperty(value = "Lease period") public long getLeasePeriod() { @@ -42,12 +41,4 @@ public class JsonLeasedLock { this.leasePeriod = leasePeriod; } - @ApiModelProperty(value = "URL to be notified") - public String getNotifyUrl() { - return notifyUrl; - } - - public void setNotifyUrl(String notifyUrl) { - this.notifyUrl = notifyUrl; - } } diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/JsonLock.java b/src/main/java/org/onap/music/datastore/jsonobjects/JsonLock.java index 88e1c3f3..f353c018 100644 --- a/src/main/java/org/onap/music/datastore/jsonobjects/JsonLock.java +++ b/src/main/java/org/onap/music/datastore/jsonobjects/JsonLock.java @@ -29,12 +29,16 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; -@ApiModel(value = "JsonTable", description = "model for leased lock") +@ApiModel(value = "Json Lock Type", description = "Model for Lock Type") @JsonIgnoreProperties(ignoreUnknown = true) public class JsonLock { private LockType locktype; - @ApiModelProperty(value = "Type of music lock") + @ApiModelProperty( + value = "Type of music lock", + name = "lockType", + allowEmptyValue = false, + allowableValues = "READ|WRITE") public LockType getLocktype() { return this.locktype; } diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/JsonOnboard.java b/src/main/java/org/onap/music/datastore/jsonobjects/JsonOnboard.java deleted file mode 100755 index 5b3bbd48..00000000 --- a/src/main/java/org/onap/music/datastore/jsonobjects/JsonOnboard.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * ============LICENSE_START========================================== - * org.onap.music - * =================================================================== - * Copyright (c) 2017 AT&T Intellectual Property - * =================================================================== - * 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============================================= - * ==================================================================== - */ - -package org.onap.music.datastore.jsonobjects; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; - -@ApiModel(value = "JsonOnboard", description = "Defines the Json for Onboarding an application.") -@JsonIgnoreProperties(ignoreUnknown = true) -public class JsonOnboard { - private String appname; - private String userId; - private String password; - private String isAAF; - private String aid; - private String keyspace; - - @ApiModelProperty(value = "Application Keyspace") - public String getKeyspace() { - return keyspace; - } - - public void setKeyspace_name(String keyspace) { - this.keyspace = keyspace; - } - - @ApiModelProperty(value = "Application Password") - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - @ApiModelProperty(value = "Application UUID") - public String getAid() { - return aid; - } - - public void setAid(String aid) { - this.aid = aid; - } - - @ApiModelProperty(value = "Application name") - public String getAppname() { - return appname; - } - - public void setAppname(String appname) { - this.appname = appname; - } - - @ApiModelProperty(value = "User Id") - public String getUserId() { - return userId; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - @ApiModelProperty(value = "Is AAF Application", allowableValues = "true, false") - public String getIsAAF() { - return isAAF; - } - - public void setIsAAF(String isAAF) { - this.isAAF = isAAF; - } - -} diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/JsonSelect.java b/src/main/java/org/onap/music/datastore/jsonobjects/JsonSelect.java index faef9b8f..4d4ab2ac 100644 --- a/src/main/java/org/onap/music/datastore/jsonobjects/JsonSelect.java +++ b/src/main/java/org/onap/music/datastore/jsonobjects/JsonSelect.java @@ -3,7 +3,7 @@ * org.onap.music * =================================================================== * Copyright (c) 2017 AT&T Intellectual Property - * Modifications Copyright (C) 2018 IBM. + * Modifications Copyright (C) 2019 IBM * =================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,13 +28,33 @@ import java.io.IOException; import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.util.List; import java.util.Map; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response.Status; + +import org.onap.music.datastore.MusicDataStoreHandle; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.main.MusicUtil; + +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.TableMetadata; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) public class JsonSelect implements Serializable { private Map<String, String> consistencyInfo; + private String keyspaceName; + private String tableName; + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonSelect.class); + public Map<String, String> getConsistencyInfo() { @@ -44,6 +64,22 @@ public class JsonSelect implements Serializable { public void setConsistencyInfo(Map<String, String> consistencyInfo) { this.consistencyInfo = consistencyInfo; } + + public String getKeyspaceName() { + return keyspaceName; + } + + public void setKeyspaceName(String keyspaceName) { + this.keyspaceName = keyspaceName; + } + + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } public byte[] serialize() { ByteArrayOutputStream bos = new ByteArrayOutputStream(); @@ -52,10 +88,121 @@ public class JsonSelect implements Serializable { out = new ObjectOutputStream(bos); out.writeObject(this); } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + logger.error("IOException occured {}",e.getMessage()); } return bos.toByteArray(); } + + /** + * genSelectQuery + * + * @return + * @throws MusicQueryException + */ + public PreparedQueryObject genSelectQuery(MultivaluedMap<String, String> rowParams) throws MusicQueryException { + + if((this.getKeyspaceName() == null || this.getKeyspaceName().isEmpty()) + || (this.getTableName() == null || this.getTableName().isEmpty())){ + throw new MusicQueryException("one or more path parameters are not set, please check and try again", + Status.BAD_REQUEST.getStatusCode()); + } + EELFLoggerDelegate.mdcPut("keyspace", "( " + this.getKeyspaceName() + " ) "); + PreparedQueryObject queryObject = new PreparedQueryObject(); + + if (rowParams.isEmpty()) { // select all + queryObject.appendQueryString("SELECT * FROM " + this.getKeyspaceName() + "." + this.getTableName() + ";"); + } else { + int limit = -1; // do not limit the number of results + try { + queryObject = selectSpecificQuery(this.getKeyspaceName(), this.getTableName(), rowParams, limit); + } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, + ErrorTypes.GENERALSERVICEERROR, ex); + + throw new MusicQueryException(ex.getMessage(), Status.BAD_REQUEST.getStatusCode()); + } + } + + return queryObject; + } + + public PreparedQueryObject selectSpecificQuery(String keyspace, + String tablename, MultivaluedMap<String, String> rowParams, int limit) + throws MusicServiceException { + PreparedQueryObject queryObject = new PreparedQueryObject(); + StringBuilder rowIdString = getRowIdentifier(keyspace, + tablename,rowParams,queryObject).rowIdString; + queryObject.appendQueryString( + "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowIdString); + if (limit != -1) { + queryObject.appendQueryString(" LIMIT " + limit); + } + queryObject.appendQueryString(";"); + return queryObject; + } + + private class RowIdentifier { + public String primarKeyValue; + public StringBuilder rowIdString; + @SuppressWarnings("unused") + public PreparedQueryObject queryObject; // the string with all the row + // identifiers separated by AND + + public RowIdentifier(String primaryKeyValue, StringBuilder rowIdString, + PreparedQueryObject queryObject) { + this.primarKeyValue = primaryKeyValue; + this.rowIdString = rowIdString; + this.queryObject = queryObject; + } + } + + /** + * + * @param keyspace + * @param tablename + * @param rowParams + * @param queryObject + * @return + * @throws MusicServiceException + */ + private RowIdentifier getRowIdentifier(String keyspace, String tablename, + MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject) + throws MusicServiceException { + StringBuilder rowSpec = new StringBuilder(); + int counter = 0; + TableMetadata tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename); + if (tableInfo == null) { + logger.error(EELFLoggerDelegate.errorLogger, + "Table information not found. Please check input for table name= " + + keyspace + "." + tablename); + throw new MusicServiceException( + "Table information not found. Please check input for table name= " + + keyspace + "." + tablename); + } + StringBuilder primaryKey = new StringBuilder(); + for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) { + String keyName = entry.getKey(); + List<String> valueList = entry.getValue(); + String indValue = valueList.get(0); + DataType colType = null; + Object formattedValue = null; + try { + colType = tableInfo.getColumn(entry.getKey()).getType(); + formattedValue = MusicUtil.convertToActualDataType(colType, indValue); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e); + } + if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey())) { + primaryKey.append(indValue); + } + rowSpec.append(keyName + "= ?"); + queryObject.addValue(formattedValue); + if (counter != rowParams.size() - 1) { + rowSpec.append(" AND "); + } + counter = counter + 1; + } + return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject); + } } diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/JsonTable.java b/src/main/java/org/onap/music/datastore/jsonobjects/JsonTable.java index badcaebe..83b5a7a5 100644 --- a/src/main/java/org/onap/music/datastore/jsonobjects/JsonTable.java +++ b/src/main/java/org/onap/music/datastore/jsonobjects/JsonTable.java @@ -4,6 +4,8 @@ * =================================================================== * Copyright (c) 2017 AT&T Intellectual Property * =================================================================== + * Modifications Copyright (C) 2019 IBM + * =================================================================== * 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 @@ -24,6 +26,14 @@ package org.onap.music.datastore.jsonobjects; import java.util.Map; +import javax.ws.rs.core.Response.Status; + +import org.apache.commons.lang3.StringUtils; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.main.MusicUtil; + import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import io.swagger.annotations.ApiModel; @@ -32,6 +42,8 @@ import io.swagger.annotations.ApiModelProperty; @ApiModel(value = "JsonTable", description = "Defines the Json for Creating a new Table.") @JsonIgnoreProperties(ignoreUnknown = true) public class JsonTable { + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonTable.class); + private String keyspaceName; private String tableName; @@ -130,6 +142,245 @@ public class JsonTable { public void setPartitionKey(String partitionKey) { this.partitionKey = partitionKey; } + + public PreparedQueryObject genCreateTableQuery() throws MusicQueryException { + if (logger.isDebugEnabled()) { + logger.debug("Coming inside genCreateTableQuery method " + this.getKeyspaceName()); + logger.debug("Coming inside genCreateTableQuery method " + this.getTableName()); + } + + String primaryKey = null; + String partitionKey = this.getPartitionKey(); + String clusterKey = this.getClusteringKey(); + String filteringKey = this.getFilteringKey(); + if (filteringKey != null) { + clusterKey = clusterKey + "," + filteringKey; + } + primaryKey = this.getPrimaryKey(); // get primaryKey if available + + PreparedQueryObject queryObject = new PreparedQueryObject(); + // first read the information about the table fields + Map<String, String> fields = this.getFields(); + if (fields == null) { + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + .setError("Create Table Error: No fields in request").toMap()).build();*/ + throw new MusicQueryException( + "Create Table Error: No fields in request", Status.BAD_REQUEST.getStatusCode()); + } + StringBuilder fieldsString = new StringBuilder("(vector_ts text,"); + int counter = 0; + for (Map.Entry<String, String> entry : fields.entrySet()) { + if (entry.getKey().equals("PRIMARY KEY")) { + primaryKey = entry.getValue(); // replaces primaryKey + primaryKey = primaryKey.trim(); + } else { + if (counter == 0 ) fieldsString.append("" + entry.getKey() + " " + entry.getValue() + ""); + else fieldsString.append("," + entry.getKey() + " " + entry.getValue() + ""); + } + + if (counter != (fields.size() - 1) ) { + counter = counter + 1; + } else { + + if((primaryKey != null) && (partitionKey == null)) { + primaryKey = primaryKey.trim(); + int count1 = StringUtils.countMatches(primaryKey, ')'); + int count2 = StringUtils.countMatches(primaryKey, '('); + if (count1 != count2) { + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + .setError("Create Table Error: primary key '(' and ')' do not match, primary key=" + primaryKey) + .toMap()).build();*/ + throw new MusicQueryException( + "Create Table Error: primary key '(' and ')' do not match, primary key=" + primaryKey, + Status.BAD_REQUEST.getStatusCode()); + } + + if ( primaryKey.indexOf('(') == -1 || ( count2 == 1 && (primaryKey.lastIndexOf(')') +1) == primaryKey.length() ) ) { + if (primaryKey.contains(",") ) { + partitionKey= primaryKey.substring(0,primaryKey.indexOf(',')); + partitionKey=partitionKey.replaceAll("[\\(]+",""); + clusterKey=primaryKey.substring(primaryKey.indexOf(',')+1); // make sure index + clusterKey=clusterKey.replaceAll("[)]+", ""); + } else { + partitionKey=primaryKey; + partitionKey=partitionKey.replaceAll("[\\)]+",""); + partitionKey=partitionKey.replaceAll("[\\(]+",""); + clusterKey=""; + } + } else { // not null and has ) before the last char + partitionKey= primaryKey.substring(0,primaryKey.indexOf(')')); + partitionKey=partitionKey.replaceAll("[\\(]+",""); + partitionKey = partitionKey.trim(); + clusterKey= primaryKey.substring(primaryKey.indexOf(')')); + clusterKey=clusterKey.replaceAll("[\\(]+",""); + clusterKey=clusterKey.replaceAll("[\\)]+",""); + clusterKey = clusterKey.trim(); + if (clusterKey.indexOf(',') == 0) { + clusterKey=clusterKey.substring(1); + } + clusterKey = clusterKey.trim(); + if (clusterKey.equals(",") ) clusterKey=""; // print error if needed ( ... ),) + } + + if (!(partitionKey.isEmpty() || clusterKey.isEmpty()) + && (partitionKey.equalsIgnoreCase(clusterKey) || + clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) { + logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey + " and primary key=" + primaryKey ); + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError( + "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ") of" + + " primary key=" + primaryKey) + .toMap()).build();*/ + throw new MusicQueryException("Create Table primary key error: clusterKey(" + clusterKey + + ") equals/contains/overlaps partitionKey(" + partitionKey + ") of" + " primary key=" + + primaryKey, Status.BAD_REQUEST.getStatusCode()); + + } + + if (partitionKey.isEmpty() ) primaryKey=""; + else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")"; + else primaryKey=" (" + partitionKey + ")," + clusterKey; + + + if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )"); + + } else { // end of length > 0 + + if (!(partitionKey.isEmpty() || clusterKey.isEmpty()) + && (partitionKey.equalsIgnoreCase(clusterKey) || + clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) { + logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey); + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError( + "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ")") + .toMap()).build();*/ + throw new MusicQueryException( + "Create Table primary key error: clusterKey(" + clusterKey + + ") equals/contains/overlaps partitionKey(" + partitionKey + ")", + Status.BAD_REQUEST.getStatusCode()); + } + + if (partitionKey.isEmpty() ) primaryKey=""; + else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")"; + else primaryKey=" (" + partitionKey + ")," + clusterKey; + + if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )"); + } + fieldsString.append(")"); + + } // end of last field check + + } // end of for each + // information about the name-value style properties + Map<String, Object> propertiesMap = this.getProperties(); + StringBuilder propertiesString = new StringBuilder(); + if (propertiesMap != null) { + counter = 0; + for (Map.Entry<String, Object> entry : propertiesMap.entrySet()) { + Object ot = entry.getValue(); + String value = ot + ""; + if (ot instanceof String) { + value = "'" + value + "'"; + } else if (ot instanceof Map) { + @SuppressWarnings("unchecked") + Map<String, Object> otMap = (Map<String, Object>) ot; + try { + value = "{" + MusicUtil.jsonMaptoSqlString(otMap, ",") + "}"; + } catch (Exception e) { + throw new MusicQueryException(e.getMessage(), + Status.BAD_REQUEST.getStatusCode()); + } + } + + propertiesString.append(entry.getKey() + "=" + value + ""); + if (counter != propertiesMap.size() - 1) + propertiesString.append(" AND "); + + counter = counter + 1; + } + } + + String clusteringOrder = this.getClusteringOrder(); + + if (clusteringOrder != null && !(clusteringOrder.isEmpty())) { + String[] arrayClusterOrder = clusteringOrder.split("[,]+"); + + for (int i = 0; i < arrayClusterOrder.length; i++) { + String[] clusterS = arrayClusterOrder[i].trim().split("[ ]+"); + if ( (clusterS.length ==2) && (clusterS[1].equalsIgnoreCase("ASC") || clusterS[1].equalsIgnoreCase("DESC"))) { + continue; + } else { + /*return response.status(Status.BAD_REQUEST) + .entity(new JsonResponse(ResultType.FAILURE) + .setError("createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname order; please correct clusteringOrder:"+ clusteringOrder+".") + .toMap()).build();*/ + + throw new MusicQueryException( + "createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname order; please correct clusteringOrder:" + + clusteringOrder + ".", + Status.BAD_REQUEST.getStatusCode()); + } + // add validation for column names in cluster key + } + + if (!(clusterKey.isEmpty())) { + clusteringOrder = "CLUSTERING ORDER BY (" +clusteringOrder +")"; + //cjc check if propertiesString.length() >0 instead propertiesMap + if (propertiesMap != null) { + propertiesString.append(" AND "+ clusteringOrder); + } else { + propertiesString.append(clusteringOrder); + } + } else { + logger.warn("Skipping clustering order=("+clusteringOrder+ ") since clustering key is empty "); + } + } //if non empty + + queryObject.appendQueryString( + "CREATE TABLE " + this.getKeyspaceName() + "." + this.getTableName() + " " + fieldsString); + + + if (propertiesString != null && propertiesString.length()>0 ) + queryObject.appendQueryString(" WITH " + propertiesString); + queryObject.appendQueryString(";"); + + return queryObject; + } + + /** + * + * @return + */ + public PreparedQueryObject genCreateShadowLockingTableQuery() { + if (logger.isDebugEnabled()) { + logger.debug("Coming inside genCreateShadowLockingTableQuery method " + this.getKeyspaceName()); + logger.debug("Coming inside genCreateShadowLockingTableQuery method " + this.getTableName()); + } + + String tableName = "unsyncedKeys_" + this.getTableName(); + String tabQuery = "CREATE TABLE IF NOT EXISTS " + this.getKeyspaceName() + "." + tableName + + " ( key text,PRIMARY KEY (key) );"; + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString(tabQuery); + + return queryObject; + } + + /** + * genDropTableQuery + * + * @return PreparedQueryObject + */ + public PreparedQueryObject genDropTableQuery() { + if (logger.isDebugEnabled()) { + logger.debug("Coming inside genDropTableQuery method " + this.getKeyspaceName()); + logger.debug("Coming inside genDropTableQuery method " + this.getTableName()); + } + + PreparedQueryObject query = new PreparedQueryObject(); + query.appendQueryString("DROP TABLE " + this.getKeyspaceName() + "." + this.getTableName() + ";"); + logger.info("Delete Query ::::: " + query.getQuery()); + + return query; + } } diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/JsonUpdate.java b/src/main/java/org/onap/music/datastore/jsonobjects/JsonUpdate.java index e31c6ccf..12508de0 100644 --- a/src/main/java/org/onap/music/datastore/jsonobjects/JsonUpdate.java +++ b/src/main/java/org/onap/music/datastore/jsonobjects/JsonUpdate.java @@ -3,7 +3,7 @@ * org.onap.music * =================================================================== * Copyright (c) 2017 AT&T Intellectual Property - * Modifications Copyright (C) 2018 IBM. + * Modifications Copyright (C) 2019 IBM * =================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,17 +28,31 @@ import java.io.IOException; import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.util.List; import java.util.Map; +import java.util.UUID; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response.Status; +import org.onap.music.datastore.Condition; +import org.onap.music.datastore.MusicDataStoreHandle; +import org.onap.music.datastore.PreparedQueryObject; import org.onap.music.eelf.logging.EELFLoggerDelegate; import org.onap.music.eelf.logging.format.AppMessages; import org.onap.music.eelf.logging.format.ErrorSeverity; import org.onap.music.eelf.logging.format.ErrorTypes; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.main.MusicUtil; +import org.onap.music.main.ReturnType; + +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.TableMetadata; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; @ApiModel(value = "JsonTable", description = "Json model for table update") @JsonIgnoreProperties(ignoreUnknown = true) @@ -51,6 +65,8 @@ public class JsonUpdate implements Serializable { private Map<String, String> consistencyInfo; private transient Map<String, Object> conditions; private transient Map<String, Object> rowSpecification; + private StringBuilder rowIdString; + private String primarKeyValue; private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonUpdate.class); @ApiModelProperty(value = "Conditions") @@ -125,6 +141,22 @@ public class JsonUpdate implements Serializable { public void setValues(Map<String, Object> values) { this.values = values; } + + public StringBuilder getRowIdString() { + return rowIdString; + } + + public void setRowIdString(StringBuilder rowIdString) { + this.rowIdString = rowIdString; + } + + public String getPrimarKeyValue() { + return primarKeyValue; + } + + public void setPrimarKeyValue(String primarKeyValue) { + this.primarKeyValue = primarKeyValue; + } public byte[] serialize() { ByteArrayOutputStream bos = new ByteArrayOutputStream(); @@ -137,5 +169,248 @@ public class JsonUpdate implements Serializable { } return bos.toByteArray(); } + + /** + * Generate TableInsertQuery + * @return + * @throws MusicQueryException + */ + public PreparedQueryObject genUpdatePreparedQueryObj(MultivaluedMap<String, String> rowParams) throws MusicQueryException { + if (logger.isDebugEnabled()) { + logger.debug("Coming inside genUpdatePreparedQueryObj method " + this.getKeyspaceName()); + logger.debug("Coming inside genUpdatePreparedQueryObj method " + this.getTableName()); + } + + PreparedQueryObject queryObject = new PreparedQueryObject(); + + if((this.getKeyspaceName() == null || this.getKeyspaceName().isEmpty()) || + (this.getTableName() == null || this.getTableName().isEmpty())){ + + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + .setError("one or more path parameters are not set, please check and try again") + .toMap()).build();*/ + + throw new MusicQueryException("one or more path parameters are not set, please check and try again", + Status.BAD_REQUEST.getStatusCode()); + } + + EELFLoggerDelegate.mdcPut("keyspace", "( "+this.getKeyspaceName()+" ) "); + long startTime = System.currentTimeMillis(); + String operationId = UUID.randomUUID().toString(); // just for infoging purposes. + String consistency = this.getConsistencyInfo().get("type"); + + logger.info(EELFLoggerDelegate.applicationLogger, "--------------Music " + consistency + + " update-" + operationId + "-------------------------"); + // obtain the field value pairs of the update + + Map<String, Object> valuesMap = this.getValues(); + + TableMetadata tableInfo; + + try { + tableInfo = MusicDataStoreHandle.returnColumnMetadata(this.getKeyspaceName(), this.getTableName()); + } catch (MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes + .GENERALSERVICEERROR, e); + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();*/ + throw new MusicQueryException(e.getMessage(), Status.BAD_REQUEST.getStatusCode()); + }catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e, AppMessages.UNKNOWNERROR, ErrorSeverity.CRITICAL, + ErrorTypes.GENERALSERVICEERROR); + throw new MusicQueryException(e.getMessage(), Status.BAD_REQUEST.getStatusCode()); + } + + if (tableInfo == null) { + logger.error(EELFLoggerDelegate.errorLogger,"Table information not found. Please check input for table name= "+this.getTableName(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); + + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + .setError("Table information not found. Please check input for table name= " + + this.getKeyspaceName() + "." + this.getTableName()).toMap()).build();*/ + + throw new MusicQueryException("Table information not found. Please check input for table name= " + + this.getKeyspaceName() + "." + this.getTableName(), Status.BAD_REQUEST.getStatusCode()); + } + + String vectorTs = String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis()); + StringBuilder fieldValueString = new StringBuilder("vector_ts=?,"); + queryObject.addValue(vectorTs); + int counter = 0; + for (Map.Entry<String, Object> entry : valuesMap.entrySet()) { + Object valueObj = entry.getValue(); + DataType colType = null; + try { + colType = tableInfo.getColumn(entry.getKey()).getType(); + } catch(NullPointerException ex) { + logger.error(EELFLoggerDelegate.errorLogger, ex, "Invalid column name : "+entry.getKey(), ex); + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE). + * setError("Invalid column name : "+entry.getKey()).toMap()).build();*/ + + throw new MusicQueryException("Invalid column name : " + entry.getKey(),Status.BAD_REQUEST.getStatusCode()); + } + Object valueString = null; + try { + valueString = MusicUtil.convertToActualDataType(colType, valueObj); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e); + } + fieldValueString.append(entry.getKey() + "= ?"); + queryObject.addValue(valueString); + if (counter != valuesMap.size() - 1) { + fieldValueString.append(","); + } + counter = counter + 1; + } + String ttl = this.getTtl(); + String timestamp = this.getTimestamp(); + + queryObject.appendQueryString("UPDATE " + this.getKeyspaceName() + "." + this.getTableName() + " "); + if ((ttl != null) && (timestamp != null)) { + logger.info("both there"); + queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?"); + queryObject.addValue(Integer.parseInt(ttl)); + queryObject.addValue(Long.parseLong(timestamp)); + } + + if ((ttl != null) && (timestamp == null)) { + logger.info("ONLY TTL there"); + queryObject.appendQueryString(" USING TTL ?"); + queryObject.addValue(Integer.parseInt(ttl)); + } + + if ((ttl == null) && (timestamp != null)) { + logger.info("ONLY timestamp there"); + queryObject.appendQueryString(" USING TIMESTAMP ?"); + queryObject.addValue(Long.parseLong(timestamp)); + } + + // get the row specifier + RowIdentifier rowId = null; + try { + rowId = getRowIdentifier(this.getKeyspaceName(), this.getTableName(), rowParams, queryObject); + this.setRowIdString(rowId.rowIdString); + this.setPrimarKeyValue(rowId.primarKeyValue); + if(rowId == null || rowId.primarKeyValue.isEmpty()) { + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + .setError("Mandatory WHERE clause is missing. Please check the input request.").toMap()).build();*/ + + throw new MusicQueryException("Mandatory WHERE clause is missing. Please check the input request.", + Status.BAD_REQUEST.getStatusCode()); + } + } catch (MusicQueryException ex) { + throw new MusicQueryException("Mandatory WHERE clause is missing. Please check the input request.", + Status.BAD_REQUEST.getStatusCode()); + + }catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes + .GENERALSERVICEERROR, ex); + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();*/ + + throw new MusicQueryException(ex.getMessage(), Status.BAD_REQUEST.getStatusCode()); + + } + + + + queryObject.appendQueryString( + " SET " + fieldValueString + " WHERE " + rowId.rowIdString + ";"); + + + + // get the conditional, if any + Condition conditionInfo; + if (this.getConditions() == null) { + conditionInfo = null; + } else { + // to avoid parsing repeatedly, just send the select query to obtain row + PreparedQueryObject selectQuery = new PreparedQueryObject(); + selectQuery.appendQueryString("SELECT * FROM " + this.getKeyspaceName() + "." + this.getTableName() + " WHERE " + + rowId.rowIdString + ";"); + selectQuery.addValue(rowId.primarKeyValue); + conditionInfo = new Condition(this.getConditions(), selectQuery); + } + + ReturnType operationResult = null; + long jsonParseCompletionTime = System.currentTimeMillis(); + + if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && this.getConsistencyInfo().get("consistency") != null) { + if(MusicUtil.isValidConsistency(this.getConsistencyInfo().get("consistency"))) { + queryObject.setConsistency(this.getConsistencyInfo().get("consistency")); + } else { + /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR) + .setError("Invalid Consistency type").toMap()).build();*/ + + logger.error("Invalid Consistency type"); + throw new MusicQueryException("Invalid Consistency type", Status.BAD_REQUEST.getStatusCode()); + } + } + + queryObject.setOperation("update"); + + return queryObject; + } + + private class RowIdentifier { + public String primarKeyValue; + public StringBuilder rowIdString; + @SuppressWarnings("unused") + public PreparedQueryObject queryObject; // the string with all the row + // identifiers separated by AND + + public RowIdentifier(String primaryKeyValue, StringBuilder rowIdString, + PreparedQueryObject queryObject) { + this.primarKeyValue = primaryKeyValue; + this.rowIdString = rowIdString; + this.queryObject = queryObject; + } + } + + /** + * + * @param keyspace + * @param tablename + * @param rowParams + * @param queryObject + * @return + * @throws MusicServiceException + */ + private RowIdentifier getRowIdentifier(String keyspace, String tablename, + MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject) + throws MusicServiceException { + StringBuilder rowSpec = new StringBuilder(); + int counter = 0; + TableMetadata tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename); + if (tableInfo == null) { + logger.error(EELFLoggerDelegate.errorLogger, + "Table information not found. Please check input for table name= " + + keyspace + "." + tablename); + throw new MusicServiceException( + "Table information not found. Please check input for table name= " + + keyspace + "." + tablename); + } + StringBuilder primaryKey = new StringBuilder(); + for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) { + String keyName = entry.getKey(); + List<String> valueList = entry.getValue(); + String indValue = valueList.get(0); + DataType colType = null; + Object formattedValue = null; + try { + colType = tableInfo.getColumn(entry.getKey()).getType(); + formattedValue = MusicUtil.convertToActualDataType(colType, indValue); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e); + } + if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey())) { + primaryKey.append(indValue); + } + rowSpec.append(keyName + "= ?"); + queryObject.addValue(formattedValue); + if (counter != rowParams.size() - 1) { + rowSpec.append(" AND "); + } + counter = counter + 1; + } + return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject); + } } diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/MusicResponse.java b/src/main/java/org/onap/music/datastore/jsonobjects/MusicResponse.java deleted file mode 100644 index 97131fd7..00000000 --- a/src/main/java/org/onap/music/datastore/jsonobjects/MusicResponse.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * ============LICENSE_START========================================== - * org.onap.music - * =================================================================== - * Copyright (c) 2017 AT&T Intellectual Property - * =================================================================== - * 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============================================= - * ==================================================================== - */ -package org.onap.music.datastore.jsonobjects; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -import org.onap.music.rest.Application; - -public class MusicResponse implements Serializable { - - /** - * - */ - private static final long serialVersionUID = 1L; - private List<Application> applicationList = new ArrayList<>(); - private String message; - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } - - private String status; - - public void setSucces(boolean isSucces) { - this.isSucces = isSucces; - } - - private boolean isSucces; - - public boolean isSucces() { - return isSucces; - } - - public void setisSucces(boolean isSucces) { - this.isSucces = isSucces; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public List<Application> getApplicationList() { - return applicationList; - } - - public void setApplicationList(List<Application> applicationList) { - this.applicationList = applicationList; - } - - public void setResposne(String status, String message) { - this.status = status; - this.message = message; - } - - public void addAppToList(Application app) { - applicationList.add(app); - } -} diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/NameSpace.java b/src/main/java/org/onap/music/datastore/jsonobjects/NameSpace.java deleted file mode 100644 index 3c18c791..00000000 --- a/src/main/java/org/onap/music/datastore/jsonobjects/NameSpace.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * ============LICENSE_START========================================== - * org.onap.music - * =================================================================== - * Copyright (c) 2017 AT&T Intellectual Property - * =================================================================== - * 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============================================= - * ==================================================================== - */ - -package org.onap.music.datastore.jsonobjects; - -import java.util.List; - - -public class NameSpace { - private String name; - private List<String> admin; - - public List<String> getAdmin() { - return admin; - } - - public String getName() { - return name; - } - - public void setAdmin(List<String> admin) { - this.admin = admin; - } - - public void setName(String name) { - this.name = name; - } - -} diff --git a/src/main/java/org/onap/music/eelf/healthcheck/MusicHealthCheck.java b/src/main/java/org/onap/music/eelf/healthcheck/MusicHealthCheck.java index df6cc265..cf4b2bc9 100644 --- a/src/main/java/org/onap/music/eelf/healthcheck/MusicHealthCheck.java +++ b/src/main/java/org/onap/music/eelf/healthcheck/MusicHealthCheck.java @@ -58,17 +58,20 @@ public class MusicHealthCheck { UUID randomUUID = UUID.randomUUID(); try { result = getAdminKeySpace(consistency, randomUUID); - } catch(Exception e) { + } catch( Exception e) { if(e.getMessage().toLowerCase().contains("unconfigured table healthcheck")) { logger.error("Error", e); logger.debug("Creating table...."); - boolean ksresult = createKeyspace(); - if(ksresult) - try { + try { + boolean ksresult = createKeyspace(); + if(ksresult) { result = getAdminKeySpace(consistency, randomUUID); - } catch (MusicServiceException e1) { - logger.error(EELFLoggerDelegate.errorLogger, e1, AppMessages.UNKNOWNERROR, ErrorSeverity.ERROR, ErrorTypes.UNKNOWN); } + } catch (MusicServiceException e1) { + logger.error(EELFLoggerDelegate.errorLogger, e1.getMessage(), AppMessages.UNKNOWNERROR, ErrorSeverity.ERROR, ErrorTypes.UNKNOWN); + } catch (MusicQueryException e1) { + logger.error(EELFLoggerDelegate.errorLogger, e1.getMessage(), AppMessages.UNKNOWNERROR, ErrorSeverity.ERROR, ErrorTypes.UNKNOWN,e1); + } } else { logger.error("Error", e); return "One or more nodes are down or not responding."; @@ -88,11 +91,12 @@ public class MusicHealthCheck { } } - private Boolean getAdminKeySpace(String consistency, UUID randomUUID) throws MusicServiceException { + private Boolean getAdminKeySpace(String consistency, UUID randomUUID) throws MusicServiceException,MusicQueryException { PreparedQueryObject pQuery = new PreparedQueryObject(); pQuery.appendQueryString("insert into admin.healthcheck (id) values (?)"); pQuery.addValue(randomUUID); - ResultType rs = MusicCore.nonKeyRelatedPut(pQuery, consistency); + ResultType rs = null; + rs = MusicCore.nonKeyRelatedPut(pQuery, consistency); logger.info(rs.toString()); return null != rs; @@ -109,15 +113,11 @@ public class MusicHealthCheck { - private boolean createKeyspace() { + private boolean createKeyspace() throws MusicServiceException,MusicQueryException { PreparedQueryObject pQuery = new PreparedQueryObject(); pQuery.appendQueryString("CREATE TABLE admin.healthcheck (id uuid PRIMARY KEY)"); ResultType rs = null ; - try { - rs = MusicCore.nonKeyRelatedPut(pQuery, ConsistencyLevel.ONE.toString()); - } catch (MusicServiceException e) { - logger.error(EELFLoggerDelegate.errorLogger, e, AppMessages.UNKNOWNERROR, ErrorSeverity.ERROR, ErrorTypes.UNKNOWN); - } + rs = MusicCore.nonKeyRelatedPut(pQuery, ConsistencyLevel.ONE.toString()); return rs != null && rs.getResult().toLowerCase().contains("success"); } diff --git a/src/main/java/org/onap/music/eelf/logging/EELFLoggerDelegate.java b/src/main/java/org/onap/music/eelf/logging/EELFLoggerDelegate.java index 64960b1e..a8012c82 100644 --- a/src/main/java/org/onap/music/eelf/logging/EELFLoggerDelegate.java +++ b/src/main/java/org/onap/music/eelf/logging/EELFLoggerDelegate.java @@ -44,6 +44,7 @@ public class EELFLoggerDelegate extends SLF4jWrapper implements EELFLogger { public static final EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger(); public static final EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger(); public static final EELFLogger debugLogger = EELFManager.getInstance().getDebugLogger(); + public static final EELFLogger securityLogger = EELFManager.getInstance().getSecurityLogger(); private String className; private static ConcurrentMap<String, EELFLoggerDelegate> classMap = new ConcurrentHashMap<>(); @@ -230,9 +231,7 @@ public class EELFLoggerDelegate extends SLF4jWrapper implements EELFLogger { * @param logger * @param msg * - * @deprecated use {@link #error(EELF, Exception)} instead */ - @Deprecated public void error(EELFLogger logger, String msg) { logger.error(className+ " - " + msg); } @@ -254,9 +253,7 @@ public class EELFLoggerDelegate extends SLF4jWrapper implements EELFLogger { * @param msg * @param arguments * - * @deprecated use {@link #error(EELF, Exception, Object...)} instead */ - @Deprecated public void error(EELFLogger logger, String msg, Object... arguments) { logger.error(msg, arguments); } @@ -289,9 +286,7 @@ public class EELFLoggerDelegate extends SLF4jWrapper implements EELFLogger { * @param logger * @param msg * @param severtiy - * @deprecated use {@link #error(EELF, Exception)} instead */ - @Deprecated public void error(EELFLogger logger, String msg, Object /* AlarmSeverityEnum */ severtiy) { logger.error(msg); } @@ -309,6 +304,8 @@ public class EELFLoggerDelegate extends SLF4jWrapper implements EELFLogger { debug(debugLogger, msg); info(auditLogger, msg); info(metricsLogger, msg); + info(securityLogger, msg); + } /** diff --git a/src/main/java/org/onap/music/eelf/logging/MusicContainerFilter.java b/src/main/java/org/onap/music/eelf/logging/MusicContainerFilter.java index 23f29595..bac02afa 100644 --- a/src/main/java/org/onap/music/eelf/logging/MusicContainerFilter.java +++ b/src/main/java/org/onap/music/eelf/logging/MusicContainerFilter.java @@ -39,32 +39,30 @@ import org.springframework.stereotype.Component; @Component public class MusicContainerFilter implements ContainerResponseFilter { - private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicContainerFilter.class); - - public MusicContainerFilter() { - - } - - @Override - public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) - throws IOException { - logger.info(EELFLoggerDelegate.applicationLogger, "In MusicContainerFilter response filter ::::::::::::::::::::::::"); - - if (null != EELFLoggerDelegate.mdcGet("transactionId")) { - EELFLoggerDelegate.mdcRemove("transactionId"); - } - - if (null != EELFLoggerDelegate.mdcGet("conversationId")) { - EELFLoggerDelegate.mdcRemove("conversationId"); - } - - if (null != EELFLoggerDelegate.mdcGet("clientId")) { - EELFLoggerDelegate.mdcRemove("clientId"); - } - - if (null != EELFLoggerDelegate.mdcGet("messageId")) { - EELFLoggerDelegate.mdcRemove("messageId"); - } - } - + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicContainerFilter.class); + + public MusicContainerFilter() { + + } + + @Override + public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) + throws IOException { + if (null != EELFLoggerDelegate.mdcGet("transactionId")) { + EELFLoggerDelegate.mdcRemove("transactionId"); + } + + if (null != EELFLoggerDelegate.mdcGet("conversationId")) { + EELFLoggerDelegate.mdcRemove("conversationId"); + } + + if (null != EELFLoggerDelegate.mdcGet("clientId")) { + EELFLoggerDelegate.mdcRemove("clientId"); + } + + if (null != EELFLoggerDelegate.mdcGet("messageId")) { + EELFLoggerDelegate.mdcRemove("messageId"); + } + } + } diff --git a/src/main/java/org/onap/music/eelf/logging/MusicLoggingServletFilter.java b/src/main/java/org/onap/music/eelf/logging/MusicLoggingServletFilter.java index cb688c54..7eca73e1 100644 --- a/src/main/java/org/onap/music/eelf/logging/MusicLoggingServletFilter.java +++ b/src/main/java/org/onap/music/eelf/logging/MusicLoggingServletFilter.java @@ -85,8 +85,8 @@ public class MusicLoggingServletFilter implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - logger.info(EELFLoggerDelegate.applicationLogger, - "In MusicLogginServletFilter doFilter start() ::::::::::::::::::::::: [\"+MusicUtil.getTransIdRequired()+\",\"+MusicUtil.getConversationIdRequired()+\",\"+MusicUtil.getClientIdRequired()+\",\"+MusicUtil.getMessageIdRequired()"); + logger.info(EELFLoggerDelegate.securityLogger, + "In MusicLogginServletFilter doFilter start() :: [\"+MusicUtil.getTransIdRequired()+\",\"+MusicUtil.getConversationIdRequired()+\",\"+MusicUtil.getClientIdRequired()+\",\"+MusicUtil.getMessageIdRequired()"); HttpServletRequest httpRequest = null; HttpServletResponse httpResponse = null; @@ -149,7 +149,7 @@ public class MusicLoggingServletFilter implements Filter { } - logger.info(EELFLoggerDelegate.applicationLogger, + logger.info(EELFLoggerDelegate.securityLogger, "In MusicLogginServletFilter doFilter. Header values validated sucessfully"); chain.doFilter(request, response); diff --git a/src/main/java/org/onap/music/main/MusicDigest.java b/src/main/java/org/onap/music/exceptions/MusicAuthenticationException.java index d05969e3..ab44fd6e 100644 --- a/src/main/java/org/onap/music/main/MusicDigest.java +++ b/src/main/java/org/onap/music/exceptions/MusicAuthenticationException.java @@ -2,7 +2,7 @@ * ============LICENSE_START========================================== * org.onap.music * =================================================================== - * Copyright (c) 2017 AT&T Intellectual Property + * Copyright (c) 2019 AT&T Intellectual Property * =================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,60 +20,56 @@ * ==================================================================== */ -package org.onap.music.main; +package org.onap.music.exceptions; /** - * + * @author inam * */ -public class MusicDigest { - private String evPutStatus; - private String vectorTs; +public class MusicAuthenticationException extends Exception { /** - * @param evPutStatus - * @param vectorTs + * */ - public MusicDigest(String evPutStatus, String vectorTs) { - this.evPutStatus = evPutStatus; - this.vectorTs = vectorTs; + public MusicAuthenticationException() { + } /** - * @return + * @param message */ - public String getEvPutStatus() { - return evPutStatus; + public MusicAuthenticationException(String message) { + super(message); + } /** - * @param evPutStatus + * @param cause */ - public void setEvPutStatus(String evPutStatus) { - this.evPutStatus = evPutStatus; + public MusicAuthenticationException(Throwable cause) { + super(cause); + } /** - * @return + * @param message + * @param cause */ - public String getVectorTs() { - return vectorTs; + public MusicAuthenticationException(String message, Throwable cause) { + super(message, cause); + } /** - * @param vectorTs + * @param message + * @param cause + * @param enableSuppression + * @param writableStackTrace */ - public void setVectorTs(String vectorTs) { - this.vectorTs = vectorTs; - } + public MusicAuthenticationException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - public String toString() { - return vectorTs + "|" + evPutStatus; } -} +} diff --git a/src/main/java/org/onap/music/lockingservice/cassandra/CassaLockStore.java b/src/main/java/org/onap/music/lockingservice/cassandra/CassaLockStore.java index 3c3f7160..06a087ab 100644 --- a/src/main/java/org/onap/music/lockingservice/cassandra/CassaLockStore.java +++ b/src/main/java/org/onap/music/lockingservice/cassandra/CassaLockStore.java @@ -274,7 +274,7 @@ public class CassaLockStore { String lockReference = "" + row.getLong("lockReference"); String createTime = row.getString("createTime"); String acquireTime = row.getString("acquireTime"); - LockType locktype = row.getBool("writeLock") ? LockType.WRITE : LockType.READ; + LockType locktype = row.isNull("writeLock") || row.getBool("writeLock") ? LockType.WRITE : LockType.READ; return new LockObject(true, lockReference, createTime, acquireTime, locktype); } @@ -283,29 +283,37 @@ public class CassaLockStore { throws MusicServiceException, MusicQueryException { logger.info(EELFLoggerDelegate.applicationLogger, "Getting lockholders in lock table for " + keyspace + "." + table + "." + key); + String origTable = table; table = table_prepend_name + table; String selectQuery = "select * from " + keyspace + "." + table + " where key=?;"; + List<String> lockHolders = new ArrayList<>(); PreparedQueryObject queryObject = new PreparedQueryObject(); queryObject.appendQueryString(selectQuery); queryObject.addValue(key); ResultSet rs = dsHandle.executeOneConsistencyGet(queryObject); - - List<String> lockHolders = new ArrayList<>(); boolean topOfQueue = true; + StringBuilder lock = new StringBuilder(). + append("$").append(keyspace).append(".").append(origTable). + append(".").append(key).append("$"); + StringBuilder lockReference = new StringBuilder(); for (Row row : rs) { - String lockReference = "" + row.getLong("lockReference"); - if (row.getBool("writeLock")) { + if ( row.isNull("lockReference") ) { + return lockHolders; + } + lockReference.append(lock).append(row.getLong("lockReference")); + if (row.isNull("writeLock") || row.getBool("writeLock")) { if (topOfQueue) { - lockHolders.add(lockReference); + lockHolders.add(lockReference.toString()); break; } else { break; } } // read lock - lockHolders.add(lockReference); + lockHolders.add(lockReference.toString()); topOfQueue = false; + lockReference.delete(0,lockReference.length()); } return lockHolders; } @@ -335,16 +343,16 @@ public class CassaLockStore { boolean topOfQueue = true; for (Row row : rs) { - String lockReference = "" + row.getLong("lockReference"); - if (row.getBool("writeLock")) { + String lockReference = "" + row.getLong("lockReference"); + if (row.isNull("writeLock") || row.getBool("writeLock")) { if (topOfQueue && lockRef.equals(lockReference)) { - return true; + return true; } else { - return false; + return false; } } if (lockRef.equals(lockReference)) { - return true; + return true; } topOfQueue = false; } @@ -384,7 +392,7 @@ public class CassaLockStore { String lockReference = "" + row.getLong("lockReference"); String createTime = row.getString("createTime"); String acquireTime = row.getString("acquireTime"); - LockType locktype = row.getBool("writeLock") ? LockType.WRITE : LockType.READ; + LockType locktype = row.isNull("writeLock") || row.getBool("writeLock") ? LockType.WRITE : LockType.READ; boolean isLockOwner = isLockOwner(keyspace, table, key, lockRef); return new LockObject(isLockOwner, lockReference, createTime, acquireTime, locktype); @@ -441,8 +449,9 @@ public class CassaLockStore { String updateQuery = "update " + keyspace + "." + table + " set acquireTime='" + System.currentTimeMillis() + "' where key='" + key + "' AND lockReference = " + lockReferenceL + " IF EXISTS;"; queryObject.appendQueryString(updateQuery); - dsHandle.executePut(queryObject, "eventual"); + //cannot use executePut because we need to ignore music timestamp adjustments for lock store + dsHandle.getSession().execute(updateQuery); } } diff --git a/src/main/java/org/onap/music/main/CipherUtil.java b/src/main/java/org/onap/music/main/CipherUtil.java new file mode 100644 index 00000000..0d5b7710 --- /dev/null +++ b/src/main/java/org/onap/music/main/CipherUtil.java @@ -0,0 +1,270 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * 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============================================= + * ==================================================================== + */ + +package org.onap.music.main; + +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.UnsupportedEncodingException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Scanner; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.lang3.ArrayUtils; +import org.onap.music.eelf.logging.EELFLoggerDelegate; + +public class CipherUtil { + + + /** + * Default key. + */ + private static String keyString = MusicUtil.getCipherEncKey(); + + private static final String ALGORITHM = "AES"; + private static final String ALGORYTHM_DETAILS = ALGORITHM + "/CBC/PKCS5PADDING"; + private static final int BLOCK_SIZE = 128; + @SuppressWarnings("unused") + private static SecretKeySpec secretKeySpec; + private static IvParameterSpec ivspec; + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(CipherUtil.class); + /** + * @deprecated Please use {@link #encryptPKC(String)} to encrypt the text. + * + * Encrypts the text using the specified secret key. + * + * @param plainText + * Text to encrypt + * @param secretKey + * Key to use for encryption + * @return encrypted version of plain text. + * @ + * if any encryption step fails + * + */ + @Deprecated + public static String encrypt(String plainText, String secretKey) { + String encryptedString = null; + try { + byte[] encryptText = plainText.getBytes("UTF-8"); + byte[] rawKey = Base64.decodeBase64(secretKey); + SecretKeySpec sKeySpec = new SecretKeySpec(rawKey, "AES"); + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.ENCRYPT_MODE, sKeySpec); + encryptedString = Base64.encodeBase64String(cipher.doFinal(encryptText)); + } catch (BadPaddingException | IllegalBlockSizeException | InvalidKeyException | NoSuchAlgorithmException + | NoSuchPaddingException | UnsupportedEncodingException ex) { + } + return encryptedString; + } + + /** + * @deprecated Please use {@link #encryptPKC(String)} to encrypt the text. + * Encrypts the text using the secret key in key.properties file. + * + * @param plainText + * Text to encrypt + * @return Encrypted Text + * @ + * if any decryption step fails + */ + @Deprecated + public static String encrypt(String plainText) { + return CipherUtil.encrypt(plainText, keyString); + } + + /** + * Encrypts the text using a secret key. + * + * @param plainText + * Text to encrypt + * @return Encrypted Text + * @ + * if any decryption step fails + */ + public static String encryptPKC(String plainText) { + return CipherUtil.encryptPKC(plainText, keyString); + } + + /** + * + * @deprecated Please use {@link #decryptPKC(String)} to Decryption the text. + * + * Decrypts the text using the specified secret key. + * + * @param encryptedText + * Text to decrypt + * @param secretKey + * Key to use for decryption + * @return plain text version of encrypted text + * @ + * if any decryption step fails + * + */ + @Deprecated + public static String decrypt(String encryptedText, String secretKey) { + String encryptedString = null; + try { + byte[] rawKey = Base64.decodeBase64(secretKey); + SecretKeySpec sKeySpec = new SecretKeySpec(rawKey, "AES"); + byte[] encryptText = Base64.decodeBase64(encryptedText.getBytes("UTF-8")); + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.DECRYPT_MODE, sKeySpec); + encryptedString = new String(cipher.doFinal(encryptText)); + } catch (BadPaddingException | IllegalBlockSizeException | InvalidKeyException | NoSuchAlgorithmException + | NoSuchPaddingException | UnsupportedEncodingException ex) { + } + return encryptedString; + } + + private static SecretKeySpec getSecretKeySpec() { + byte[] key = Base64.decodeBase64(keyString); + return new SecretKeySpec(key, ALGORITHM); + } + + private static SecretKeySpec getSecretKeySpec(String keyString) { + byte[] key = Base64.decodeBase64(keyString); + return new SecretKeySpec(key, ALGORITHM); + } + + /** + * Encrypt the text using the secret key in key.properties file + * + * @param value + * @return The encrypted string + * @throws BadPaddingException + * @ + * In case of issue with the encryption + */ + public static String encryptPKC(String value, String skey) { + Cipher cipher = null; + byte[] iv = null, finalByte = null; + + try { + cipher = Cipher.getInstance(ALGORYTHM_DETAILS, "SunJCE"); + + SecureRandom r = SecureRandom.getInstance("SHA1PRNG"); + iv = new byte[BLOCK_SIZE / 8]; + r.nextBytes(iv); + ivspec = new IvParameterSpec(iv); + cipher.init(Cipher.ENCRYPT_MODE, getSecretKeySpec(skey), ivspec); + finalByte = cipher.doFinal(value.getBytes()); + + } catch (Exception ex) { + + } + return Base64.encodeBase64String(ArrayUtils.addAll(iv, finalByte)); + } + + /** + * Decrypts the text using the secret key in key.properties file. + * + * @param message + * The encrypted string that must be decrypted using the ecomp + * Encryption Key + * @return The String decrypted + * @ + * if any decryption step fails + */ + public static String decryptPKC(String message, String skey) { + byte[] encryptedMessage = Base64.decodeBase64(message); + Cipher cipher; + byte[] decrypted = null; + try { + cipher = Cipher.getInstance(ALGORYTHM_DETAILS, "SunJCE"); + ivspec = new IvParameterSpec(ArrayUtils.subarray(encryptedMessage, 0, BLOCK_SIZE / 8)); + byte[] realData = ArrayUtils.subarray(encryptedMessage, BLOCK_SIZE / 8, encryptedMessage.length); + cipher.init(Cipher.DECRYPT_MODE, getSecretKeySpec(skey), ivspec); + decrypted = cipher.doFinal(realData); + + } catch (Exception ex) { + + + } + + return new String(decrypted); + } + + /** + * @deprecated Please use {@link #decryptPKC(String)} to Decrypt the text. + * + * Decrypts the text using the secret key in key.properties file. + * + * @param encryptedText + * Text to decrypt + * @return Decrypted text + * @ + * if any decryption step fails + */ + @Deprecated + public static String decrypt(String encryptedText) { + return CipherUtil.decrypt(encryptedText, keyString); + } + + /** + * + * Decrypts the text using the secret key in key.properties file. + * + * @param encryptedText + * Text to decrypt + * @return Decrypted text + * @ + * if any decryption step fails + */ + public static String decryptPKC(String encryptedText) { + return CipherUtil.decryptPKC(encryptedText, keyString); + } + + + public static void readAndSetKeyString() { + try { + Scanner in = new Scanner(new FileReader("/opt/app/music/etc/properties.txt")); + StringBuilder sb = new StringBuilder(); + while(in.hasNext()) { + sb.append(in.next()); + } + in.close(); + keyString = sb.toString(); + } catch (FileNotFoundException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + } + } + + /*public static void main(String[] args) { + + System.out.println("Encrypted password: "+encryptPKC("cassandra")); + + System.out.println("Decrypted password: "+decryptPKC("dDhqAp5/RwZbl9yRSZg15fN7Qul9eiE/JFkKemtTib0=")); + System.out.println("Decrypted password: "+decryptPKC("I/dOtD/YYzBStbtOYhKuUUyPHSW2G9ZzdSyB8bJp4vk=")); + System.out.println("Decrypted password: "+decryptPKC("g7zJqg74dLsH/fyL7I75b4eySy3pbMS2xVqkrB5lDl8=")); + }*/ + +} diff --git a/src/main/java/org/onap/music/main/MusicCore.java b/src/main/java/org/onap/music/main/MusicCore.java index 324f4681..da94e1a6 100644 --- a/src/main/java/org/onap/music/main/MusicCore.java +++ b/src/main/java/org/onap/music/main/MusicCore.java @@ -24,8 +24,18 @@ package org.onap.music.main; import java.util.List; import java.util.Map; + +import javax.ws.rs.core.MultivaluedMap; + import org.onap.music.datastore.Condition; import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.datastore.jsonobjects.JsonDelete; +import org.onap.music.datastore.jsonobjects.JsonIndex; +import org.onap.music.datastore.jsonobjects.JsonInsert; +import org.onap.music.datastore.jsonobjects.JsonKeySpace; +import org.onap.music.datastore.jsonobjects.JsonSelect; +import org.onap.music.datastore.jsonobjects.JsonTable; +import org.onap.music.datastore.jsonobjects.JsonUpdate; import org.onap.music.eelf.logging.EELFLoggerDelegate; import org.onap.music.exceptions.MusicLockingException; import org.onap.music.exceptions.MusicQueryException; @@ -34,17 +44,22 @@ import org.onap.music.lockingservice.cassandra.CassaLockStore; import org.onap.music.lockingservice.cassandra.LockType; import org.onap.music.lockingservice.cassandra.MusicLockState; import org.onap.music.service.MusicCoreService; -import org.onap.music.service.impl.MusicCassaCore; + import com.datastax.driver.core.ResultSet; public class MusicCore { private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicCore.class); - private static boolean unitTestRun = true; - private static MusicCoreService musicCore = MusicUtil.getMusicCoreService(); - public static CassaLockStore mLockHandle; + private static CassaLockStore mLockHandle; + + public static CassaLockStore getmLockHandle() { + return mLockHandle; + } + public static void setmLockHandle(CassaLockStore mLockHandleIn) { + mLockHandle = mLockHandleIn; + } /** * Acquire lock @@ -122,7 +137,7 @@ public class MusicCore { } public static ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) - throws MusicServiceException { + throws MusicServiceException,MusicQueryException { return musicCore.nonKeyRelatedPut(queryObject, consistency); } @@ -177,5 +192,59 @@ public class MusicCore { public static MusicLockState releaseLock(String lockId, boolean voluntaryRelease) throws MusicLockingException { return musicCore.releaseLock(lockId, voluntaryRelease); } + + //Added changes for orm implementation. + + public static ResultType createKeyspace(JsonKeySpace jsonKeySpaceObject, String consistencyInfo) + throws MusicServiceException, MusicQueryException { + return musicCore.createKeyspace(jsonKeySpaceObject,consistencyInfo); + } + + public static ResultType dropKeyspace(JsonKeySpace josnKeyspaceObject, String consistencyInfo) + throws MusicServiceException,MusicQueryException { + return musicCore.dropKeyspace(josnKeyspaceObject, consistencyInfo); + } + + public static ResultType createTable(JsonTable jsonTableObject,String consistencyInfo) + throws MusicServiceException,MusicQueryException { + return musicCore.createTable(jsonTableObject, consistencyInfo); + } + + public static ResultType dropTable(JsonTable jsonTableObject, String consistencyInfo) + throws MusicServiceException, MusicQueryException { + return musicCore.dropTable(jsonTableObject, consistencyInfo); + } + + public static ResultType createIndex(JsonIndex jsonIndexObject, String consistencyInfo) + throws MusicServiceException,MusicQueryException { + return musicCore.createIndex(jsonIndexObject, consistencyInfo); + } + + public static ResultSet select(JsonSelect jsonSelect, MultivaluedMap<String, String> rowParams) + throws MusicServiceException, MusicQueryException{ + return musicCore.select(jsonSelect, rowParams); + } + + public static ResultSet selectCritical(JsonInsert jsonInsertObj, MultivaluedMap<String, String> rowParams) + throws MusicLockingException, MusicQueryException, MusicServiceException{ + return musicCore.selectCritical(jsonInsertObj, rowParams); + } + + + public static ReturnType insertIntoTable(JsonInsert jsonInsert) throws MusicLockingException, MusicQueryException, MusicServiceException{ + return musicCore.insertIntoTable(jsonInsert); + } + + public static ReturnType updateTable(JsonUpdate jsonUpdateObj,MultivaluedMap<String, String> rowParams) + throws MusicLockingException, MusicQueryException, MusicServiceException{ + return musicCore.updateTable(jsonUpdateObj, rowParams); + } + + public static ReturnType deleteFromTable(JsonDelete jsonDeleteObj,MultivaluedMap<String, String> rowParams) + throws MusicLockingException, MusicQueryException, MusicServiceException{ + return musicCore.deleteFromTable(jsonDeleteObj,rowParams); + } + + } diff --git a/src/main/java/org/onap/music/main/MusicUtil.java b/src/main/java/org/onap/music/main/MusicUtil.java index 9ffa2503..21e5c255 100755 --- a/src/main/java/org/onap/music/main/MusicUtil.java +++ b/src/main/java/org/onap/music/main/MusicUtil.java @@ -31,20 +31,13 @@ import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.Row; import java.io.File; import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; import java.math.BigInteger; import java.nio.ByteBuffer; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.Scanner; -import java.util.StringTokenizer; import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.ResponseBuilder; @@ -61,7 +54,6 @@ import org.onap.music.service.impl.MusicCassaCore; import com.datastax.driver.core.ConsistencyLevel; import com.datastax.driver.core.DataType; -import com.sun.jersey.core.util.Base64; /** * @author nelson24 @@ -103,30 +95,27 @@ public class MusicUtil { private static final String PROPERTIES_FILE = "/opt/app/music/etc/music.properties"; public static final String DEFAULTKEYSPACENAME = "TBD"; - private static String myCassaHost = LOCALHOST; - private static String defaultMusicIp = LOCALHOST; - private static int cassandraPort = 9042; - private static int notifytimeout = 30000; - private static int notifyinterval = 5000; private static long defaultLockLeasePeriod = 6000; + // Amount of times to retry to delete a lock in atomic. private static int retryCount = 3; - private static int cacheObjectMaxLife = -1; private static String lockUsing = MusicUtil.CASSANDRA; + // Cadi OnOff private static boolean isCadi = false; + // Keyspace Creation on/off private static boolean isKeyspaceActive = false; private static boolean debug = true; private static String version = "0.0.0"; private static String build = ""; private static String musicPropertiesFilePath = PROPERTIES_FILE; - private static final String[] propKeys = new String[] { "cassandra.host", "music.ip", "debug", - "version", "music.rest.ip", "music.properties", "lock.lease.period", "id", "all.ids", - "public.ip","all.pubic.ips", "cassandra.user", "cassandra.password", "aaf.endpoint.url", - "admin.username","admin.password","aaf.admin.url","music.namespace","admin.aaf.role", - "cassandra.port","lock.using","retry.count","transId.header.required", - "conversation.header.required","clientId.header.required","messageId.header.required", - "transId.header.prefix","conversation.header.prefix","clientId.header.prefix", - "messageId.header.prefix"}; + // private static final String[] propKeys = new String[] { MusicUtil.class.getDeclaredMethod(arg0, )"build","cassandra.host", "debug", + // "version", "music.properties", "lock.lease.period", "cassandra.user", + // "cassandra.password", "aaf.endpoint.url","admin.username","admin.password", + // "music.namespace","admin.aaf.role","cassandra.port","lock.using","retry.count", + // "transId.header.required","conversation.header.required","clientId.header.required", + // "messageId.header.required","transId.header.prefix","conversation.header.prefix", + // "clientId.header.prefix","messageId.header.prefix"}; + // Consistency Constants and variables. private static final String[] cosistencyLevel = new String[] { "ALL","EACH_QUORUM","QUORUM","LOCAL_QUORUM","ONE","TWO", "THREE","LOCAL_ONE","ANY","SERIAL","LOCAL_SERIAL"}; @@ -143,87 +132,42 @@ public class MusicUtil { consistencyName.put("LOCAL_ONE",ConsistencyLevel.LOCAL_ONE); consistencyName.put("LOCAL_SERIAL",ConsistencyLevel.LOCAL_SERIAL); } + + // Cassandra Values private static String cassName = "cassandra"; private static String cassPwd; - private static String aafEndpointUrl = null; - private static String adminId = "username"; - private static String adminPass= "password"; - private static String aafAdminUrl= null; - private static String musicNamespace= "org.onap.music.api"; - private static String adminAafRole= "org.onap.music.api.admin_api"; + private static String myCassaHost = LOCALHOST; + private static int cassandraPort = 9042; + + // AAF + private static String musicAafNs = "org.onap.music.cadi"; + // Locking public static final long MusicEternityEpochMillis = 1533081600000L; // Wednesday, August 1, 2018 12:00:00 AM public static final long MaxLockReferenceTimePart = 1000000000000L; // millis after eternity (eq sometime in 2050) public static final long MaxCriticalSectionDurationMillis = 1L * 24 * 60 * 60 * 1000; // 1 day - private static String transIdPrefix= "false"; - private static String conversationIdPrefix= "false"; - private static String clientIdPrefix= "false"; - private static String messageIdPrefix= "false"; - private static String transIdRequired= "false"; - private static String conversationIdRequired= "false"; - private static String clientIdRequired= "false"; - private static String messageIdRequired= "false"; + // Response/Request tracking headers + private static String transIdPrefix = "false"; + private static String conversationIdPrefix = "false"; + private static String clientIdPrefix = "false"; + private static String messageIdPrefix = "false"; + private static Boolean transIdRequired = false; + private static Boolean conversationIdRequired = false; + private static Boolean clientIdRequired = false; + private static Boolean messageIdRequired = false; + private static String cipherEncKey = ""; + public static String getLockUsing() { return lockUsing; } - public static void setLockUsing(String lockUsing) { MusicUtil.lockUsing = lockUsing; } - - public static String getAafAdminUrl() { - return aafAdminUrl; - } - - - public static void setAafAdminUrl(String aafAdminUrl) { - MusicUtil.aafAdminUrl = aafAdminUrl; - } - - - public static String getMusicNamespace() { - return musicNamespace; - } - - - public static void setMusicNamespace(String musicNamespace) { - MusicUtil.musicNamespace = musicNamespace; - } - - - public static String getAdminAafRole() { - return adminAafRole; - } - - - public static void setAdminAafRole(String adminAafRole) { - MusicUtil.adminAafRole = adminAafRole; - } - - - - public static String getAdminId() { - return adminId; - } - - public static void setAdminId(String adminId) { - MusicUtil.adminId = adminId; - } - - - public static String getAdminPass() { - return adminPass; - } - - public static void setAdminPass(String adminPass) { - MusicUtil.adminPass = adminPass; - } - - private MusicUtil() { + public MusicUtil() { throw new IllegalStateException("Utility Class"); } /** @@ -256,30 +200,14 @@ public class MusicUtil { } /** - * @return the aafEndpointUrl - */ - public static String getAafEndpointUrl() { - return aafEndpointUrl; - } - - /** - * - * @param aafEndpointUrl - */ - public static void setAafEndpointUrl(String aafEndpointUrl) { - MusicUtil.aafEndpointUrl = aafEndpointUrl; - } - - - /** * Returns An array of property names that should be in the Properties * files. * - * @return - */ - public static String[] getPropkeys() { - return propKeys.clone(); - } +// * @return +// */ +// public static String[] getPropkeys() { +// return propKeys.clone(); +// } /** * Get MusicPropertiesFilePath - Default = /opt/music/music.properties @@ -390,24 +318,6 @@ public class MusicUtil { public static void setMyCassaHost(String myCassaHost) { MusicUtil.myCassaHost = myCassaHost; } - - /** - * Get DefaultMusicIp - Default = localhost property file value - music.ip - * - * @return - */ - public static String getDefaultMusicIp() { - return defaultMusicIp; - } - - /** - * Set DefaultMusicIp - * - * @param defaultMusicIp . - */ - public static void setDefaultMusicIp(String defaultMusicIp) { - MusicUtil.defaultMusicIp = defaultMusicIp; - } /** * Gey default retry count @@ -443,9 +353,11 @@ public class MusicUtil { } /** - * . + * This method depricated as its not used or needed. + * * @return String */ + @Deprecated public static String getTestType() { String testType = ""; try { @@ -462,7 +374,9 @@ public class MusicUtil { } /** - * + * Method to do a Thread Sleep. + * Used for adding a delay. + * * @param time */ public static void sleep(long time) { @@ -638,7 +552,7 @@ public class MusicUtil { response.header(XPATCHVERSION,verArray[2]); } response.header(XLATESTVERSION,version); - logger.info(EELFLoggerDelegate.applicationLogger,"Version In:" + versionIn); + logger.info(EELFLoggerDelegate.auditLogger,"Version In:" + versionIn); return response; } @@ -655,29 +569,6 @@ public class MusicUtil { return consistencyName.get(consistency.toUpperCase()); } - public static void setNotifyInterval(int notifyinterval) { - MusicUtil.notifyinterval = notifyinterval; - } - public static void setNotifyTimeOut(int notifytimeout) { - MusicUtil.notifytimeout = notifytimeout; - } - - public static int getNotifyInterval() { - return MusicUtil.notifyinterval; - } - - public static int getNotifyTimeout() { - return MusicUtil.notifytimeout; - } - - public static int getCacheObjectMaxLife() { - return MusicUtil.cacheObjectMaxLife; - } - - public static void setCacheObjectMaxLife(int cacheObjectMaxLife) { - MusicUtil.cacheObjectMaxLife = cacheObjectMaxLife; - } - /** * Given the time of write for an update in a critical section, this method provides a transformed timestamp * that ensures that a previous lock holder who is still alive can never corrupt a later critical section. @@ -839,67 +730,89 @@ public class MusicUtil { } /** - * @return the transIdRequired - */ - public static String getTransIdRequired() { - return transIdRequired; - } - - - /** - * @param transIdRequired the transIdRequired to set - */ - public static void setTransIdRequired(String transIdRequired) { - MusicUtil.transIdRequired = transIdRequired; - } - - - /** - * @return the conversationIdRequired - */ - public static String getConversationIdRequired() { - return conversationIdRequired; - } - - - /** - * @param conversationIdRequired the conversationIdRequired to set - */ - public static void setConversationIdRequired(String conversationIdRequired) { - MusicUtil.conversationIdRequired = conversationIdRequired; - } - - - /** - * @return the clientIdRequired - */ - public static String getClientIdRequired() { - return clientIdRequired; - } - - - /** - * @param clientIdRequired the clientIdRequired to set - */ - public static void setClientIdRequired(String clientIdRequired) { - MusicUtil.clientIdRequired = clientIdRequired; - } - - - /** - * @return the messageIdRequired - */ - public static String getMessageIdRequired() { - return messageIdRequired; - } - - - /** - * @param messageIdRequired the messageIdRequired to set - */ - public static void setMessageIdRequired(String messageIdRequired) { - MusicUtil.messageIdRequired = messageIdRequired; - } + * @return the transIdRequired + */ + public static Boolean getTransIdRequired() { + return transIdRequired; + } + + + /** + * @param transIdRequired the transIdRequired to set + */ + public static void setTransIdRequired(Boolean transIdRequired) { + MusicUtil.transIdRequired = transIdRequired; + } + + + /** + * @return the conversationIdRequired + */ + public static Boolean getConversationIdRequired() { + return conversationIdRequired; + } + + + /** + * @param conversationIdRequired the conversationIdRequired to set + */ + public static void setConversationIdRequired(Boolean conversationIdRequired) { + MusicUtil.conversationIdRequired = conversationIdRequired; + } + + + /** + * @return the clientIdRequired + */ + public static Boolean getClientIdRequired() { + return clientIdRequired; + } + + + /** + * @param clientIdRequired the clientIdRequired to set + */ + public static void setClientIdRequired(Boolean clientIdRequired) { + MusicUtil.clientIdRequired = clientIdRequired; + } + + + /** + * @return the messageIdRequired + */ + public static Boolean getMessageIdRequired() { + return messageIdRequired; + } + + /** + * @param messageIdRequired the messageIdRequired to set + */ + public static void setMessageIdRequired(Boolean messageIdRequired) { + MusicUtil.messageIdRequired = messageIdRequired; + } + + + public static String getCipherEncKey() { + return MusicUtil.cipherEncKey; + } + + + public static void setCipherEncKey(String cipherEncKey) { + MusicUtil.cipherEncKey = cipherEncKey; + if ( null == cipherEncKey || cipherEncKey.equals("") || + cipherEncKey.equals("nothing to see here")) { + logger.error(EELFLoggerDelegate.errorLogger, "Missing Cipher Encryption Key."); + } + } + + public static String getMusicAafNs() { + return MusicUtil.musicAafNs; + } + + + public static void setMusicAafNs(String musicAafNs) { + MusicUtil.musicAafNs = musicAafNs; + } diff --git a/src/main/java/org/onap/music/main/PropertiesLoader.java b/src/main/java/org/onap/music/main/PropertiesLoader.java index c20ce5c5..f99650ae 100644 --- a/src/main/java/org/onap/music/main/PropertiesLoader.java +++ b/src/main/java/org/onap/music/main/PropertiesLoader.java @@ -22,9 +22,6 @@ package org.onap.music.main; -import java.util.ArrayList; -import java.util.Arrays; - import org.onap.music.eelf.logging.EELFLoggerDelegate; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Value; @@ -33,7 +30,7 @@ import org.springframework.context.annotation.PropertySource; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.stereotype.Component; -@PropertySource(value = {"file:/opt/app/music/etc/music.properties", "classpath:/project.properties"}) +@PropertySource(value = {"file:/opt/app/music/etc/music.properties", "classpath:/project.properties","file:/opt/app/music/etc/key.properties"}) @Component public class PropertiesLoader implements InitializingBean { @@ -64,33 +61,9 @@ public class PropertiesLoader implements InitializingBean { @Value("${cassandra.password}") public String cassandraPassword; - @Value("${aaf.endpoint.url}") - public String aafEndpointUrl; - - @Value("${admin.username}") - public String adminUsername; - - @Value("${admin.password}") - public String adminPassword; - @Value("${cassandra.port}") public String cassandraPort; - @Value("${aaf.admin.url}") - public String aafAdminUrl; - - @Value("${music.namespace}") - public String musicNamespace; - - @Value("${admin.aaf.role}") - public String adminAafRole; - - @Value("${notify.interval}") - public String notifyInterval; - - @Value("${notify.timeout}") - public String notifyTimeout; - @Value("${cadi}") public String isCadi; @@ -113,16 +86,22 @@ public class PropertiesLoader implements InitializingBean { private String messageIdPrefix; @Value("${transId.header.required}") - private String transIdRequired; + private Boolean transIdRequired; @Value("${conversation.header.required}") - private String conversationIdRequired; + private Boolean conversationIdRequired; @Value("${clientId.header.required}") - private String clientIdRequired; + private Boolean clientIdRequired; @Value("${messageId.header.required}") - private String messageIdRequired; + private Boolean messageIdRequired; + + @Value("${music.aaf.ns}") + private String musicAafNs; + + @Value("${cipher.enc.key}") + private String cipherEncKey; private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(PropertiesLoader.class); @@ -139,20 +118,11 @@ public class PropertiesLoader implements InitializingBean { * . */ public void loadProperties() { - if (aafAdminUrl != null && !aafAdminUrl.equals("${aaf.admin.url}")) { - MusicUtil.setAafAdminUrl(aafAdminUrl); + if(cipherEncKey != null) { + MusicUtil.setCipherEncKey(cipherEncKey); } - if (aafEndpointUrl != null && !aafEndpointUrl.equals("${aaf.endpoint.url}")) { - MusicUtil.setAafEndpointUrl(aafEndpointUrl); - } - if (adminAafRole != null && !adminAafRole.equals("${admin.aaf.role}")) { - MusicUtil.setAdminAafRole(adminAafRole); - } - if (adminPassword != null && !adminPassword.equals("${admin.password}")) { - MusicUtil.setAdminPass(adminPassword); - } - if (adminUsername != null && !adminUsername.equals("${admin.username}")) { - MusicUtil.setAdminId(adminUsername); + if (musicAafNs != null) { + MusicUtil.setMusicAafNs(musicAafNs); } if (cassandraPort != null && !cassandraPort.equals("${cassandra.port}")) { MusicUtil.setCassandraPort(Integer.parseInt(cassandraPort)); @@ -169,24 +139,12 @@ public class PropertiesLoader implements InitializingBean { if (lockLeasePeriod != null && !lockLeasePeriod.equals("${lock.lease.period}")) { MusicUtil.setDefaultLockLeasePeriod(Long.parseLong(lockLeasePeriod)); } - if (musicIp != null && !musicIp.equals("${music.ip}")) { - MusicUtil.setDefaultMusicIp(musicIp); - } - if (musicNamespace != null && !musicNamespace.equals("${music.namespace}")) { - MusicUtil.setMusicNamespace(musicNamespace); - } if (musicProperties != null && !musicProperties.equals("${music.properties}")) { MusicUtil.setMusicPropertiesFilePath(musicProperties); } if (cassandraHost != null && !cassandraHost.equals("${cassandra.host}")) { MusicUtil.setMyCassaHost(cassandraHost); } - if (notifyInterval != null && !notifyInterval.equals("${notify.interval}")) { - MusicUtil.setNotifyInterval(Integer.parseInt(notifyInterval)); - } - if (notifyTimeout != null && !notifyTimeout.equals("${notify.timeout}")) { - MusicUtil.setNotifyTimeOut(Integer.parseInt(notifyTimeout)); - } if (version != null && !version.equals("${version}")) { MusicUtil.setVersion(version); } @@ -202,8 +160,6 @@ public class PropertiesLoader implements InitializingBean { if (isKeyspaceActive != null && !isKeyspaceActive.equals("${keyspace.active}")) { MusicUtil.setKeyspaceActive(Boolean.parseBoolean(isKeyspaceActive)); } - - if(transIdPrefix!=null) { MusicUtil.setTransIdPrefix(transIdPrefix); } @@ -236,6 +192,8 @@ public class PropertiesLoader implements InitializingBean { MusicUtil.setMessageIdRequired(messageIdRequired); } } + + @Override diff --git a/src/main/java/org/onap/music/response/jsonobjects/JsonResponse.java b/src/main/java/org/onap/music/response/jsonobjects/JsonResponse.java index 2c419e18..f0793dc2 100644 --- a/src/main/java/org/onap/music/response/jsonobjects/JsonResponse.java +++ b/src/main/java/org/onap/music/response/jsonobjects/JsonResponse.java @@ -56,9 +56,19 @@ public class JsonResponse { private LockStatus lockStatus; private List<String> lockHolders; private String lockLease; + private boolean isLockHolders=false; - /** + public boolean isLockHolders() { + return isLockHolders; + } + + public JsonResponse setisLockHolders(boolean isLockHolders) { + this.isLockHolders = isLockHolders; + return this; + } + + /** * Create a JSONLock Response * Use setters to provide more information as in * JsonLockResponse(ResultType.SUCCESS).setMessage("We did it").setLock(mylockname) @@ -282,7 +292,7 @@ public class JsonResponse { lockMap.put("lock-status", lockStatus); } if (lockHolders != null && !lockHolders.isEmpty()) { - if (lockHolders.size()==1) { + if (lockHolders.size()==1 && !isLockHolders) { //for backwards compatability lockMap.put("lock-holder", lockHolders.get(0)); } else { diff --git a/src/main/java/org/onap/music/rest/RestMusicDataAPI.java b/src/main/java/org/onap/music/rest/RestMusicDataAPI.java index 219e713c..756856d0 100755 --- a/src/main/java/org/onap/music/rest/RestMusicDataAPI.java +++ b/src/main/java/org/onap/music/rest/RestMusicDataAPI.java @@ -6,6 +6,8 @@ * =================================================================== * Modifications Copyright (c) 2019 Samsung * =================================================================== + * Modifications Copyright (C) 2019 IBM + * =================================================================== * 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 @@ -24,7 +26,6 @@ package org.onap.music.rest; -import java.nio.ByteBuffer; import java.util.List; import java.util.Map; import java.util.UUID; @@ -46,23 +47,23 @@ import javax.ws.rs.core.Response.ResponseBuilder; import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.UriInfo; -import org.apache.commons.lang3.StringUtils; +import org.onap.music.datastore.MusicDataStoreHandle; import org.onap.music.datastore.PreparedQueryObject; import org.onap.music.datastore.jsonobjects.JsonDelete; +import org.onap.music.datastore.jsonobjects.JsonIndex; import org.onap.music.datastore.jsonobjects.JsonInsert; import org.onap.music.datastore.jsonobjects.JsonKeySpace; +import org.onap.music.datastore.jsonobjects.JsonSelect; import org.onap.music.datastore.jsonobjects.JsonTable; import org.onap.music.datastore.jsonobjects.JsonUpdate; import org.onap.music.eelf.logging.EELFLoggerDelegate; -import org.onap.music.exceptions.MusicLockingException; -import org.onap.music.exceptions.MusicQueryException; import org.onap.music.eelf.logging.format.AppMessages; import org.onap.music.eelf.logging.format.ErrorSeverity; import org.onap.music.eelf.logging.format.ErrorTypes; +import org.onap.music.exceptions.MusicLockingException; +import org.onap.music.exceptions.MusicQueryException; import org.onap.music.exceptions.MusicServiceException; import org.onap.music.main.MusicCore; -import org.onap.music.datastore.Condition; -import org.onap.music.datastore.MusicDataStoreHandle; import org.onap.music.main.MusicUtil; import org.onap.music.main.ResultType; import org.onap.music.main.ReturnType; @@ -75,8 +76,10 @@ import com.datastax.driver.core.TableMetadata; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; -import io.swagger.annotations.ApiResponses; import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import io.swagger.annotations.Example; +import io.swagger.annotations.ExampleProperty; /* Version 2 Class */ //@Path("/v{version: [0-9]+}/keyspaces") @@ -111,6 +114,8 @@ public class RestMusicDataAPI { private static final String XPATCHVERSION = "X-patchVersion"; private static final String NS = "ns"; private static final String VERSION = "v2"; + private static final String PARAMETER_ERROR = "Missing Row Identifier. Please provide the parameter of key=value for the row being selected."; + private class RowIdentifier { public String primarKeyValue; @@ -138,9 +143,22 @@ public class RestMusicDataAPI { */ @POST @Path("/{name}") - @ApiOperation(value = "Create Keyspace", response = String.class,hidden = true) + @ApiOperation(value = "Create Keyspace", response = String.class, + notes = "This API will not work if MUSIC properties has keyspace.active=false ") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"message\" : \"Keysapce <keyspace> Created\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"<errorMessage>\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response createKeySpace( @ApiParam(value = "Major Version",required = true) @PathParam("version") String version, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @@ -161,46 +179,19 @@ public class RestMusicDataAPI { response.status(Status.BAD_REQUEST); return response.entity(new JsonResponse(ResultType.FAILURE).setError(ResultType.BODYMISSING.getResult()).toMap()).build(); } - - String consistency = MusicUtil.EVENTUAL;// for now this needs only eventual consistency - - PreparedQueryObject queryObject = new PreparedQueryObject(); - if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && kspObject.getConsistencyInfo().get("consistency") != null) { - if(MusicUtil.isValidConsistency(kspObject.getConsistencyInfo().get("consistency"))) - queryObject.setConsistency(kspObject.getConsistencyInfo().get("consistency")); - else - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build(); - } - long start = System.currentTimeMillis(); - Map<String, Object> replicationInfo = kspObject.getReplicationInfo(); - String repString = null; - try { - repString = "{" + MusicUtil.jsonMaptoSqlString(replicationInfo, ",") + "}"; - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGDATA ,ErrorSeverity - .CRITICAL, ErrorTypes.DATAERROR, e); - - } - queryObject.appendQueryString( - "CREATE KEYSPACE " + keyspaceName + " WITH replication = " + repString); - if (kspObject.getDurabilityOfWrites() != null) { - queryObject.appendQueryString( - " AND durable_writes = " + kspObject.getDurabilityOfWrites()); - } - - queryObject.appendQueryString(";"); - long end = System.currentTimeMillis(); - logger.info(EELFLoggerDelegate.applicationLogger, - "Time taken for setting up query in create keyspace:" + (end - start)); - ResultType result = ResultType.FAILURE; try { - result = MusicCore.nonKeyRelatedPut(queryObject, consistency); + kspObject.setKeyspaceName(keyspaceName); + result = MusicCore.createKeyspace(kspObject, MusicUtil.EVENTUAL); logger.info(EELFLoggerDelegate.applicationLogger, "result = " + result); + } catch ( MusicQueryException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.QUERYERROR + ,ErrorSeverity.WARN, ErrorTypes.QUERYERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); } catch ( MusicServiceException ex) { logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity .WARN, ErrorTypes.MUSICSERVICEERROR, ex); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("err:" + ex.getMessage()).toMap()).build(); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); } return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Created").toMap()).build(); @@ -225,8 +216,21 @@ public class RestMusicDataAPI { */ @DELETE @Path("/{name}") - @ApiOperation(value = "Delete Keyspace", response = String.class,hidden=true) + @ApiOperation(value = "Delete Keyspace", response = String.class, + notes = "This API will not work if MUSIC properties has keyspace.active=false ") @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"message\" : \"Keysapce <keyspace> Deleted\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"<errorMessage>\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response dropKeySpace( @ApiParam(value = "Major Version",required = true) @PathParam("version") String version, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @@ -241,11 +245,22 @@ public class RestMusicDataAPI { logger.info(EELFLoggerDelegate.applicationLogger,"In Drop Keyspace " + keyspaceName); if (MusicUtil.isKeyspaceActive()) { String consistency = MusicUtil.EVENTUAL;// for now this needs only - PreparedQueryObject queryObject = new PreparedQueryObject(); - queryObject.appendQueryString("DROP KEYSPACE " + keyspaceName + ";"); - ResultType result = MusicCore.nonKeyRelatedPut(queryObject, consistency); - if ( result.equals(ResultType.FAILURE) ) { - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Error Deleteing Keyspace " + keyspaceName).toMap()).build(); + String droperror = "Error Deleteing Keyspace " + keyspaceName; + JsonKeySpace kspObject = new JsonKeySpace(); + kspObject.setKeyspaceName(keyspaceName); + try{ + ResultType result = MusicCore.dropKeyspace(kspObject, consistency); + if ( result.equals(ResultType.FAILURE) ) { + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError(droperror).toMap()).build(); + } + } catch ( MusicQueryException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.QUERYERROR + ,ErrorSeverity.WARN, ErrorTypes.QUERYERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(droperror + " " + ex.getMessage()).toMap()).build(); + } catch ( MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR + ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR, ex); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(droperror + " " + ex.getMessage()).toMap()).build(); } return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Deleted").toMap()).build(); } else { @@ -271,18 +286,27 @@ public class RestMusicDataAPI { */ @POST @Path("/{keyspace: .*}/tables/{tablename: .*}") - @ApiOperation(value = "Create Table", response = String.class) + @ApiOperation(value = "Create Table", response = String.class, + notes = "Create a table with the required json in the body.") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @ApiResponses(value={ - @ApiResponse(code= 400, message = "Will return JSON response with message"), - @ApiResponse(code= 401, message = "Unautorized User") - }) + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"message\" : \"Tablename <tablename> Created under keyspace <keyspace>\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"<errorMessage>\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response createTable( @ApiParam(value = "Major Version",required = true) @PathParam("version") String version, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "AID", required = false,hidden = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam(NS) String ns, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, JsonTable tableObj, @@ -303,180 +327,15 @@ public class RestMusicDataAPI { EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) "); String consistency = MusicUtil.EVENTUAL; // for now this needs only eventual consistency - String primaryKey = null; - String partitionKey = tableObj.getPartitionKey(); - String clusterKey = tableObj.getClusteringKey(); - String filteringKey = tableObj.getFilteringKey(); - if(filteringKey != null) { - clusterKey = clusterKey + "," + filteringKey; - } - primaryKey = tableObj.getPrimaryKey(); // get primaryKey if available - - PreparedQueryObject queryObject = new PreparedQueryObject(); - // first read the information about the table fields - Map<String, String> fields = tableObj.getFields(); - if (fields == null) { - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) - .setError("Create Table Error: No fields in request").toMap()).build(); - } - - StringBuilder fieldsString = new StringBuilder("(vector_ts text,"); - int counter = 0; - for (Map.Entry<String, String> entry : fields.entrySet()) { - if (entry.getKey().equals("PRIMARY KEY")) { - primaryKey = entry.getValue(); // replaces primaryKey - primaryKey = primaryKey.trim(); - } else { - if (counter == 0 ) fieldsString.append("" + entry.getKey() + " " + entry.getValue() + ""); - else fieldsString.append("," + entry.getKey() + " " + entry.getValue() + ""); - } - - if (counter != (fields.size() - 1) ) { - counter = counter + 1; - } else { - - if((primaryKey != null) && (partitionKey == null)) { - primaryKey = primaryKey.trim(); - int count1 = StringUtils.countMatches(primaryKey, ')'); - int count2 = StringUtils.countMatches(primaryKey, '('); - if (count1 != count2) { - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) - .setError("Create Table Error: primary key '(' and ')' do not match, primary key=" + primaryKey) - .toMap()).build(); - } - - if ( primaryKey.indexOf('(') == -1 || ( count2 == 1 && (primaryKey.lastIndexOf(')') +1) == primaryKey.length() ) ) { - if (primaryKey.contains(",") ) { - partitionKey= primaryKey.substring(0,primaryKey.indexOf(',')); - partitionKey=partitionKey.replaceAll("[\\(]+",""); - clusterKey=primaryKey.substring(primaryKey.indexOf(',')+1); // make sure index - clusterKey=clusterKey.replaceAll("[)]+", ""); - } else { - partitionKey=primaryKey; - partitionKey=partitionKey.replaceAll("[\\)]+",""); - partitionKey=partitionKey.replaceAll("[\\(]+",""); - clusterKey=""; - } - } else { // not null and has ) before the last char - partitionKey= primaryKey.substring(0,primaryKey.indexOf(')')); - partitionKey=partitionKey.replaceAll("[\\(]+",""); - partitionKey = partitionKey.trim(); - clusterKey= primaryKey.substring(primaryKey.indexOf(')')); - clusterKey=clusterKey.replaceAll("[\\(]+",""); - clusterKey=clusterKey.replaceAll("[\\)]+",""); - clusterKey = clusterKey.trim(); - if (clusterKey.indexOf(',') == 0) { - clusterKey=clusterKey.substring(1); - } - clusterKey = clusterKey.trim(); - if (clusterKey.equals(",") ) clusterKey=""; // print error if needed ( ... ),) - } - - if (!(partitionKey.isEmpty() || clusterKey.isEmpty()) - && (partitionKey.equalsIgnoreCase(clusterKey) || - clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) { - logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey + " and primary key=" + primaryKey ); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError( - "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ") of" - + " primary key=" + primaryKey) - .toMap()).build(); - - } - - if (partitionKey.isEmpty() ) primaryKey=""; - else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")"; - else primaryKey=" (" + partitionKey + ")," + clusterKey; - - - if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )"); - - } else { // end of length > 0 - - if (!(partitionKey.isEmpty() || clusterKey.isEmpty()) - && (partitionKey.equalsIgnoreCase(clusterKey) || - clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) { - logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError( - "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ")") - .toMap()).build(); - } - - if (partitionKey.isEmpty() ) primaryKey=""; - else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")"; - else primaryKey=" (" + partitionKey + ")," + clusterKey; - - if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )"); - } - fieldsString.append(")"); - - } // end of last field check - - } // end of for each - // information about the name-value style properties - Map<String, Object> propertiesMap = tableObj.getProperties(); - StringBuilder propertiesString = new StringBuilder(); - if (propertiesMap != null) { - counter = 0; - for (Map.Entry<String, Object> entry : propertiesMap.entrySet()) { - Object ot = entry.getValue(); - String value = ot + ""; - if (ot instanceof String) { - value = "'" + value + "'"; - } else if (ot instanceof Map) { - @SuppressWarnings("unchecked") - Map<String, Object> otMap = (Map<String, Object>) ot; - value = "{" + MusicUtil.jsonMaptoSqlString(otMap, ",") + "}"; - } - - propertiesString.append(entry.getKey() + "=" + value + ""); - if (counter != propertiesMap.size() - 1) - propertiesString.append(" AND "); - - counter = counter + 1; - } - } - - String clusteringOrder = tableObj.getClusteringOrder(); - - if (clusteringOrder != null && !(clusteringOrder.isEmpty())) { - String[] arrayClusterOrder = clusteringOrder.split("[,]+"); - - for (int i = 0; i < arrayClusterOrder.length; i++) { - String[] clusterS = arrayClusterOrder[i].trim().split("[ ]+"); - if ( (clusterS.length ==2) && (clusterS[1].equalsIgnoreCase("ASC") || clusterS[1].equalsIgnoreCase("DESC"))) { - continue; - } else { - return response.status(Status.BAD_REQUEST) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname order; please correct clusteringOrder:"+ clusteringOrder+".") - .toMap()).build(); - } - // add validation for column names in cluster key - } - - if (!(clusterKey.isEmpty())) { - clusteringOrder = "CLUSTERING ORDER BY (" +clusteringOrder +")"; - //cjc check if propertiesString.length() >0 instead propertiesMap - if (propertiesMap != null) { - propertiesString.append(" AND "+ clusteringOrder); - } else { - propertiesString.append(clusteringOrder); - } - } else { - logger.warn("Skipping clustering order=("+clusteringOrder+ ") since clustering key is empty "); - } - } //if non empty - - queryObject.appendQueryString( - "CREATE TABLE " + keyspace + "." + tablename + " " + fieldsString); - - - if (propertiesString != null && propertiesString.length()>0 ) - queryObject.appendQueryString(" WITH " + propertiesString); - queryObject.appendQueryString(";"); ResultType result = ResultType.FAILURE; try { - result = MusicCore.createTable(keyspace, tablename, queryObject, consistency); + tableObj.setKeyspaceName(keyspace); + tableObj.setTableName(tablename); + result = MusicCore.createTable(tableObj, consistency); + } catch (MusicQueryException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), ex.getMessage() ,ErrorSeverity + .WARN, ErrorTypes.MUSICSERVICEERROR, ex); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); } catch (MusicServiceException ex) { logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.MUSICSERVICEERROR); response.status(Status.BAD_REQUEST); @@ -501,14 +360,34 @@ public class RestMusicDataAPI { */ @POST @Path("/{keyspace: .*}/tables/{tablename: .*}/index/{field: .*}") - @ApiOperation(value = "Create Index", response = String.class) + @ApiOperation(value = "Create Index", response = String.class, + notes = "An index provides a means to access data using attributes " + + "other than the partition key. The benefit is fast, efficient lookup " + + "of data matching a given condition.") @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"message\" : \"Index Created on <keyspace>.<table>.<field>\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"<errorMessage>\"," + + "\"status\" : \"FAILURE\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Unknown Error in create index.\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response createIndex( @ApiParam(value = "Major Version",required = true) @PathParam("version") String version, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid, - @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam(NS) String ns, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, @ApiParam(value = "Keyspace Name",required = true) @PathParam("keyspace") String keyspace, @ApiParam(value = "Table Name",required = true) @PathParam("tablename") String tablename, @@ -526,13 +405,12 @@ public class RestMusicDataAPI { String indexName = ""; if (rowParams.getFirst("index_name") != null) indexName = rowParams.getFirst("index_name"); - PreparedQueryObject query = new PreparedQueryObject(); - query.appendQueryString("Create index if not exists " + indexName + " on " + keyspace + "." - + tablename + " (" + fieldName + ");"); - + + JsonIndex jsonIndexObject = new JsonIndex(indexName, keyspace, tablename, fieldName); + ResultType result = ResultType.FAILURE; try { - result = MusicCore.nonKeyRelatedPut(query, "eventual"); + result = MusicCore.createIndex(jsonIndexObject, MusicUtil.EVENTUAL); } catch (MusicServiceException ex) { logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity .CRITICAL, ErrorTypes.GENERALSERVICEERROR, ex); @@ -559,9 +437,22 @@ public class RestMusicDataAPI { */ @POST @Path("/{keyspace: .*}/tables/{tablename: .*}/rows") - @ApiOperation(value = "Insert Into Table", response = String.class) + @ApiOperation(value = "Insert Into Table", response = String.class, + notes = "Insert into table with data in json body.") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"message\" : \"Insert Successful\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure - Generic",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"<errorMessage>\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response insertIntoTable( @ApiParam(value = "Major Version",required = true) @PathParam("version") String version, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @@ -586,143 +477,12 @@ public class RestMusicDataAPI { .toMap()).build(); } EELFLoggerDelegate.mdcPut("keyspace","(" + keyspace + ")"); - PreparedQueryObject queryObject = new PreparedQueryObject(); - TableMetadata tableInfo = null; - try { - tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename); - if(tableInfo == null) { - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Table name doesn't exists. Please check the table name.").toMap()).build(); - } - } catch (MusicServiceException e) { - logger.error(EELFLoggerDelegate.errorLogger, e, AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); - } - String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName(); - StringBuilder fieldsString = new StringBuilder("(vector_ts,"); - String vectorTs = - String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis()); - StringBuilder valueString = new StringBuilder("(" + "?" + ","); - queryObject.addValue(vectorTs); - - Map<String, Object> valuesMap = insObj.getValues(); - if (valuesMap==null) { - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) - .setError("Nothing to insert. No values provided in request.").toMap()).build(); - } - int counter = 0; - String primaryKey = ""; - for (Map.Entry<String, Object> entry : valuesMap.entrySet()) { - fieldsString.append("" + entry.getKey()); - Object valueObj = entry.getValue(); - if (primaryKeyName.equals(entry.getKey())) { - primaryKey = entry.getValue() + ""; - primaryKey = primaryKey.replace("'", "''"); - } - DataType colType = null; - try { - colType = tableInfo.getColumn(entry.getKey()).getType(); - } catch(NullPointerException ex) { - logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() +" Invalid column name : "+entry.getKey - (), AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR, ex); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap()).build(); - } - - Object formattedValue = null; - try { - formattedValue = MusicUtil.convertToActualDataType(colType, valueObj); - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger,e); - } - valueString.append("?"); - - queryObject.addValue(formattedValue); - - if (counter == valuesMap.size() - 1) { - fieldsString.append(")"); - valueString.append(")"); - } else { - fieldsString.append(","); - valueString.append(","); - } - counter = counter + 1; - } - - //blobs.. - Map<String, byte[]> objectMap = insObj.getObjectMap(); - if(objectMap != null) { - for (Map.Entry<String, byte[]> entry : objectMap.entrySet()) { - if(counter > 0) { - fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ","); - valueString.replace(valueString.length()-1, valueString.length(), ","); - } - fieldsString.append("" + entry.getKey()); - byte[] valueObj = entry.getValue(); - if (primaryKeyName.equals(entry.getKey())) { - primaryKey = entry.getValue() + ""; - primaryKey = primaryKey.replace("'", "''"); - } - DataType colType = tableInfo.getColumn(entry.getKey()).getType(); - ByteBuffer formattedValue = null; - if(colType.toString().toLowerCase().contains("blob")) { - formattedValue = MusicUtil.convertToActualDataType(colType, valueObj); - } - valueString.append("?"); - queryObject.addValue(formattedValue); - counter = counter + 1; - fieldsString.append(","); - valueString.append(","); - } - } - - if(primaryKey == null || primaryKey.length() <= 0) { - logger.error(EELFLoggerDelegate.errorLogger, "Some required partition key parts are missing: "+primaryKeyName ); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Some required partition key parts are missing: "+primaryKeyName).toMap()).build(); - } - - fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ")"); - valueString.replace(valueString.length()-1, valueString.length(), ")"); - - queryObject.appendQueryString("INSERT INTO " + keyspace + "." + tablename + " " - + fieldsString + " VALUES " + valueString); - - String ttl = insObj.getTtl(); - String timestamp = insObj.getTimestamp(); - - if ((ttl != null) && (timestamp != null)) { - logger.info(EELFLoggerDelegate.applicationLogger, "both there"); - queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?"); - queryObject.addValue(Integer.parseInt(ttl)); - queryObject.addValue(Long.parseLong(timestamp)); - } - - if ((ttl != null) && (timestamp == null)) { - logger.info(EELFLoggerDelegate.applicationLogger, "ONLY TTL there"); - queryObject.appendQueryString(" USING TTL ?"); - queryObject.addValue(Integer.parseInt(ttl)); - } - - if ((ttl == null) && (timestamp != null)) { - logger.info(EELFLoggerDelegate.applicationLogger, "ONLY timestamp there"); - queryObject.appendQueryString(" USING TIMESTAMP ?"); - queryObject.addValue(Long.parseLong(timestamp)); - } - - queryObject.appendQueryString(";"); - ReturnType result = null; String consistency = insObj.getConsistencyInfo().get("type"); - if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && insObj.getConsistencyInfo().get("consistency") != null) { - if(MusicUtil.isValidConsistency(insObj.getConsistencyInfo().get("consistency"))) { - queryObject.setConsistency(insObj.getConsistencyInfo().get("consistency")); - } else { - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build(); - } - } - queryObject.setOperation("insert"); try { - if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) { - result = MusicCore.eventualPut(queryObject); - } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + insObj.setKeyspaceName(keyspace); + insObj.setTableName(tablename); + if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { String lockId = insObj.getConsistencyInfo().get("lockId"); if(lockId == null) { logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" @@ -730,11 +490,13 @@ public class RestMusicDataAPI { return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock " + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build(); } - result = MusicCore.criticalPut(keyspace, tablename, primaryKey, queryObject, lockId,null); - } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { - result = MusicCore.atomicPut(keyspace, tablename, primaryKey, queryObject, null); } - } catch (Exception ex) { + result = MusicCore.insertIntoTable(insObj); + }catch (MusicQueryException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), ex.getMessage() ,ErrorSeverity + .WARN, ErrorTypes.MUSICSERVICEERROR, ex); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); + }catch (Exception ex) { logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity .WARN, ErrorTypes.MUSICSERVICEERROR, ex); return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); @@ -764,7 +526,8 @@ public class RestMusicDataAPI { */ @PUT @Path("/{keyspace: .*}/tables/{tablename: .*}/rows") - @ApiOperation(value = "Update Table", response = String.class) + @ApiOperation(value = "Update Table", response = String.class, + notes = "Update the table with the data in the JSON body.") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response updateTable( @@ -800,153 +563,41 @@ public class RestMusicDataAPI { String operationId = UUID.randomUUID().toString(); // just for infoging // purposes. String consistency = updateObj.getConsistencyInfo().get("type"); - + ReturnType operationResult = null; logger.info(EELFLoggerDelegate.applicationLogger, "--------------Music " + consistency + " update-" + operationId + "-------------------------"); - // obtain the field value pairs of the update - - PreparedQueryObject queryObject = new PreparedQueryObject(); - Map<String, Object> valuesMap = updateObj.getValues(); - - TableMetadata tableInfo; - try { - tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename); - } catch (MusicServiceException e) { - logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes - .GENERALSERVICEERROR, e); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); - } - if (tableInfo == null) { - logger.error(EELFLoggerDelegate.errorLogger,"Table information not found. Please check input for table name= "+tablename, AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) - .setError("Table information not found. Please check input for table name= " - + keyspace + "." + tablename).toMap()).build(); - } - String vectorTs = String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis()); - StringBuilder fieldValueString = new StringBuilder("vector_ts=?,"); - queryObject.addValue(vectorTs); - int counter = 0; - for (Map.Entry<String, Object> entry : valuesMap.entrySet()) { - Object valueObj = entry.getValue(); - DataType colType = null; - try { - colType = tableInfo.getColumn(entry.getKey()).getType(); - } catch(NullPointerException ex) { - logger.error(EELFLoggerDelegate.errorLogger, ex, "Invalid column name : "+entry.getKey(), ex); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap()).build(); - } - Object valueString = null; - try { - valueString = MusicUtil.convertToActualDataType(colType, valueObj); - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger,e); - } - fieldValueString.append(entry.getKey() + "= ?"); - queryObject.addValue(valueString); - if (counter != valuesMap.size() - 1) { - fieldValueString.append(","); - } - counter = counter + 1; - } - String ttl = updateObj.getTtl(); - String timestamp = updateObj.getTimestamp(); - - queryObject.appendQueryString("UPDATE " + keyspace + "." + tablename + " "); - if ((ttl != null) && (timestamp != null)) { - logger.info("both there"); - queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?"); - queryObject.addValue(Integer.parseInt(ttl)); - queryObject.addValue(Long.parseLong(timestamp)); - } - - if ((ttl != null) && (timestamp == null)) { - logger.info("ONLY TTL there"); - queryObject.appendQueryString(" USING TTL ?"); - queryObject.addValue(Integer.parseInt(ttl)); - } - - if ((ttl == null) && (timestamp != null)) { - logger.info("ONLY timestamp there"); - queryObject.appendQueryString(" USING TIMESTAMP ?"); - queryObject.addValue(Long.parseLong(timestamp)); - } - // get the row specifier - RowIdentifier rowId = null; + + updateObj.setKeyspaceName(keyspace); + updateObj.setTableName(tablename); + try { - rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject); - if(rowId == null || rowId.primarKeyValue.isEmpty()) { - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) - .setError("Mandatory WHERE clause is missing. Please check the input request.").toMap()).build(); + if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + String lockId = updateObj.getConsistencyInfo().get("lockId"); + if(lockId == null) { + logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" + + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock " + + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build(); + } } - } catch (MusicServiceException ex) { - logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes - .GENERALSERVICEERROR, ex); + operationResult = MusicCore.updateTable(updateObj,info.getQueryParameters()); + }catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, + ErrorTypes.GENERALSERVICEERROR, e); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); + }catch (MusicQueryException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), ex.getMessage() ,ErrorSeverity + .WARN, ErrorTypes.MUSICSERVICEERROR, ex); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); + }catch (Exception ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity + .WARN, ErrorTypes.MUSICSERVICEERROR, ex); return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); - } - - queryObject.appendQueryString( - " SET " + fieldValueString + " WHERE " + rowId.rowIdString + ";"); - - // get the conditional, if any - Condition conditionInfo; - if (updateObj.getConditions() == null) { - conditionInfo = null; - } else { - // to avoid parsing repeatedly, just send the select query to obtain row - PreparedQueryObject selectQuery = new PreparedQueryObject(); - selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE " - + rowId.rowIdString + ";"); - selectQuery.addValue(rowId.primarKeyValue); - conditionInfo = new Condition(updateObj.getConditions(), selectQuery); - } - - ReturnType operationResult = null; - long jsonParseCompletionTime = System.currentTimeMillis(); - - if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && updateObj.getConsistencyInfo().get("consistency") != null) { - if(MusicUtil.isValidConsistency(updateObj.getConsistencyInfo().get("consistency"))) { - queryObject.setConsistency(updateObj.getConsistencyInfo().get("consistency")); - } else { - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build(); - } - } - queryObject.setOperation("update"); - if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) { - operationResult = MusicCore.eventualPut(queryObject); - } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { - String lockId = updateObj.getConsistencyInfo().get("lockId"); - if(lockId == null) { - logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" - + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock " - + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build(); - } - operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue, - queryObject, lockId, conditionInfo); - } else if (consistency.equalsIgnoreCase("atomic_delete_lock")) { - // this function is mainly for the benchmarks - try { - operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, - rowId.primarKeyValue, queryObject, conditionInfo); - } catch (MusicLockingException e) { - logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, - ErrorTypes.GENERALSERVICEERROR, e); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); - } - } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { - try { - operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue, - queryObject, conditionInfo); - } catch (MusicLockingException e) { - logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR, e); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); - } - } else if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) { - operationResult = MusicCore.eventualPut_nb(queryObject, keyspace, tablename, rowId.primarKeyValue); } long actualUpdateCompletionTime = System.currentTimeMillis(); long endTime = System.currentTimeMillis(); + long jsonParseCompletionTime = System.currentTimeMillis(); String timingString = "Time taken in ms for Music " + consistency + " update-" + operationId + ":" + "|total operation time:" + (endTime - startTime) + "|json parsing time:" + (jsonParseCompletionTime - startTime) @@ -987,7 +638,8 @@ public class RestMusicDataAPI { */ @DELETE @Path("/{keyspace: .*}/tables/{tablename: .*}/rows") - @ApiOperation(value = "Delete From table", response = String.class) + @ApiOperation(value = "Delete From table", response = String.class, + notes = "Delete from a table, the row or parts of a row. Based on JSON body.") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response deleteFromTable( @@ -1019,76 +671,12 @@ public class RestMusicDataAPI { logger.error(EELFLoggerDelegate.errorLogger,ResultType.BODYMISSING.getResult(), AppMessages.MISSINGDATA ,ErrorSeverity.WARN, ErrorTypes.DATAERROR); return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ResultType.BODYMISSING.getResult()).toMap()).build(); } - PreparedQueryObject queryObject = new PreparedQueryObject(); - StringBuilder columnString = new StringBuilder(); - - int counter = 0; - List<String> columnList = delObj.getColumns(); - if (columnList != null) { - for (String column : columnList) { - columnString.append(column); - if (counter != columnList.size() - 1) - columnString.append(","); - counter = counter + 1; - } - } - - // get the row specifier - RowIdentifier rowId = null; - try { - rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject); - } catch (MusicServiceException ex) { - logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes - .GENERALSERVICEERROR, ex); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); - } - String rowSpec = rowId.rowIdString.toString(); - - if ((columnList != null) && (!rowSpec.isEmpty())) { - queryObject.appendQueryString("DELETE " + columnString + " FROM " + keyspace + "." - + tablename + " WHERE " + rowSpec + ";"); - } - - if ((columnList == null) && (!rowSpec.isEmpty())) { - queryObject.appendQueryString("DELETE FROM " + keyspace + "." + tablename + " WHERE " - + rowSpec + ";"); - } - - if ((columnList != null) && (rowSpec.isEmpty())) { - queryObject.appendQueryString( - "DELETE " + columnString + " FROM " + keyspace + "." + rowSpec + ";"); - } - // get the conditional, if any - Condition conditionInfo; - if (delObj.getConditions() == null) { - conditionInfo = null; - } else { - // to avoid parsing repeatedly, just send the select query to - // obtain row - PreparedQueryObject selectQuery = new PreparedQueryObject(); - selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE " - + rowId.rowIdString + ";"); - selectQuery.addValue(rowId.primarKeyValue); - conditionInfo = new Condition(delObj.getConditions(), selectQuery); - } - - String consistency = delObj.getConsistencyInfo().get("type"); - - - if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && delObj.getConsistencyInfo().get("consistency")!=null) { - if(MusicUtil.isValidConsistency(delObj.getConsistencyInfo().get("consistency"))) { - queryObject.setConsistency(delObj.getConsistencyInfo().get("consistency")); - } else { - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR) - .setError("Invalid Consistency type").toMap()).build(); - } - } ReturnType operationResult = null; - queryObject.setOperation("delete"); + String consistency = delObj.getConsistencyInfo().get("type"); + delObj.setKeyspaceName(keyspace); + delObj.setTableName(tablename); try { - if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) - operationResult = MusicCore.eventualPut(queryObject); - else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { String lockId = delObj.getConsistencyInfo().get("lockId"); if(lockId == null) { logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" @@ -1096,14 +684,14 @@ public class RestMusicDataAPI { return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock " + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build(); } - operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue, - queryObject, lockId, conditionInfo); - } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { - operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue, - queryObject, conditionInfo); - } else if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) { - operationResult = MusicCore.eventualPut_nb(queryObject, keyspace, tablename, rowId.primarKeyValue); } + + operationResult = MusicCore.deleteFromTable(delObj,info.getQueryParameters()); + } catch (MusicQueryException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), ex.getMessage() ,ErrorSeverity + .WARN, ErrorTypes.MUSICSERVICEERROR, ex); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); + } catch (MusicLockingException e) { logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR, e); return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) @@ -1135,6 +723,17 @@ public class RestMusicDataAPI { @Path("/{keyspace: .*}/tables/{tablename: .*}") @ApiOperation(value = "Drop Table", response = String.class) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"<errorMessage>\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response dropTable( @ApiParam(value = "Major Version", required = true) @PathParam("version") String version, @@ -1142,7 +741,7 @@ public class RestMusicDataAPI { required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version", required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "AID", required = false,hidden = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", required = false, hidden = true) @HeaderParam(NS) String ns, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, @@ -1158,14 +757,18 @@ public class RestMusicDataAPI { .toMap()).build(); } EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) "); - String consistency = "eventual";// for now this needs only eventual consistency - PreparedQueryObject query = new PreparedQueryObject(); - query.appendQueryString("DROP TABLE " + keyspace + "." + tablename + ";"); + JsonTable jsonTable = new JsonTable(); + jsonTable.setKeyspaceName(keyspace); + jsonTable.setTableName(tablename); try { - return response.status(Status.OK).entity(new JsonResponse(MusicCore.nonKeyRelatedPut(query, consistency)).toMap()).build(); + return response.status(Status.OK).entity(new JsonResponse(MusicCore.dropTable(jsonTable, MusicUtil.EVENTUAL)).toMap()).build(); + } catch (MusicQueryException ex) { + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), AppMessages.QUERYERROR,ErrorSeverity.WARN + , ErrorTypes.QUERYERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); } catch (MusicServiceException ex) { - logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes - .GENERALSERVICEERROR); + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN + , ErrorTypes.GENERALSERVICEERROR,ex); return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); } } finally { @@ -1183,15 +786,34 @@ public class RestMusicDataAPI { */ @PUT @Path("/{keyspace: .*}/tables/{tablename: .*}/rows/criticalget") - @ApiOperation(value = "Select Critical", response = Map.class) + @ApiOperation(value = "** Depreciated ** - Select Critical", response = Map.class, + notes = "This API is depreciated in favor of the regular select api.\n" + + "Avaliable to use with the select api by providing a minorVersion of 1 " + + "and patchVersion of 0.\n" + + "Critical Get requires parameter rowId=value and consistency in order to work.\n" + + "It will fail if either are missing.") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"result\":{\"row 0\":{\"address\":" + + "{\"city\":\"Someplace\",\"street\":\"1 Some way\"}," + + "\"emp_salary\":50,\"emp_name\":\"tom\",\"emp_id\":" + + "\"cfd66ccc-d857-4e90-b1e5-df98a3d40cd6\"}},\"status\":\"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"<errorMessage>\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response selectCritical( @ApiParam(value = "Major Version", - required = true) @PathParam("version") String version, - @ApiParam(value = "Minor Version", + required = true) @PathParam("version") String version, + @ApiParam(value = "Minor Version",example = "0", required = false) @HeaderParam(XMINORVERSION) String minorVersion, - @ApiParam(value = "Patch Version", + @ApiParam(value = "Patch Version",example = "0", required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", @@ -1205,49 +827,46 @@ public class RestMusicDataAPI { @Context UriInfo info) throws Exception { try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); - if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){ + if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())) { return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) .setError("one or more path parameters are not set, please check and try again") .toMap()).build(); } - if(selObj == null) { - logger.error(EELFLoggerDelegate.errorLogger,ResultType.BODYMISSING.getResult(), AppMessages.MISSINGDATA ,ErrorSeverity.WARN, ErrorTypes.DATAERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ResultType.BODYMISSING.getResult()).toMap()).build(); + EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspace + " )"); + if (info.getQueryParameters().isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger,RestMusicDataAPI.PARAMETER_ERROR, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes + .GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(RestMusicDataAPI.PARAMETER_ERROR).toMap()).build(); } - - EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) "); - String lockId = selObj.getConsistencyInfo().get("lockId"); - PreparedQueryObject queryObject = new PreparedQueryObject(); - RowIdentifier rowId = null; - try { - rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject); - } catch (MusicServiceException ex) { - logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes - .GENERALSERVICEERROR, ex); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); + if (selObj == null || selObj.getConsistencyInfo().isEmpty()) { + String error = " Missing Body or Consistency type."; + logger.error(EELFLoggerDelegate.errorLogger,ResultType.BODYMISSING.getResult() + error, AppMessages.MISSINGDATA ,ErrorSeverity.WARN, ErrorTypes.DATAERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ResultType.BODYMISSING.getResult() + error).toMap()).build(); } - queryObject.appendQueryString( - "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowId.rowIdString + ";"); - ResultSet results = null; - String consistency = selObj.getConsistencyInfo().get("type"); + String lockId = selObj.getConsistencyInfo().get("lockId"); + selObj.setKeyspaceName(keyspace); + selObj.setTableName(tablename); try { - if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { - if(lockId == null) { - logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" - + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock " - + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build(); + if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + if(lockId == null) { + logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" + + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock " + + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build(); + } } - results = MusicCore.criticalGet(keyspace, tablename, rowId.primarKeyValue, queryObject,lockId); - } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { - results = MusicCore.atomicGet(keyspace, tablename, rowId.primarKeyValue, queryObject); - } + results = MusicCore.selectCritical(selObj, info.getQueryParameters()); + }catch (MusicQueryException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), ex.getMessage() ,ErrorSeverity + .WARN, ErrorTypes.MUSICSERVICEERROR, ex); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); + }catch(Exception ex) { return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); } - + if(results!=null && results.getAvailableWithoutFetching() >0) { return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build(); } @@ -1258,33 +877,74 @@ public class RestMusicDataAPI { } /** - * + * This API will replace the original select and provide a single API fro select and critical. + * The idea is to depreciate the older api of criticalGet and use a single API. + * + * @param selObj * @param keyspace * @param tablename * @param info * @return - * @throws Exception */ @GET @Path("/{keyspace: .*}/tables/{tablename: .*}/rows") - @ApiOperation(value = "Select All or Select Specific", response = Map.class) + @ApiOperation(value = "Select", response = Map.class, + notes = "This has 2 versions: if minorVersion and patchVersion is null or 0, this will be a Eventual Select only.\n" + + "If minorVersion is 1 and patchVersion is 0, this will act like the Critical Select \n" + + "Critical Get requires parameter rowId=value and consistency in order to work.\n" + + "If parameters are missing or consistency information is missing. An eventual select will be preformed.") + @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - public Response select( - @ApiParam(value = "Major Version", + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"result\":{\"row 0\":{\"address\":" + + "{\"city\":\"Someplace\",\"street\":\"1 Some way\"}," + + "\"emp_salary\":50,\"emp_name\":\"tom\",\"emp_id\":" + + "\"cfd66ccc-d857-4e90-b1e5-df98a3d40cd6\"}},\"status\":\"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"<errorMessage>\"," + + "\"status\" : \"FAILURE\"}") + })) + }) + public Response selectWithCritical( + @ApiParam(value = "Major Version",example = "v2", required = true) @PathParam("version") String version, - @ApiParam(value = "Minor Version", + @ApiParam(value = "Minor Version",example = "1", required = false) @HeaderParam(XMINORVERSION) String minorVersion, - @ApiParam(value = "Patch Version", + @ApiParam(value = "Patch Version",example = "0", required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", required = false,hidden = true) @HeaderParam(NS) String ns, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "Keyspace Name", - required = true) @PathParam("keyspace") String keyspace, - @ApiParam(value = "Table Name", - required = true) @PathParam("tablename") String tablename, + JsonInsert selObj, + @ApiParam(value = "Keyspace Name", required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Table Name", required = true) @PathParam("tablename") String tablename, @Context UriInfo info) throws Exception { + if ((minorVersion != null && patchVersion != null) && + (Integer.parseInt(minorVersion) == 1 && Integer.parseInt(patchVersion) == 0) && + (!(null == selObj) && !selObj.getConsistencyInfo().isEmpty())) { + return selectCritical(version, minorVersion, patchVersion, aid, ns, authorization, selObj, keyspace, tablename, info); + } else { + return select(version, minorVersion, patchVersion, aid, ns, authorization, keyspace, tablename, info); + } + } + + /** + * + * @param keyspace + * @param tablename + * @param info + * @return + * @throws Exception + */ + private Response select( + String version,String minorVersion,String patchVersion, + String aid,String ns,String authorization,String keyspace, + String tablename,UriInfo info) throws Exception { try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){ @@ -1293,26 +953,20 @@ public class RestMusicDataAPI { .toMap()).build(); } EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspace + " ) "); - PreparedQueryObject queryObject = new PreparedQueryObject(); - - if (info.getQueryParameters().isEmpty()) { // select all - queryObject.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + ";"); - } else { - int limit = -1; // do not limit the number of results - try { - queryObject = selectSpecificQuery(keyspace, tablename, info, limit); - } catch (MusicServiceException ex) { - logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, - ErrorTypes.GENERALSERVICEERROR, ex); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); - } - } try { - ResultSet results = MusicCore.get(queryObject); + JsonSelect jsonSelect = new JsonSelect(); + jsonSelect.setKeyspaceName(keyspace); + jsonSelect.setTableName(tablename); + ResultSet results = MusicCore.select(jsonSelect, info.getQueryParameters()); if(results.getAvailableWithoutFetching() >0) { return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build(); } return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).setError("No data found").toMap()).build(); + } catch (MusicQueryException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), ex.getMessage() ,ErrorSeverity + .WARN, ErrorTypes.MUSICSERVICEERROR, ex); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); + } catch (MusicServiceException ex) { logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.ERROR, ErrorTypes.MUSICSERVICEERROR, ex); diff --git a/src/main/java/org/onap/music/rest/RestMusicHealthCheckAPI.java b/src/main/java/org/onap/music/rest/RestMusicHealthCheckAPI.java index cb8965ee..eef3aa3a 100644 --- a/src/main/java/org/onap/music/rest/RestMusicHealthCheckAPI.java +++ b/src/main/java/org/onap/music/rest/RestMusicHealthCheckAPI.java @@ -62,32 +62,44 @@ public class RestMusicHealthCheckAPI { private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicUtil.class); private static final String ACTIVE_STATUS = "ACTIVE"; + private static final String INVALID_STATUS = "INVALID"; + private static final String INACTIVE_STATUS = "INACTIVE"; + private static final String INVALID_MESSAGE = "Consistency level is invalid..."; + private static final String INACTIVE_MESSAGE = "One or more nodes in the Cluster is/are down or not responding."; + private static final String ACTIVE_MESSAGE = "Cassandra Running and Listening to requests"; + private static final String STATUS_KEY = "status"; + private static final String MESSAGE_KEY = "message"; @GET @Path("/pingCassandra/{consistency}") @ApiOperation(value = "Get Health Status", response = Map.class) @Produces(MediaType.APPLICATION_JSON) - public Response cassandraStatus(@Context HttpServletResponse response, @ApiParam(value = "Consistency level", - required = true) @PathParam("consistency") String consistency) { + public Response cassandraStatus( + @Context HttpServletResponse response, + @ApiParam(value = "Consistency level",required = true) + @PathParam("consistency") String consistency) { logger.info(EELFLoggerDelegate.applicationLogger,"Replying to request for MUSIC Health Check status for Cassandra"); Map<String, Object> resultMap = new HashMap<>(); if(ConsistencyLevel.valueOf(consistency) == null) { - resultMap.put("INVALID", "Consistency level is invalid..."); + resultMap.put(STATUS_KEY,INVALID_STATUS); + resultMap.put(MESSAGE_KEY, INVALID_MESSAGE); + resultMap.put(INVALID_STATUS, INVALID_STATUS); return Response.status(Status.BAD_REQUEST).entity(resultMap).build(); } MusicHealthCheck cassHealthCheck = new MusicHealthCheck(); String status = cassHealthCheck.getCassandraStatus(consistency); if(status.equals(ACTIVE_STATUS)) { - resultMap.put(ACTIVE_STATUS, "Cassandra Running and Listening to requests"); + resultMap.put(STATUS_KEY,ACTIVE_STATUS); + resultMap.put(MESSAGE_KEY, ACTIVE_MESSAGE); + resultMap.put(ACTIVE_STATUS, ACTIVE_MESSAGE); return Response.status(Status.OK).entity(resultMap).build(); } else { - resultMap.put("INACTIVE", "One or more nodes in the Cluster is/are down or not responding."); + resultMap.put(STATUS_KEY,INACTIVE_STATUS); + resultMap.put(MESSAGE_KEY, INACTIVE_MESSAGE); + resultMap.put(INACTIVE_STATUS, INACTIVE_MESSAGE); return Response.status(Status.BAD_REQUEST).entity(resultMap).build(); } - - - } @GET diff --git a/src/main/java/org/onap/music/rest/RestMusicLocksAPI.java b/src/main/java/org/onap/music/rest/RestMusicLocksAPI.java index 079fe97c..35f03e60 100644 --- a/src/main/java/org/onap/music/rest/RestMusicLocksAPI.java +++ b/src/main/java/org/onap/music/rest/RestMusicLocksAPI.java @@ -59,10 +59,14 @@ import org.onap.music.response.jsonobjects.JsonResponse; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import io.swagger.annotations.Example; +import io.swagger.annotations.ExampleProperty; @Path("/v2/locks/") -@Api(value="Lock Api") +@Api(value="Locking Api") public class RestMusicLocksAPI { private EELFLoggerDelegate logger =EELFLoggerDelegate.getLogger(RestMusicLocksAPI.class); @@ -80,22 +84,40 @@ public class RestMusicLocksAPI { */ @POST @Path("/create/{lockname}") - @ApiOperation(value = "Create Lock", - notes = "Puts the requesting process in the q for this lock." + - " The corresponding lock will be created if it did not already exist." + - " Lock Name is the \"key\" of the form keyspaceName.tableName.rowId", + @ApiOperation(value = "Create and Acquire a Lock Id for a single row.", + notes = "Creates and Acquires a Lock Id for a specific Row in a table based on the key of that row.\n" + + " The corresponding lock will be created if it did not already exist." + + " Lock Name also the Lock is in the form of keyspaceName.tableName.rowId.\n" + + " The Response will be in the form of \"$kesypaceName.tableName.rowId$lockRef\" " + + " where the lockRef is a integer representing the Lock Name buffered by \"$\" " + + " followed by the lock number. This term for " + + " this response is a lockId and it will be used in other /locks API calls where a " + + " lockId is required. If just a lock is required then the form that would be " + + " the original lockname(without the buffered \"$\").", response = Map.class) @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"lock\" : {\"lock\" : \"$keyspace.table.rowId$<integer>\"}," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Unable to aquire lock\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response createLockReference( @ApiParam(value="Lock Name",required=true) @PathParam("lockname") String lockName, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, JsonLock lockObject, @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map<String, Object> resultMap = MusicCore.validateLock(lockName); @@ -138,19 +160,32 @@ public class RestMusicLocksAPI { * @throws Exception */ @GET - @Path("/acquire/{lockreference}") - @ApiOperation(value = "Aquire Lock", + @Path("/acquire/{lockId}") + @ApiOperation(value = "Aquire Lock Id ", notes = "Checks if the node is in the top of the queue and hence acquires the lock", response = Map.class) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"lock\" : {\"lock\" : \"$keyspace.table.rowId$<integer>\"}," + + "\"message\" : \"<integer> is the lock holder for the key\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Unable to aquire lock\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response accquireLock( - @ApiParam(value="Lock Reference",required=true) @PathParam("lockreference") String lockId, + @ApiParam(value="Lock Id",required=true) @PathParam("lockId") String lockId, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map<String, Object> resultMap = MusicCore.validateLock(lockId); @@ -182,21 +217,40 @@ public class RestMusicLocksAPI { } - - @POST - @Path("/acquire-with-lease/{lockreference}") - @ApiOperation(value = "Aquire Lock with Lease", response = Map.class) + @Path("/acquire-with-lease/{lockId}") + @ApiOperation( + hidden = false, + value = " ** DEPRECATED ** - Aquire Lock with Lease", + notes = "Acquire the lock with a lease, where lease period is in Milliseconds.\n" + + "This will ensure that a lock will expire in set milliseconds.\n" + + "This is no longer available after v3.2.0", + response = Map.class) @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - public Response accquireLockWithLease(JsonLeasedLock lockObj, - @ApiParam(value="Lock Reference",required=true) @PathParam("lockreference") String lockId, - @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, - @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, - @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"lock\" : {\"lock\" : \"$keyspace.table.rowId$<integer>\"," + + "\"lock-lease\" : \"6000\"}," + + "\"message\" : \"<integer> is the lock holder for the key\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Unable to aquire lock\"," + + "\"status\" : \"FAILURE\"}") + })) + }) + @Deprecated + public Response accquireLockWithLease( + JsonLeasedLock lockObj, + @ApiParam(value="Lock Id",required=true) @PathParam("lockId") String lockId, + @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, + @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, + @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map<String, Object> resultMap = MusicCore.validateLock(lockId); @@ -220,6 +274,8 @@ public class RestMusicLocksAPI { } finally { EELFLoggerDelegate.mdcRemove("keyspace"); } + + } @@ -229,14 +285,27 @@ public class RestMusicLocksAPI { notes = "Gets the current single lockholder at top of lock queue", response = Map.class) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"lock\" : {\"lock\" : \"keyspace.table.rowId\"," + + "\"lock-holder\" : \"$tomtest.employees.tom$<integer>\"}}," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Error Message\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response enquireLock( @ApiParam(value="Lock Name",required=true) @PathParam("lockname") String lockName, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map<String, Object> resultMap = MusicCore.validateLock(lockName); @@ -265,16 +334,30 @@ public class RestMusicLocksAPI { @GET @Path("/holders/{lockname}") @ApiOperation(value = "Get Lock Holders", - notes = "Gets the current Lock Holders", + notes = "Gets the current Lock Holders.\n" + + "Will return an array of READ Lock References.", response = Map.class) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"lock\" : {\"lock\" : \"keyspace.table.rowId\"," + + "\"lock-holder\" : [\"$keyspace.table.rowId$<integer1>\",\"$keyspace.table.rowId$<integer2>\"]}}," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Error message\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response currentLockHolder(@ApiParam(value="Lock Name",required=true) @PathParam("lockname") String lockName, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map<String, Object> resultMap = MusicCore.validateLock(lockName); @@ -290,9 +373,9 @@ public class RestMusicLocksAPI { List<String> who = MusicCore.getCurrentLockHolders(lockName); ResultType status = ResultType.SUCCESS; String error = ""; - if (who == null) { + if (who == null || who.isEmpty()) { status = ResultType.FAILURE; - error = "There was a problem getting the lock holder"; + error = (who !=null && who.isEmpty()) ? "No lock holders for the key":"There was a problem getting the lock holder"; logger.error(EELFLoggerDelegate.errorLogger, "There was a problem getting the lock holder", AppMessages.INCORRECTDATA, ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); return response.status(Status.BAD_REQUEST) @@ -300,8 +383,8 @@ public class RestMusicLocksAPI { .build(); } return response.status(Status.OK) - .entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).toMap()) - .build(); + .entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).setisLockHolders(true).toMap()) + .build(); } finally { EELFLoggerDelegate.mdcRemove("keyspace"); } @@ -312,16 +395,29 @@ public class RestMusicLocksAPI { @Path("/{lockname}") @ApiOperation(value = "Lock State", notes = "Returns current Lock State and Holder.", - response = Map.class) + response = Map.class,hidden = true) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"lock\" : {\"lock\" : \"$keyspace.table.rowId$<integer>\"}," + + "\"message\" : \"<integer> is the lock holder for the key\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Unable to aquire lock\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response currentLockState( @ApiParam(value="Lock Name",required=true) @PathParam("lockname") String lockName, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map<String, Object> resultMap = MusicCore.validateLock(lockName); @@ -358,16 +454,29 @@ public class RestMusicLocksAPI { @DELETE @Path("/release/{lockreference}") @ApiOperation(value = "Release Lock", - notes = "deletes the process from the lock queue", + notes = "Releases the lock from the lock queue.", response = Map.class) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success - UNLOCKED = Lock Removed.",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"lock\" : {\"lock\" : \"$keyspace.table.rowId$<integer>\"}," + + "\"lock-status\" : \"UNLOCKED\"}," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Unable to aquire lock\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response unLock(@PathParam("lockreference") String lockId, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map<String, Object> resultMap = MusicCore.validateLock(lockId); @@ -409,17 +518,32 @@ public class RestMusicLocksAPI { * @param lockName * @throws Exception */ + @Deprecated @DELETE @Path("/delete/{lockname}") - @ApiOperation(value = "Delete Lock", response = Map.class) + @ApiOperation( + hidden = true, + value = "-DEPRECATED- Delete Lock", response = Map.class, + notes = "-DEPRECATED- Delete the lock.") @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Error Message if any\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response deleteLock(@PathParam("lockname") String lockName, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map<String, Object> resultMap = MusicCore.validateLock(lockName); diff --git a/src/main/java/org/onap/music/rest/RestMusicQAPI.java b/src/main/java/org/onap/music/rest/RestMusicQAPI.java index 768f1a44..4def0e45 100755 --- a/src/main/java/org/onap/music/rest/RestMusicQAPI.java +++ b/src/main/java/org/onap/music/rest/RestMusicQAPI.java @@ -25,7 +25,6 @@ package org.onap.music.rest; -import java.util.HashMap; import java.util.Map; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; @@ -67,7 +66,7 @@ import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; @Path("/v2/priorityq/") -@Api(value = "Q Api") +@Api(value = "Q Api",hidden = true) public class RestMusicQAPI { private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicQAPI.class); @@ -95,7 +94,7 @@ public class RestMusicQAPI { @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, JsonTable tableObj, @ApiParam(value = "Key Space", required = true) @PathParam("keyspace") String keyspace, - @ApiParam(value = "Table Name", required = true) @PathParam("qname") String tablename) throws Exception { + @ApiParam(value = "Table Name", required = true) @PathParam("qname") String tablename) throws Exception { ResponseBuilder response = MusicUtil.buildVersionResponse(version, minorVersion, patchVersion); Map<String, String> fields = tableObj.getFields(); @@ -409,7 +408,7 @@ public class RestMusicQAPI { @ApiParam(value = "Table Name", required = true) @PathParam("qname") String tablename, @Context UriInfo info) throws Exception { - return new RestMusicDataAPI().select(version, minorVersion, patchVersion, aid, ns, authorization, keyspace, tablename, info);// , limit) + return new RestMusicDataAPI().selectWithCritical(version, minorVersion, patchVersion, aid, ns, authorization,null, keyspace, tablename, info);// , limit) } diff --git a/src/main/java/org/onap/music/rest/RestMusicTestAPI.java b/src/main/java/org/onap/music/rest/RestMusicTestAPI.java index 6d973acb..c1c04b09 100644 --- a/src/main/java/org/onap/music/rest/RestMusicTestAPI.java +++ b/src/main/java/org/onap/music/rest/RestMusicTestAPI.java @@ -51,6 +51,7 @@ public class RestMusicTestAPI { * @return */ @GET + @Path("/") @ApiOperation(value = "Get Test", response = Map.class) @Produces(MediaType.APPLICATION_JSON) public Map<String, HashMap<String, String>> simpleTests( @@ -60,6 +61,7 @@ public class RestMusicTestAPI { for(int i=0; i < 3; i++){ HashMap<String, String> innerMap = new HashMap<>(); innerMap.put("Music Version",MusicUtil.getVersion()); + innerMap.put("Music Build",MusicUtil.getBuild()); innerMap.put(i+1+"", i+2+""); testMap.put(i+"", innerMap); } diff --git a/src/main/java/org/onap/music/rest/RestMusicVersionAPI.java b/src/main/java/org/onap/music/rest/RestMusicVersionAPI.java index 94540eb1..8c86152e 100644 --- a/src/main/java/org/onap/music/rest/RestMusicVersionAPI.java +++ b/src/main/java/org/onap/music/rest/RestMusicVersionAPI.java @@ -3,6 +3,8 @@ * org.onap.music * =================================================================== * Copyright (c) 2017 AT&T Intellectual Property + * + * Modifications Copyright (C) 2019 IBM. * =================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,9 +38,6 @@ import org.onap.music.eelf.logging.EELFLoggerDelegate; import org.onap.music.main.MusicUtil; import org.onap.music.main.ResultType; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; - import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -48,7 +47,7 @@ import io.swagger.annotations.ApiOperation; public class RestMusicVersionAPI { private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicVersionAPI.class); - + private static final String MUSIC_KEY = "MUSIC:"; /** * Get the version of MUSIC. * @return @@ -60,7 +59,7 @@ public class RestMusicVersionAPI { logger.info("Replying to request for MUSIC version with MUSIC:" + MusicUtil.getVersion()); response.addHeader("X-latestVersion",MusicUtil.getVersion()); return new JsonResponse(ResultType.SUCCESS). - setMusicVersion("MUSIC:" + MusicUtil.getVersion()).toMap(); + setMusicVersion(MUSIC_KEY + MusicUtil.getVersion()).toMap(); } /** @@ -75,8 +74,8 @@ public class RestMusicVersionAPI { logger.info("Replying to request for MUSIC build with MUSIC:" + MusicUtil.getBuild()); response.addHeader("X-latestVersion",MusicUtil.getVersion()); return new JsonResponse(ResultType.SUCCESS) - .setMusicBuild("MUSIC:" + MusicUtil.getBuild()) - .setMusicVersion("MUSIC:" + MusicUtil.getVersion()).toMap(); + .setMusicBuild(MUSIC_KEY + MusicUtil.getBuild()) + .setMusicVersion(MUSIC_KEY + MusicUtil.getVersion()).toMap(); } diff --git a/src/main/java/org/onap/music/service/MusicCoreService.java b/src/main/java/org/onap/music/service/MusicCoreService.java index a50e7c2a..c96d2b30 100644 --- a/src/main/java/org/onap/music/service/MusicCoreService.java +++ b/src/main/java/org/onap/music/service/MusicCoreService.java @@ -25,7 +25,17 @@ package org.onap.music.service; import java.util.List; import java.util.Map; +import javax.ws.rs.core.MultivaluedMap; + +import org.onap.music.datastore.Condition; import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.datastore.jsonobjects.JsonDelete; +import org.onap.music.datastore.jsonobjects.JsonIndex; +import org.onap.music.datastore.jsonobjects.JsonInsert; +import org.onap.music.datastore.jsonobjects.JsonKeySpace; +import org.onap.music.datastore.jsonobjects.JsonSelect; +import org.onap.music.datastore.jsonobjects.JsonTable; +import org.onap.music.datastore.jsonobjects.JsonUpdate; import org.onap.music.exceptions.MusicLockingException; import org.onap.music.exceptions.MusicQueryException; import org.onap.music.exceptions.MusicServiceException; @@ -33,7 +43,6 @@ import org.onap.music.lockingservice.cassandra.LockType; import org.onap.music.lockingservice.cassandra.MusicLockState; import org.onap.music.main.ResultType; import org.onap.music.main.ReturnType; -import org.onap.music.datastore.*; import com.datastax.driver.core.ResultSet; @@ -51,7 +60,7 @@ public interface MusicCoreService { PreparedQueryObject queryObject, String lockId, Condition conditionInfo); public ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) - throws MusicServiceException; + throws MusicServiceException,MusicQueryException; public ResultSet get(PreparedQueryObject queryObject) throws MusicServiceException; @@ -134,5 +143,34 @@ public interface MusicCoreService { public Map<String, Object> validateLock(String lockName); public MusicLockState releaseLock(String lockId, boolean voluntaryRelease) throws MusicLockingException; + + + //Methods added for orm + + + public ResultType createTable(JsonTable jsonTableObject, String consistencyInfo) throws MusicServiceException,MusicQueryException; + + public ResultType dropTable(JsonTable jsonTableObject, String consistencyInfo) + throws MusicServiceException,MusicQueryException; + + public ResultType createKeyspace(JsonKeySpace jsonKeySpaceObject,String consistencyInfo) throws MusicServiceException,MusicQueryException; + + public ResultType dropKeyspace(JsonKeySpace jsonKeySpaceObject, String consistencyInfo) + throws MusicServiceException,MusicQueryException; + + public ResultType createIndex(JsonIndex jsonIndexObject, String consistencyInfo) throws MusicServiceException,MusicQueryException; + + public ResultSet select(JsonSelect jsonSelect, MultivaluedMap<String, String> rowParams) throws MusicServiceException, MusicQueryException; + + public ResultSet selectCritical(JsonInsert jsonInsertObj, MultivaluedMap<String, String> rowParams) + throws MusicLockingException, MusicQueryException, MusicServiceException; + + public ReturnType insertIntoTable(JsonInsert jsonInsert) throws MusicLockingException, MusicQueryException, MusicServiceException; + + public ReturnType updateTable(JsonUpdate jsonUpdateObj,MultivaluedMap<String, String> rowParams) + throws MusicLockingException, MusicQueryException, MusicServiceException; + + public ReturnType deleteFromTable(JsonDelete jsonDeleteObj,MultivaluedMap<String, String> rowParams) + throws MusicLockingException, MusicQueryException, MusicServiceException; } diff --git a/src/main/java/org/onap/music/service/impl/MusicCassaCore.java b/src/main/java/org/onap/music/service/impl/MusicCassaCore.java index cebdc667..04fcfd23 100644 --- a/src/main/java/org/onap/music/service/impl/MusicCassaCore.java +++ b/src/main/java/org/onap/music/service/impl/MusicCassaCore.java @@ -29,11 +29,20 @@ import java.io.StringWriter; import java.util.List; import java.util.Map; import java.util.StringTokenizer; -import java.util.concurrent.TimeUnit; +import javax.ws.rs.core.MultivaluedMap; + +import org.onap.music.datastore.Condition; import org.onap.music.datastore.MusicDataStore; import org.onap.music.datastore.MusicDataStoreHandle; import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.datastore.jsonobjects.JsonDelete; +import org.onap.music.datastore.jsonobjects.JsonIndex; +import org.onap.music.datastore.jsonobjects.JsonInsert; +import org.onap.music.datastore.jsonobjects.JsonKeySpace; +import org.onap.music.datastore.jsonobjects.JsonSelect; +import org.onap.music.datastore.jsonobjects.JsonTable; +import org.onap.music.datastore.jsonobjects.JsonUpdate; import org.onap.music.eelf.logging.EELFLoggerDelegate; import org.onap.music.eelf.logging.format.AppMessages; import org.onap.music.eelf.logging.format.ErrorSeverity; @@ -51,24 +60,29 @@ import org.onap.music.main.ResultType; import org.onap.music.main.ReturnType; import org.onap.music.service.MusicCoreService; -import com.att.eelf.configuration.EELFLogger; import com.datastax.driver.core.DataType; import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.Row; import com.datastax.driver.core.TableMetadata; -import org.onap.music.datastore.*; - public class MusicCassaCore implements MusicCoreService { - public static CassaLockStore mLockHandle = null;; + private static CassaLockStore mLockHandle = null; private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicCassaCore.class); - private static boolean unitTestRun=true; private static MusicCassaCore musicCassaCoreInstance = null; private MusicCassaCore() { + // not going to happen + } + + public static CassaLockStore getmLockHandle() { + return mLockHandle; + } + public static void setmLockHandle(CassaLockStore mLockHandle) { + MusicCassaCore.mLockHandle = mLockHandle; } + public static MusicCassaCore getInstance() { if(musicCassaCoreInstance == null) { @@ -77,6 +91,9 @@ public class MusicCassaCore implements MusicCoreService { return musicCassaCoreInstance; } + + + public static CassaLockStore getLockingServiceHandle() throws MusicLockingException { logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring lock store handle"); long start = System.currentTimeMillis(); @@ -95,7 +112,7 @@ public class MusicCassaCore implements MusicCoreService { } public String createLockReference(String fullyQualifiedKey) throws MusicLockingException { - return createLockReference(fullyQualifiedKey, LockType.WRITE); + return createLockReference(fullyQualifiedKey, LockType.WRITE); } public String createLockReference(String fullyQualifiedKey, LockType locktype) throws MusicLockingException { @@ -125,8 +142,8 @@ public class MusicCassaCore implements MusicCoreService { public ReturnType acquireLockWithLease(String fullyQualifiedKey, String lockReference, long leasePeriod) throws MusicLockingException, MusicQueryException, MusicServiceException { - evictExpiredLockHolder(fullyQualifiedKey,leasePeriod); - return acquireLock(fullyQualifiedKey, lockReference); + evictExpiredLockHolder(fullyQualifiedKey,leasePeriod); + return acquireLock(fullyQualifiedKey, lockReference); } private void evictExpiredLockHolder(String fullyQualifiedKey, long leasePeriod) @@ -167,7 +184,7 @@ public class MusicCassaCore implements MusicCoreService { if (!lockInfo.getIsLockOwner()) { return new ReturnType(ResultType.FAILURE, lockId + " is not a lock holder");//not top of the lock store q } - + //check to see if the value of the key has to be synced in case there was a forceful release String syncTable = keyspace+".unsyncedKeys_"+table; String query = "select * from "+syncTable+" where key='"+localFullyQualifiedKey+"';"; @@ -498,14 +515,22 @@ public class MusicCassaCore implements MusicCoreService { PreparedQueryObject queryObject, String lockId, Condition conditionInfo) { long start = System.currentTimeMillis(); try { + String keyLock = lockId.substring(lockId.lastIndexOf(".") + 1,lockId.lastIndexOf("$")); + if (lockId.contains(".") && !keyLock.equals(primaryKeyValue)) { + return new ReturnType(ResultType.FAILURE,"Lock value '" + keyLock + "' and key value '" + + primaryKeyValue + "' not match. Please check your values: " + + lockId + " ."); + } LockObject lockObject = getLockingServiceHandle().getLockInfo(keyspace, table, primaryKeyValue, lockId.substring(lockId.lastIndexOf("$") + 1)); - if (!lockObject.getIsLockOwner()) { + if ( lockObject == null ) { + return new ReturnType(ResultType.FAILURE, lockId + " does not exist."); + } else if (!lockObject.getIsLockOwner()) { return new ReturnType(ResultType.FAILURE, lockId + " is not the lock holder"); } else if (lockObject.getLocktype() != LockType.WRITE) { return new ReturnType(ResultType.FAILURE, - "Attempting to do write operation, but " + lockId + " is a write lock"); + "Attempting to do write operation, but " + lockId + " is a read lock"); } if (conditionInfo != null) { @@ -536,10 +561,10 @@ public class MusicCassaCore implements MusicCoreService { dsHandle.executePut(queryObject, MusicUtil.CRITICAL); long end = System.currentTimeMillis(); logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the critical put:" + (end - start) + " ms"); - }catch (MusicQueryException | MusicServiceException | MusicLockingException e) { + } catch (MusicQueryException | MusicServiceException | MusicLockingException e) { logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), e); return new ReturnType(ResultType.FAILURE, - "Exception thrown while doing the critical put\n" + "Exception thrown while doing the critical put: " + e.getMessage()); } return new ReturnType(ResultType.SUCCESS, "Update performed"); @@ -555,17 +580,17 @@ public class MusicCassaCore implements MusicCoreService { * * */ - public ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) throws MusicServiceException { + public ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) throws MusicServiceException,MusicQueryException { // this is mainly for some functions like keyspace creation etc which does not // really need the bells and whistles of Music locking. boolean result = false; - try { - result = MusicDataStoreHandle.getDSHandle().executePut(queryObject, consistency); - } catch (MusicQueryException | MusicServiceException ex) { - logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), AppMessages.UNKNOWNERROR, - ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR, ex); - throw new MusicServiceException(ex.getMessage()); - } +// try { + result = MusicDataStoreHandle.getDSHandle().executePut(queryObject, consistency); +// } catch (MusicQueryException | MusicServiceException ex) { + // logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), AppMessages.UNKNOWNERROR, + // ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR, ex); +// throw new MusicServiceException(ex.getMessage(),ex); +// } return result ? ResultType.SUCCESS : ResultType.FAILURE; } @@ -601,17 +626,33 @@ public class MusicCassaCore implements MusicCoreService { public ResultSet criticalGet(String keyspace, String table, String primaryKeyValue, PreparedQueryObject queryObject, String lockId) throws MusicServiceException { ResultSet results = null; - + String keyLock = lockId.substring(lockId.lastIndexOf(".") + 1,lockId.lastIndexOf("$")); try { + if (lockId.contains(".") && !keyLock.equals(primaryKeyValue)) { + throw new MusicLockingException("Lock value '" + keyLock + "' and key value '" + + primaryKeyValue + "' do not match. Please check your values: " + + lockId + " ."); + } LockObject lockObject = getLockingServiceHandle().getLockInfo(keyspace, table, primaryKeyValue, - lockId.substring(lockId.lastIndexOf("$") + 1)); - if (!lockObject.getIsLockOwner()) { + lockId.substring(lockId.lastIndexOf("$") + 1)); + if (null == lockObject) { + throw new MusicLockingException("No Lock Object. Please check if lock name or key is correct." + + lockId + " ."); + } + if ( !lockObject.getIsLockOwner()) { return null;// not top of the lock store q } results = MusicDataStoreHandle.getDSHandle().executeQuorumConsistencyGet(queryObject); - } catch (MusicQueryException | MusicServiceException | MusicLockingException e) { - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity + } catch ( MusicLockingException e ) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity + .WARN, ErrorTypes.MUSICSERVICEERROR); + throw new MusicServiceException( + "Cannot perform critical get for key: " + primaryKeyValue + " : " + e.getMessage()); + } catch (MusicQueryException | MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity .WARN, ErrorTypes.MUSICSERVICEERROR, e); + throw new MusicServiceException( + "Cannot perform critical get for key: " + primaryKeyValue + " : " + e.getMessage()); } return results; } @@ -780,5 +821,270 @@ public class MusicCassaCore implements MusicCoreService { //deprecated return null; } + + //Methods added for ORM changes + + public ResultType createKeyspace(JsonKeySpace jsonKeySpaceObject,String consistencyInfo) + throws MusicServiceException,MusicQueryException { + ResultType result = nonKeyRelatedPut(jsonKeySpaceObject.genCreateKeyspaceQuery(), consistencyInfo); + logger.info(EELFLoggerDelegate.applicationLogger, " Keyspace Creation Process completed successfully"); + + return result; + } + + public ResultType dropKeyspace(JsonKeySpace jsonKeySpaceObject, String consistencyInfo) + throws MusicServiceException,MusicQueryException { + ResultType result = nonKeyRelatedPut(jsonKeySpaceObject.genDropKeyspaceQuery(), + consistencyInfo); + logger.info(EELFLoggerDelegate.applicationLogger, " Keyspace deletion Process completed successfully"); + return result; + } + + public ResultType createTable(JsonTable jsonTableObject, String consistencyInfo) + throws MusicServiceException, MusicQueryException { + ResultType result = null; + try { + result = createTable(jsonTableObject.getKeyspaceName(), + jsonTableObject.getTableName(), jsonTableObject.genCreateTableQuery(), consistencyInfo); + + } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), AppMessages.UNKNOWNERROR, ErrorSeverity.WARN, + ErrorTypes.MUSICSERVICEERROR); + throw new MusicServiceException(ex.getMessage()); + } + logger.info(EELFLoggerDelegate.applicationLogger, " Table Creation Process completed successfully "); + return result; + } + + public ResultType dropTable(JsonTable jsonTableObject,String consistencyInfo) + throws MusicServiceException,MusicQueryException { + ResultType result = nonKeyRelatedPut(jsonTableObject.genDropTableQuery(), + consistencyInfo); + logger.info(EELFLoggerDelegate.applicationLogger, " Table deletion Process completed successfully "); + + return result; + } + + @Override + public ResultType createIndex(JsonIndex jsonIndexObject, String consistencyInfo) + throws MusicServiceException, MusicQueryException{ + ResultType result = nonKeyRelatedPut(jsonIndexObject.genCreateIndexQuery(), + consistencyInfo); + + logger.info(EELFLoggerDelegate.applicationLogger, " Index creation Process completed successfully "); + return result; + } + + /** + * This method performs DDL operation on cassandra. + * + * @param queryObject query object containing prepared query and values + * @return ResultSet + * @throws MusicServiceException + */ + public ResultSet select(JsonSelect jsonSelect, MultivaluedMap<String, String> rowParams) + throws MusicServiceException, MusicQueryException { + ResultSet results = null; + try { + results = get(jsonSelect.genSelectQuery(rowParams)); + } catch (MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); + throw new MusicServiceException(e.getMessage()); + } + return results; + } + + /** + * Select Critical + */ + public ResultSet selectCritical(JsonInsert jsonInsertObj, MultivaluedMap<String, String> rowParams) + throws MusicLockingException, MusicQueryException, MusicServiceException { + + ResultSet results = null; + String consistency = ""; + if(null != jsonInsertObj && null != jsonInsertObj.getConsistencyInfo()) { + consistency = jsonInsertObj.getConsistencyInfo().get("type"); + } + + String lockId = jsonInsertObj.getConsistencyInfo().get("lockId"); + + PreparedQueryObject queryObject = jsonInsertObj.genSelectCriticalPreparedQueryObj(rowParams); + + if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + results = criticalGet(jsonInsertObj.getKeyspaceName(), jsonInsertObj.getTableName(), + jsonInsertObj.getPrimaryKeyVal(), queryObject,lockId); + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + results = atomicGet(jsonInsertObj.getKeyspaceName(), jsonInsertObj.getTableName(), + jsonInsertObj.getPrimaryKeyVal(), queryObject); + } + + return results; + } + + /** + * this is insert row into Table + */ + public ReturnType insertIntoTable(JsonInsert jsonInsertObj) + throws MusicLockingException, MusicQueryException, MusicServiceException { + + String consistency = ""; + if(null != jsonInsertObj && null != jsonInsertObj.getConsistencyInfo()) { + consistency = jsonInsertObj.getConsistencyInfo().get("type"); + } + + ReturnType result = null; + + try { + PreparedQueryObject queryObj = null; + queryObj = jsonInsertObj.genInsertPreparedQueryObj(); + + if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) { + result = eventualPut(jsonInsertObj.genInsertPreparedQueryObj()); + } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + String lockId = jsonInsertObj.getConsistencyInfo().get("lockId"); + if(lockId == null) { + logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" + + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); + return new ReturnType(ResultType.FAILURE, "LockId cannot be null. Create lock " + + "and acquire lock or use ATOMIC instead of CRITICAL"); + } + result = criticalPut(jsonInsertObj.getKeyspaceName(), + jsonInsertObj.getTableName(), jsonInsertObj.getPrimaryKeyVal(), jsonInsertObj.genInsertPreparedQueryObj(), lockId,null); + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + result = atomicPut(jsonInsertObj.getKeyspaceName(), jsonInsertObj.getTableName(), + jsonInsertObj.getPrimaryKeyVal(), jsonInsertObj.genInsertPreparedQueryObj(), null); + } + } catch (Exception ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity + .WARN, ErrorTypes.MUSICSERVICEERROR, ex); + return new ReturnType(ResultType.FAILURE, ex.getMessage()); + } + + return result; + } + + /** + * This is insert row into Table + */ + public ReturnType updateTable(JsonUpdate jsonUpdateObj, MultivaluedMap<String, String> rowParams) + throws MusicLockingException, MusicQueryException, MusicServiceException { + + ReturnType result = null; + String consistency = ""; + if(null != jsonUpdateObj && null != jsonUpdateObj.getConsistencyInfo()) { + consistency = jsonUpdateObj.getConsistencyInfo().get("type"); + } + PreparedQueryObject queryObject = jsonUpdateObj.genUpdatePreparedQueryObj(rowParams); + + Condition conditionInfo; + if (jsonUpdateObj.getConditions() == null) { + conditionInfo = null; + } else { + // to avoid parsing repeatedly, just send the select query to obtain row + PreparedQueryObject selectQuery = new PreparedQueryObject(); + selectQuery.appendQueryString("SELECT * FROM " + jsonUpdateObj.getKeyspaceName() + "." + jsonUpdateObj.getTableName() + " WHERE " + + jsonUpdateObj.getRowIdString() + ";"); + selectQuery.addValue(jsonUpdateObj.getPrimarKeyValue()); + conditionInfo = new Condition(jsonUpdateObj.getConditions(), selectQuery); + } + + + if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) { + result = eventualPut(queryObject); + } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + String lockId = jsonUpdateObj.getConsistencyInfo().get("lockId"); + if(lockId == null) { + logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" + + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); + + return new ReturnType(ResultType.FAILURE, "LockId cannot be null. Create lock " + + "and acquire lock or use ATOMIC instead of CRITICAL"); + } + result = criticalPut(jsonUpdateObj.getKeyspaceName(), jsonUpdateObj.getTableName(), jsonUpdateObj.getPrimarKeyValue(), + queryObject, lockId, conditionInfo); + } else if (consistency.equalsIgnoreCase("atomic_delete_lock")) { + // this function is mainly for the benchmarks + try { + result = atomicPutWithDeleteLock(jsonUpdateObj.getKeyspaceName(), jsonUpdateObj.getTableName(), + jsonUpdateObj.getPrimarKeyValue(), queryObject, conditionInfo); + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, + ErrorTypes.GENERALSERVICEERROR, e); + throw new MusicLockingException(AppMessages.UNKNOWNERROR.toString()); + + } + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + try { + result = atomicPut(jsonUpdateObj.getKeyspaceName(), jsonUpdateObj.getTableName(), jsonUpdateObj.getPrimarKeyValue(), + queryObject, conditionInfo); + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR, e); + throw new MusicLockingException(AppMessages.UNKNOWNERROR.toString()); + } + } else if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) { + try { + result = eventualPut_nb(queryObject, jsonUpdateObj.getKeyspaceName(), + jsonUpdateObj.getTableName(), jsonUpdateObj.getPrimarKeyValue()); + }catch (Exception e) { + return new ReturnType(ResultType.FAILURE, e.getMessage()); + } + + } + + return result; + } + + /** + * This method is for Delete From Table + */ + public ReturnType deleteFromTable(JsonDelete jsonDeleteObj, MultivaluedMap<String, String> rowParams) + throws MusicLockingException, MusicQueryException, MusicServiceException { + + ReturnType result = null; + String consistency = ""; + if(null != jsonDeleteObj && null != jsonDeleteObj.getConsistencyInfo()) { + consistency = jsonDeleteObj.getConsistencyInfo().get("type"); + } + PreparedQueryObject queryObject = jsonDeleteObj.genDeletePreparedQueryObj(rowParams); + + // get the conditional, if any + Condition conditionInfo; + if (jsonDeleteObj.getConditions() == null) { + conditionInfo = null; + } else { + // to avoid parsing repeatedly, just send the select query to obtain row + PreparedQueryObject selectQuery = new PreparedQueryObject(); + selectQuery.appendQueryString("SELECT * FROM " + jsonDeleteObj.getKeyspaceName() + "." + jsonDeleteObj.getTableName() + " WHERE " + + jsonDeleteObj.getRowIdString() + ";"); + selectQuery.addValue(jsonDeleteObj.getPrimarKeyValue()); + conditionInfo = new Condition(jsonDeleteObj.getConditions(), selectQuery); + } + + if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) + result = eventualPut(queryObject); + else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + String lockId = jsonDeleteObj.getConsistencyInfo().get("lockId"); + if(lockId == null) { + logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" + + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); + + return new ReturnType(ResultType.FAILURE, "LockId cannot be null. Create lock " + + "and acquire lock or use ATOMIC instead of CRITICAL"); + } + result = criticalPut(jsonDeleteObj.getKeyspaceName(), + jsonDeleteObj.getTableName(), jsonDeleteObj.getPrimarKeyValue(), + queryObject, lockId, conditionInfo); + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + result = atomicPut(jsonDeleteObj.getKeyspaceName(), + jsonDeleteObj.getTableName(), jsonDeleteObj.getPrimarKeyValue(), + queryObject, conditionInfo); + } else if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) { + result = eventualPut_nb(queryObject, jsonDeleteObj.getKeyspaceName(), + jsonDeleteObj.getTableName(), jsonDeleteObj.getPrimarKeyValue()); + } + + return result; + } + } diff --git a/src/main/resources/cache.ccf b/src/main/resources/cache.ccf deleted file mode 100644 index e152ee8b..00000000 --- a/src/main/resources/cache.ccf +++ /dev/null @@ -1,62 +0,0 @@ -# DEFAULT CACHE REGION -jcs.default=DC -jcs.default.cacheattributes=org.apache.commons.jcs.engine.CompositeCacheAttributes -jcs.default.cacheattributes.MaxObjects=1000 -jcs.default.cacheattributes.MemoryCacheName=org.apache.commons.jcs.engine.memory.lru.LRUMemoryCache -jcs.default.elementattributes=org.apache.commons.jcs.engine.ElementAttributes -jcs.default.elementattributes.IsEternal=true -jcs.default.elementattributes.IsSpool=true - -# PRE-DEFINED CACHE REGIONS -jcs.region.musicCache= -jcs.region.musicCache.cacheattributes=org.apache.commons.jcs.engine.CompositeCacheAttributes -jcs.region.musicCache.cacheattributes.MaxObjects=1000 -jcs.region.musicCache.cacheattributes.MemoryCacheName=org.apache.commons.jcs.engine.memory.lru.LRUMemoryCache -jcs.region.musicCache.cacheattributes.UseMemoryShrinker=false -jcs.region.musicCache.cacheattributes.MaxMemoryIdleTime=3600 -jcs.region.musicCache.cacheattributes.ShrinkerInterval=60 -jcs.region.musicCache.cacheattributes.MaxSpoolPerRun=500 -jcs.region.musicCache.elementattributes=org.apache.commons.jcs.engine.ElementAttributes -jcs.region.musicCache.elementattributes.IsEternal=false - - -# PRE-DEFINED CACHE REGIONS -jcs.region.aafCache= -jcs.region.aafCache.cacheattributes=org.apache.commons.jcs.engine.CompositeCacheAttributes -jcs.region.aafCache.cacheattributes.MaxObjects=1000 -jcs.region.aafCache.cacheattributes.MemoryCacheName=org.apache.commons.jcs.engine.memory.lru.LRUMemoryCache -jcs.region.aafCache.cacheattributes.UseMemoryShrinker=false -jcs.region.aafCache.cacheattributes.MaxMemoryIdleTime=3600 -jcs.region.aafCache.cacheattributes.ShrinkerInterval=60 -jcs.region.aafCache.cacheattributes.MaxSpoolPerRun=500 -jcs.region.aafCache.elementattributes=org.apache.commons.jcs.engine.ElementAttributes -jcs.region.aafCache.elementattributes.IsEternal=false - -# PRE-DEFINED CACHE REGIONS -jcs.region.appNameCache= -jcs.region.appNameCache.cacheattributes=org.apache.commons.jcs.engine.CompositeCacheAttributes -jcs.region.appNameCache.cacheattributes.MaxObjects=1000 -jcs.region.appNameCache.cacheattributes.MemoryCacheName=org.apache.commons.jcs.engine.memory.lru.LRUMemoryCache -jcs.region.appNameCache.cacheattributes.UseMemoryShrinker=false -jcs.region.appNameCache.cacheattributes.MaxMemoryIdleTime=3600 -jcs.region.appNameCache.cacheattributes.ShrinkerInterval=60 -jcs.region.appNameCache.cacheattributes.MaxSpoolPerRun=500 -jcs.region.appNameCache.elementattributes=org.apache.commons.jcs.engine.ElementAttributes -jcs.region.appNameCache.elementattributes.IsEternal=false - -jcs.default=DC -jcs.default.cacheattributes=org.apache.commons.jcs.engine.CompositeCacheAttributes -jcs.default.cacheattributes.MaxObjects=1000 -jcs.default.cacheattributes.MemoryCacheName=org.apache.commons.jcs.engine.memory.lru.LRUMemoryCache -jcs.default.elementattributes=org.apache.commons.jcs.engine.ElementAttributes -jcs.default.elementattributes.IsEternal=true -jcs.default.elementattributes.IsSpool=true - -jcs.region.eternalCache=DC -jcs.region.eternalCache.cacheattributes=org.apache.commons.jcs.engine.CompositeCacheAttributes -jcs.region.eternalCache.cacheattributes.MaxObjects=1000 -jcs.region.eternalCache.cacheattributes.MemoryCacheName=org.apache.commons.jcs.engine.memory.lru.LRUMemoryCache -jcs.region.eternalCache.elementattributes=org.apache.commons.jcs.engine.ElementAttributes -jcs.region.eternalCache.elementattributes.IsEternal=true -jcs.region.eternalCache.elementattributes.IsSpool=true - diff --git a/src/main/resources/key.properties b/src/main/resources/key.properties new file mode 100644 index 00000000..5ce266fa --- /dev/null +++ b/src/main/resources/key.properties @@ -0,0 +1 @@ +cipher.enc.key= nothing to see here diff --git a/src/test/java/org/onap/music/datastore/PreparedQueryObjectTest.java b/src/test/java/org/onap/music/datastore/PreparedQueryObjectTest.java new file mode 100644 index 00000000..7ab7d148 --- /dev/null +++ b/src/test/java/org/onap/music/datastore/PreparedQueryObjectTest.java @@ -0,0 +1,101 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 IBM. + * =================================================================== + * 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 + * e + * 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============================================= + * ==================================================================== + */ + +package org.onap.music.datastore; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +public class PreparedQueryObjectTest { + + private PreparedQueryObject preparedQueryObject; + + @Before + public void setUp() + { + preparedQueryObject = new PreparedQueryObject(); + } + + @Test + public void testKeyspaceName() + { + preparedQueryObject.setKeyspaceName("keyspaceName"); + assertEquals("keyspaceName", preparedQueryObject.getKeyspaceName()); + } + + @Test + public void testConsistency() + { + preparedQueryObject.setConsistency("consistency"); + assertEquals("consistency", preparedQueryObject.getConsistency()); + } + + @Test + public void testTableName() + { + preparedQueryObject.setTableName("tableName"); + assertEquals("tableName", preparedQueryObject.getTableName()); + } + + @Test + public void testoperation() + { + preparedQueryObject.setOperation("operation"); + assertEquals("operation", preparedQueryObject.getOperation()); + } + + @Test + public void testprimaryKeyValue() + { + preparedQueryObject.setPrimaryKeyValue("primaryKeyValue"); + assertEquals("primaryKeyValue", preparedQueryObject.getPrimaryKeyValue()); + } + + @Test + public void testAddValue() { + preparedQueryObject.addValue("one"); + assertEquals("one", preparedQueryObject.getValues().get(0)); + } + + @Test + public void testAddValues() { + preparedQueryObject.addValues("one", "two", "three"); + assertEquals(3, preparedQueryObject.getValues().size()); + assertEquals("two", preparedQueryObject.getValues().get(1)); + } + + @Test + public void testConstructorQuery() { + preparedQueryObject = new PreparedQueryObject("some query string"); + assertEquals("some query string", preparedQueryObject.getQuery()); + } + + @Test + public void testConstructorQueryValues() { + preparedQueryObject = new PreparedQueryObject("another query string", "a", "b", "c"); + assertEquals("another query string", preparedQueryObject.getQuery()); + assertEquals(3, preparedQueryObject.getValues().size()); + assertEquals("b", preparedQueryObject.getValues().get(1)); + } +} diff --git a/src/test/java/org/onap/music/unittests/JsonResponseTest.java b/src/test/java/org/onap/music/unittests/JsonResponseTest.java index 20ac1562..6af8c0d9 100644 --- a/src/test/java/org/onap/music/unittests/JsonResponseTest.java +++ b/src/test/java/org/onap/music/unittests/JsonResponseTest.java @@ -113,6 +113,28 @@ public class JsonResponseTest { } @Test + public void testLockLease() { + result = new JsonResponse(ResultType.SUCCESS); + result.setLockLease("lockLease"); + assertEquals("lockLease", result.getLockLease()); + } + + @Test + public void testMusicBuild() { + result = new JsonResponse(ResultType.SUCCESS); + result.setMusicBuild("Build"); + assertEquals("Build", result.getMusicBuild()); + } + + @Test + public void testLockHolder() { + result = new JsonResponse(ResultType.SUCCESS); + List<String> lockHolders = new ArrayList<>(); + result.setLockHolder(lockHolders); + assertEquals(lockHolders, result.getLockHolder()); + } + + @Test public void testLockStatus() { result = new JsonResponse(ResultType.SUCCESS); LockStatus status = LockStatus.LOCKED; diff --git a/src/test/java/org/onap/music/unittests/MusicUtilTest.java b/src/test/java/org/onap/music/unittests/MusicUtilTest.java index 930959ba..c4c8ba2e 100644 --- a/src/test/java/org/onap/music/unittests/MusicUtilTest.java +++ b/src/test/java/org/onap/music/unittests/MusicUtilTest.java @@ -25,20 +25,28 @@ package org.onap.music.unittests; import static org.junit.Assert.*; import java.math.BigInteger; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; + import org.junit.Test; import org.onap.music.datastore.PreparedQueryObject; import org.onap.music.main.MusicUtil; import org.onap.music.main.PropertiesLoader; -import org.springframework.test.context.TestPropertySource; +import org.onap.music.service.MusicCoreService; + +import com.datastax.driver.core.ConsistencyLevel; import com.datastax.driver.core.DataType; public class MusicUtilTest { + private static final String XLATESTVERSION = "X-latestVersion"; + private static final String XMINORVERSION = "X-minorVersion"; + private static final String XPATCHVERSION = "X-patchVersion"; + @Test public void testGetCassName() { MusicUtil.setCassName("Cassandra"); @@ -52,14 +60,28 @@ public class MusicUtilTest { } @Test - public void testGetAafEndpointUrl() { - MusicUtil.setAafEndpointUrl("url"); - assertEquals(MusicUtil.getAafEndpointUrl(),"url"); + public void testMusicAafNs() { + MusicUtil.setMusicAafNs("ns"); + assertTrue("ns".equals(MusicUtil.getMusicAafNs())); + } + + @Test + public void testMusicCoreService() { + MusicUtil.setLockUsing(MusicUtil.CASSANDRA); + MusicCoreService mc = null; + mc = MusicUtil.getMusicCoreService(); + assertTrue(mc != null); + MusicUtil.setLockUsing("nothing"); + mc = null; + mc = MusicUtil.getMusicCoreService(); + assertTrue(mc != null); + } @Test - public void testGetPropkeys() { - assertEquals(MusicUtil.getPropkeys()[2],"debug"); + public void testCipherEncKey() { + MusicUtil.setCipherEncKey("cipherEncKey"); + assertTrue("cipherEncKey".equals(MusicUtil.getCipherEncKey())); } @Test @@ -86,28 +108,53 @@ public class MusicUtilTest { assertEquals(MusicUtil.getVersion(),"1.0.0"); } - /*@Test - public void testGetMyZkHost() { - MusicUtil.setMyZkHost("10.0.0.2"); - assertEquals(MusicUtil.getMyZkHost(),"10.0.0.2"); - }*/ + @Test + public void testBuildVersionA() { + assertEquals(MusicUtil.buildVersion("1","2","3"),"1.2.3"); + } + + @Test + public void testBuildVersionB() { + assertEquals(MusicUtil.buildVersion("1",null,"3"),"1"); + } + + @Test + public void testBuildVersionC() { + assertEquals(MusicUtil.buildVersion("1","2",null),"1.2"); + } + @Test - public void testGetMyCassaHost() { - MusicUtil.setMyCassaHost("10.0.0.2"); - assertEquals(MusicUtil.getMyCassaHost(),"10.0.0.2"); + public void testBuileVersionResponse() { + assertTrue(MusicUtil.buildVersionResponse("1","2","3").getClass().getSimpleName().equals("Builder")); + assertTrue(MusicUtil.buildVersionResponse("1",null,"3").getClass().getSimpleName().equals("Builder")); + assertTrue(MusicUtil.buildVersionResponse("1","2",null).getClass().getSimpleName().equals("Builder")); + assertTrue(MusicUtil.buildVersionResponse(null,null,null).getClass().getSimpleName().equals("Builder")); + } + + @Test + public void testGetConsistency() { + assertTrue(ConsistencyLevel.ONE.equals(MusicUtil.getConsistencyLevel("one"))); + } + + @Test + public void testRetryCount() { + MusicUtil.setRetryCount(1); + assertEquals(MusicUtil.getRetryCount(),1); } @Test - public void testGetDefaultMusicIp() { - MusicUtil.setDefaultMusicIp("10.0.0.2"); - assertEquals(MusicUtil.getDefaultMusicIp(),"10.0.0.2"); + public void testIsCadi() { + MusicUtil.setIsCadi(true); + assertEquals(MusicUtil.getIsCadi(),true); } -// @Test -// public void testGetTestType() { -// fail("Not yet implemented"); // TODO -// } + + @Test + public void testGetMyCassaHost() { + MusicUtil.setMyCassaHost("10.0.0.2"); + assertEquals(MusicUtil.getMyCassaHost(),"10.0.0.2"); + } @Test public void testIsValidQueryObject() { @@ -130,6 +177,16 @@ public class MusicUtilTest { } + + + + @Test(expected = IllegalStateException.class) + public void testMusicUtil() { + System.out.println("MusicUtil Constructor Test"); + MusicUtil mu = new MusicUtil(); + System.out.println(mu.toString()); + } + @Test public void testConvertToCQLDataType() throws Exception { Map<String,Object> myMap = new HashMap<String,Object>(); @@ -150,9 +207,20 @@ public class MusicUtilTest { assertEquals(MusicUtil.convertToActualDataType(DataType.cfloat(),"123.01"),Float.parseFloat("123.01")); assertEquals(MusicUtil.convertToActualDataType(DataType.cdouble(),"123.02"),Double.parseDouble("123.02")); assertEquals(MusicUtil.convertToActualDataType(DataType.cboolean(),"true"),Boolean.parseBoolean("true")); + List<String> myList = new ArrayList<String>(); + List<String> newList = myList; + myList.add("TOM"); + assertEquals(MusicUtil.convertToActualDataType(DataType.list(DataType.varchar()),myList),newList); Map<String,Object> myMap = new HashMap<String,Object>(); myMap.put("name","tom"); - assertEquals(MusicUtil.convertToActualDataType(DataType.map(DataType.varchar(),DataType.varchar()),myMap),myMap); + Map<String,Object> newMap = myMap; + assertEquals(MusicUtil.convertToActualDataType(DataType.map(DataType.varchar(),DataType.varchar()),myMap),newMap); + } + + @Test + public void testConvertToActualDataTypeByte() throws Exception { + byte[] testByte = "TOM".getBytes(); + assertEquals(MusicUtil.convertToActualDataType(DataType.blob(),testByte),ByteBuffer.wrap(testByte)); } @@ -189,42 +257,6 @@ public class MusicUtilTest { } @Test - public void testAAFAdminUrl() { - MusicUtil.setAafAdminUrl("aafAdminURL.com"); - assertEquals("aafAdminURL.com", MusicUtil.getAafAdminUrl()); - } - - @Test - public void testAAFEndpointUrl() { - MusicUtil.setAafEndpointUrl("aafEndpointURL.com"); - assertEquals("aafEndpointURL.com", MusicUtil.getAafEndpointUrl()); - } - - @Test - public void testNamespace() { - MusicUtil.setMusicNamespace("musicNamespace"); - assertEquals("musicNamespace", MusicUtil.getMusicNamespace()); - } - - @Test - public void testAAFRole() { - MusicUtil.setAdminAafRole("aafRole"); - assertEquals("aafRole", MusicUtil.getAdminAafRole()); - } - - @Test - public void testAdminId() { - MusicUtil.setAdminId("adminId"); - assertEquals("adminId", MusicUtil.getAdminId()); - } - - @Test - public void testAdminPass() { - MusicUtil.setAdminPass("pass"); - assertEquals("pass", MusicUtil.getAdminPass()); - } - - @Test public void testCassaPort() { MusicUtil.setCassandraPort(1234); assertEquals(1234, MusicUtil.getCassandraPort()); @@ -237,18 +269,6 @@ public class MusicUtilTest { } @Test - public void testNotifyInterval() { - MusicUtil.setNotifyInterval(123); - assertEquals(123, MusicUtil.getNotifyInterval()); - } - - @Test - public void testNotifyTimeout() { - MusicUtil.setNotifyTimeOut(789); - assertEquals(789, MusicUtil.getNotifyTimeout()); - } - - @Test public void testTransId() { MusicUtil.setTransIdPrefix("prefix"); assertEquals("prefix-", MusicUtil.getTransIdPrefix()); @@ -280,23 +300,29 @@ public class MusicUtilTest { } @Test - public void testconvIdReq() { - MusicUtil.setConversationIdRequired("conversationIdRequired"); - assertEquals("conversationIdRequired", MusicUtil.getConversationIdRequired()); + public void testConvIdReq() { + MusicUtil.setConversationIdRequired(true); + assertEquals(true, MusicUtil.getConversationIdRequired()); } @Test public void testClientIdRequired() { - MusicUtil.setClientIdRequired("conversationIdRequired"); - assertEquals("conversationIdRequired", MusicUtil.getClientIdRequired()); + MusicUtil.setClientIdRequired(true); + assertEquals(true, MusicUtil.getClientIdRequired()); } @Test public void testMessageIdRequired() { - MusicUtil.setMessageIdRequired("msgIdRequired"); - assertEquals("msgIdRequired", MusicUtil.getMessageIdRequired()); + MusicUtil.setMessageIdRequired(true); + assertEquals(true, MusicUtil.getMessageIdRequired()); } - + + @Test + public void testTransIdRequired() { + MusicUtil.setTransIdRequired(true); + assertEquals(true,MusicUtil.getTransIdRequired()); + } + @Test public void testLoadProperties() { PropertiesLoader pl = new PropertiesLoader(); diff --git a/src/test/java/org/onap/music/unittests/TestRestMusicQAPI.java b/src/test/java/org/onap/music/unittests/TestRestMusicQAPI.java index a9e6e4b6..385a4698 100644 --- a/src/test/java/org/onap/music/unittests/TestRestMusicQAPI.java +++ b/src/test/java/org/onap/music/unittests/TestRestMusicQAPI.java @@ -132,7 +132,7 @@ public class TestRestMusicQAPI { try { ReflectionTestUtils.setField(MusicDataStoreHandle.class, "mDstoreHandle", CassandraCQL.connectToEmbeddedCassandra()); - MusicCore.mLockHandle = new CassaLockStore(MusicDataStoreHandle.getDSHandle()); + MusicCore.setmLockHandle(new CassaLockStore(MusicDataStoreHandle.getDSHandle())); // System.out.println("before class keysp"); //resp=data.createKeySpace(majorV,minorV,patchV,aid,appName,userId,password,kspObject,keyspaceName); diff --git a/src/test/java/org/onap/music/unittests/TestsUsingCassandra.java b/src/test/java/org/onap/music/unittests/TestsUsingCassandra.java index e2c65447..cc7c5146 100644 --- a/src/test/java/org/onap/music/unittests/TestsUsingCassandra.java +++ b/src/test/java/org/onap/music/unittests/TestsUsingCassandra.java @@ -66,7 +66,7 @@ public class TestsUsingCassandra { public static void beforeClass() throws Exception { ReflectionTestUtils.setField(MusicDataStoreHandle.class, "mDstoreHandle", CassandraCQL.connectToEmbeddedCassandra()); - MusicCore.mLockHandle = new CassaLockStore(MusicDataStoreHandle.getDSHandle()); + MusicCore.setmLockHandle(new CassaLockStore(MusicDataStoreHandle.getDSHandle())); createAdminTable(); } diff --git a/src/test/java/org/onap/music/unittests/TstRestMusicDataAPI.java b/src/test/java/org/onap/music/unittests/TstRestMusicDataAPI.java index 3bf33179..407d0323 100644 --- a/src/test/java/org/onap/music/unittests/TstRestMusicDataAPI.java +++ b/src/test/java/org/onap/music/unittests/TstRestMusicDataAPI.java @@ -194,6 +194,16 @@ public class TstRestMusicDataAPI { System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); assertEquals(200, response.getStatus()); } + + @Test + public void test3_createTableNoBody() throws Exception { + System.out.println("Testing create table w/o body"); + + Response response = data.createTable("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, + authorization, null, keyspaceName, tableName); + System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); + assertEquals(400, response.getStatus()); + } @Test public void test3_createTableNoName() throws Exception { @@ -312,7 +322,7 @@ public class TstRestMusicDataAPI { assertEquals(400, response2.getStatus()); Map<String, String> respMap = (Map<String, String>) response2.getEntity(); assertEquals(ResultType.FAILURE, respMap.get("status")); - assertEquals("Table " + keyspaceName + "." + tableNameDup + " already exists", respMap.get("error")); + assertEquals("AlreadyExistsException: Table " + keyspaceName + "." + tableNameDup + " already exists", respMap.get("error")); } @@ -539,8 +549,37 @@ public class TstRestMusicDataAPI { assertEquals(200, response.getStatus()); } + + @Test + public void test4_insertIntoTableNoBody() throws Exception { + System.out.println("Testing insert into table w/o body"); + createTable(); + Response response = data.insertIntoTable("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, + authorization, null, keyspaceName, tableName); + System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); + + assertEquals(400, response.getStatus()); + } @Test + public void test4_insertIntoTableNoaValues() throws Exception { + System.out.println("Testing insert into table"); + createTable(); + JsonInsert jsonInsert = new JsonInsert(); + Map<String, String> consistencyInfo = new HashMap<>(); + consistencyInfo.put("type", "eventual"); + jsonInsert.setConsistencyInfo(consistencyInfo); + jsonInsert.setKeyspaceName(keyspaceName); + jsonInsert.setTableName(tableName); + + Response response = data.insertIntoTable("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, + authorization, jsonInsert, keyspaceName, tableName); + System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); + + assertEquals(400, response.getStatus()); + } + + @Test public void test4_insertIntoTableNoValues() throws Exception { System.out.println("Testing insert into table"); createTable(); @@ -827,6 +866,23 @@ public class TstRestMusicDataAPI { @Test + public void test6_critical_select() throws Exception { + System.out.println("Testing critical select w/o body"); + createAndInsertIntoTable(); + MultivaluedMap<String, String> row = new MultivaluedMapImpl(); + row.add("emp_name", "testname"); + Mockito.when(info.getQueryParameters()).thenReturn(row); + Response response = data.selectCritical("1", "1", "1","abc66ccc-d857-4e90-b1e5-df98a3d40ce6", + appName, authorization, null, keyspaceName, tableName,info); + HashMap<String,HashMap<String,Object>> map = (HashMap<String, HashMap<String, Object>>) response.getEntity(); + HashMap<String, Object> result = map.get("result"); + System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); + + assertEquals(400, response.getStatus()); + } + + // Added during merge? + @Test public void test6_critical_selectCritical_nolockid() throws Exception { System.out.println("Testing critical select critical w/o lockid"); createAndInsertIntoTable(); @@ -872,8 +928,8 @@ public class TstRestMusicDataAPI { consistencyInfo.put("type", "atomic"); jsonSelect.setConsistencyInfo(consistencyInfo); Mockito.when(info.getQueryParameters()).thenReturn(row); - Response response = data.select("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, authorization, - keyspaceName, tableName, info); + Response response = data.selectWithCritical("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, authorization, + null,keyspaceName, tableName, info); HashMap<String, HashMap<String, Object>> map = (HashMap<String, HashMap<String, Object>>) response.getEntity(); HashMap<String, Object> result = map.get("result"); System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); @@ -891,8 +947,8 @@ public class TstRestMusicDataAPI { Map<String, String> consistencyInfo = new HashMap<>(); consistencyInfo.put("type", "atomic"); jsonSelect.setConsistencyInfo(consistencyInfo); - Response response = data.select("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", - appName, wrongAuthorization, keyspaceName, null, info); + Response response = data.selectWithCritical("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", + appName, wrongAuthorization,null, keyspaceName, null, info); System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); assertEquals(400, response.getStatus()); diff --git a/src/test/java/org/onap/music/unittests/TstRestMusicLockAPI.java b/src/test/java/org/onap/music/unittests/TstRestMusicLockAPI.java index 1e9ed79a..ec7659a6 100644 --- a/src/test/java/org/onap/music/unittests/TstRestMusicLockAPI.java +++ b/src/test/java/org/onap/music/unittests/TstRestMusicLockAPI.java @@ -371,8 +371,7 @@ public class TstRestMusicLockAPI { System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); assertEquals(200, response.getStatus()); Map<String, Object> respMap = (Map<String, Object>) response.getEntity(); - //TODO: this should be lockRef - assertEquals("1", ((Map<String, String>) respMap.get("lock")).get("lock-holder")); + assertEquals(lockRef, ((Map<String, List>) respMap.get("lock")).get("lock-holder").get(0)); } @Test diff --git a/src/test/java/org/onap/music/unittests/jsonobjects/MusicDigestTest.java b/src/test/java/org/onap/music/unittests/authentication/AuthorizationErrorTest.java index cf8a9c63..b432072a 100644 --- a/src/test/java/org/onap/music/unittests/jsonobjects/MusicDigestTest.java +++ b/src/test/java/org/onap/music/unittests/authentication/AuthorizationErrorTest.java @@ -20,41 +20,32 @@ * ==================================================================== */ -package org.onap.music.unittests.jsonobjects; +package org.onap.music.unittests.authentication; import static org.junit.Assert.assertEquals; import org.junit.Before; import org.junit.Test; -import org.onap.music.main.MusicDigest; +import org.onap.music.authentication.AuthorizationError; -public class MusicDigestTest { - - private MusicDigest musicDigest; +public class AuthorizationErrorTest { + + private AuthorizationError authorizationError; @Before - public void setUp() - { - musicDigest= new MusicDigest("evPutStatus", "vectorTs"); - } - - @Test - public void testGetSetEvPutStatus() - { - musicDigest.setEvPutStatus("evPutStatus"); - assertEquals("evPutStatus", musicDigest.getEvPutStatus()); + public void setUp() { + authorizationError = new AuthorizationError(); } - + @Test - public void testGetSetVectorTs() - { - musicDigest.setVectorTs("vectorTs"); - assertEquals("vectorTs", musicDigest.getVectorTs()); + public void testResponseCode() { + authorizationError.setResponseCode(400); + assertEquals(400, authorizationError.getResponseCode()); } - + @Test - public void testToString() - { - assertEquals("vectorTs|evPutStatus", musicDigest.toString()); + public void testResponseMessage() { + authorizationError.setResponseMessage("ResponseMessage"); + assertEquals("ResponseMessage", authorizationError.getResponseMessage()); } } diff --git a/src/test/java/org/onap/music/unittests/jsonobjects/AAFResponseTest.java b/src/test/java/org/onap/music/unittests/jsonobjects/AAFResponseTest.java deleted file mode 100644 index 354668c7..00000000 --- a/src/test/java/org/onap/music/unittests/jsonobjects/AAFResponseTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * ============LICENSE_START========================================== - * org.onap.music - * =================================================================== - * Copyright (c) 2017 AT&T Intellectual Property - * =================================================================== - * 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============================================= - * ==================================================================== - */ - -package org.onap.music.unittests.jsonobjects; - -import static org.junit.Assert.*; -import java.util.ArrayList; -import org.junit.Test; -import org.onap.music.datastore.jsonobjects.AAFResponse; -import org.onap.music.datastore.jsonobjects.NameSpace; - -public class AAFResponseTest { - - @Test - public void testGetNs() { - NameSpace ns = new NameSpace(); - AAFResponse ar = new AAFResponse(); - ArrayList<NameSpace> nsArray = new ArrayList<>(); - ns.setName("tom"); - ArrayList<String> admin = new ArrayList<>(); - admin.add("admin1"); - ns.setAdmin(admin); - nsArray.add(ns); - ar.setNs(nsArray); - assertEquals("tom",ar.getNs().get(0).getName()); - assertEquals("admin1",ar.getNs().get(0).getAdmin().get(0)); - - } - -// @Test -// public void testSetNs() { -// fail("Not yet implemented"); -// } - -} diff --git a/src/test/java/org/onap/music/unittests/jsonobjects/JsonInsertTest.java b/src/test/java/org/onap/music/unittests/jsonobjects/JsonInsertTest.java index 535cdd84..4992af7b 100644 --- a/src/test/java/org/onap/music/unittests/jsonobjects/JsonInsertTest.java +++ b/src/test/java/org/onap/music/unittests/jsonobjects/JsonInsertTest.java @@ -4,6 +4,8 @@ * =================================================================== * Copyright (c) 2017 AT&T Intellectual Property * =================================================================== + * Modifications Copyright (c) 2019 IBM. + * =================================================================== * 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 @@ -22,9 +24,9 @@ package org.onap.music.unittests.jsonobjects; -import static org.junit.Assert.*; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; -import java.io.Serializable; import java.util.HashMap; import java.util.Map; @@ -98,6 +100,12 @@ public class JsonInsertTest { assertArrayEquals(ji1,test1); } - + @Test + public void testObjectMap() + { + Map<String, byte[]> map = new HashMap<>(); + ji.setObjectMap(map); + assertEquals(map, ji.getObjectMap()); + } } diff --git a/src/test/java/org/onap/music/unittests/jsonobjects/JsonLeasedLockTest.java b/src/test/java/org/onap/music/unittests/jsonobjects/JsonLeasedLockTest.java index 0014093d..b7dfa075 100644 --- a/src/test/java/org/onap/music/unittests/jsonobjects/JsonLeasedLockTest.java +++ b/src/test/java/org/onap/music/unittests/jsonobjects/JsonLeasedLockTest.java @@ -44,11 +44,4 @@ public class JsonLeasedLockTest { assertEquals(lease,jl.getLeasePeriod()); } - @Test - public void testGetNotifyUrl() { - String url = "http://somewhere.com"; - jl.setNotifyUrl(url); - assertEquals(url,jl.getNotifyUrl()); - } - } diff --git a/src/test/java/org/onap/music/unittests/jsonobjects/JsonOnboardTest.java b/src/test/java/org/onap/music/unittests/jsonobjects/JsonOnboardTest.java deleted file mode 100644 index 1e66ed58..00000000 --- a/src/test/java/org/onap/music/unittests/jsonobjects/JsonOnboardTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * ============LICENSE_START========================================== - * org.onap.music - * =================================================================== - * Copyright (c) 2017 AT&T Intellectual Property - * =================================================================== - * 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============================================= - * ==================================================================== - */ - -package org.onap.music.unittests.jsonobjects; - -import static org.junit.Assert.*; -import org.junit.Before; -import org.junit.Test; -import org.onap.music.datastore.jsonobjects.JsonOnboard; - -public class JsonOnboardTest { - - JsonOnboard jo = null; - - @Before - public void init() { - jo = new JsonOnboard(); - } - - - @Test - public void testGetPassword() { - String password = "password"; - jo.setPassword(password); - assertEquals(password,jo.getPassword()); - } - - @Test - public void testGetAid() { - String aid = "aid"; - jo.setAid(aid); - assertEquals(aid,jo.getAid()); - - } - - @Test - public void testGetAppname() { - String appName = "appName"; - jo.setAppname(appName); - assertEquals(appName,jo.getAppname()); - - } - - @Test - public void testGetUserId() { - String userId = "userId"; - jo.setUserId(userId); - assertEquals(userId,jo.getUserId()); - - } - - @Test - public void testGetIsAAF() { - String aaf = "true"; - jo.setIsAAF(aaf); - assertEquals(aaf,jo.getIsAAF()); - - } - -} diff --git a/src/test/java/org/onap/music/unittests/jsonobjects/NameSpaceTest.java b/src/test/java/org/onap/music/unittests/jsonobjects/NameSpaceTest.java deleted file mode 100644 index ee4d3933..00000000 --- a/src/test/java/org/onap/music/unittests/jsonobjects/NameSpaceTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * ============LICENSE_START========================================== - * org.onap.music - * =================================================================== - * Copyright (c) 2018 IBM. - * =================================================================== - * 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============================================= - * ==================================================================== - */ - -package org.onap.music.unittests.jsonobjects; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import org.onap.music.datastore.jsonobjects.NameSpace; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class NameSpaceTest { - private NameSpace nameSpace; - - @Before - public void setUp() { - nameSpace = new NameSpace(); - } - - @Test - public void testGetSetAdmin() { - List<String> list = new ArrayList<String>(); - list.add("admin"); - nameSpace.setAdmin(list); - Assert.assertEquals(list, nameSpace.getAdmin()); - } - - @Test - public void testGetSetName() { - nameSpace.setName("name"); - Assert.assertEquals("name", nameSpace.getName()); - } -} diff --git a/version.properties b/version.properties index e4766ef0..ba44c860 100755 --- a/version.properties +++ b/version.properties @@ -4,7 +4,7 @@ major=3 minor=2 -patch=29 +patch=34 base_version=${major}.${minor}.${patch} |