diff options
89 files changed, 13855 insertions, 22 deletions
diff --git a/WebContent/WEB-INF/web.xml b/WebContent/WEB-INF/web.xml index 59fe1251..323c805f 100644 --- a/WebContent/WEB-INF/web.xml +++ b/WebContent/WEB-INF/web.xml @@ -18,7 +18,8 @@ io.swagger.jaxrs.json, io.swagger.jaxrs.listing, org.onap.music.rest, - org.onap.music.exceptions + org.onap.music.exceptions, + org.onap.music.conductor.conditionals </param-value> </init-param> <init-param> diff --git a/jar/DO_NOT_EDIT_ANYTHING_IN_THIS_FOLDER.md b/jar/DO_NOT_EDIT_ANYTHING_IN_THIS_FOLDER.md new file mode 100644 index 00000000..d0baf49b --- /dev/null +++ b/jar/DO_NOT_EDIT_ANYTHING_IN_THIS_FOLDER.md @@ -0,0 +1 @@ +This folder (/jar) is not guaranteed to be around for Casablanca. diff --git a/jar/pom.xml b/jar/pom.xml new file mode 100644 index 00000000..91652832 --- /dev/null +++ b/jar/pom.xml @@ -0,0 +1,470 @@ +<!-- + ============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============================================= + ==================================================================== +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.onap.music</groupId> + <artifactId>MUSIC</artifactId> + <packaging>jar</packaging> + <version>2.5.11</version> + <description> + This is the MUSIC REST interface, packaged as a war file. + </description> + + <parent> + <groupId>org.onap.oparent</groupId> + <artifactId>oparent</artifactId> + <version>0.1.1</version> + <relativePath /> + </parent> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <jersey1.version>1.19</jersey1.version> + <jersey2.version>2.25.1</jersey2.version> + <jaxrs.version>2.0.1</jaxrs.version> + <cassandra.version>3.4.0</cassandra.version> + <zookeeper.version>3.4.11</zookeeper.version> + + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> + <!--nexus --> + <nexusproxy>https://nexus.onap.org</nexusproxy> + <snapshotNexusPath>/content/repositories/snapshots/</snapshotNexusPath> + <releaseNexusPath>/content/repositories/releases/</releaseNexusPath> + <stagingNexusPath>/content/repositories/staging/</stagingNexusPath> + <sitePath>/content/sites/site/org/onap/music/${project.version}</sitePath> + <!--maven --> + <timestamp>${maven.build.timestamp}</timestamp> + <maven.build.timestamp.format>yyyy.MM.dd.HH.mm</maven.build.timestamp.format> + <!--docker --> + <docker.tag>${project.version}-${timestamp}</docker.tag> + <docker.latest.tag>${project.version}-latest</docker.latest.tag> + </properties> + + <repositories> + <repository> + <id>ecomp-releases</id> + <name>ECOMP Release Repository</name> + <url>${onap.nexus.url}/${releaseNexusPath}</url> + </repository> + <repository> + <id>ecomp-snapshots</id> + <name>Snapshot Repository</name> + <url>${nexusproxy}/${snapshotNexusPath}</url> + </repository> + <repository> + <id>ecomp-staging</id> + <name>Staging Repository</name> + <url>${nexusproxy}/${stagingNexusPath}</url> + </repository> + </repositories> + + <build> + <finalName>MUSIC</finalName> + <sourceDirectory>src/main/java</sourceDirectory> + <outputDirectory>src/main/webapp/WEB-INF/classes</outputDirectory> + <testSourceDirectory>src/test/java</testSourceDirectory> + <testOutputDirectory>target/test-classes</testOutputDirectory> + <defaultGoal>validate</defaultGoal> + <resources> + <resource> + <directory>src/main/resources</directory> + <filtering>true</filtering> + </resource> + </resources> + <plugins> + <plugin> + <artifactId>maven-eclipse-plugin</artifactId> + <version>2.9</version> + <configuration> + <additionalProjectnatures> + <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature> + </additionalProjectnatures> + <additionalBuildcommands> + <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand> + </additionalBuildcommands> + <downloadSources>true</downloadSources> + <downloadJavadocs>true</downloadJavadocs> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.5.1</version> + <configuration> + <source>1.7</source> + <target>1.7</target> + <excludes> + <exclude>jar/**</exclude> + </excludes> + </configuration> + </plugin> + <plugin> + <artifactId>maven-war-plugin</artifactId> + <version>2.4</version> + <configuration> + <warSourceDirectory>WebContent</warSourceDirectory> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>2.4</version> + <executions> + <execution> + <id>make-a-jar</id> + <phase>compile</phase> + <goals> + <goal>jar</goal> + </goals> + <configuration> + <excludes> + <exclude>**/*.xml</exclude> + <exclude>**/*.properties</exclude> + <exclude>**/Sample*</exclude> + </excludes> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-install-plugin</artifactId> + <version>2.4</version> + <executions> + <execution> + <phase>install</phase> + <goals> + <goal>install-file</goal> + </goals> + <configuration> + <packaging>jar</packaging> + <artifactId>${project.artifactId}</artifactId> + <groupId>${project.groupId}</groupId> + <version>${project.version}</version> + <file>${project.build.directory}/${project.artifactId}.jar</file> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <dependencies> + <!-- Development --> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>servlet-api</artifactId> + <version>2.4</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <version>3.0.1</version> + <scope>provided</scope> + </dependency> + <!-- /Development --> + + <!-- Logging --> + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-core</artifactId> + <version>1.2.3</version> + <exclusions> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + <version>1.2.3</version> + <exclusions> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>com.att.eelf</groupId> + <artifactId>eelf-core</artifactId> + <version>1.0.1-oss</version> + </dependency> + <!-- End Logging --> + + <!-- Cassandra --> + <dependency> + <groupId>com.datastax.cassandra</groupId> + <artifactId>cassandra-driver-core</artifactId> + <version>${cassandra.version}</version> + </dependency> + <!-- /Cassandra --> + + <!-- Zookeeper --> + <dependency> + <groupId>org.apache.zookeeper</groupId> + <artifactId>zookeeper</artifactId> + <version>${zookeeper.version}</version> + <exclusions> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + </exclusion> + </exclusions> + </dependency> + <!-- /Zookeeper --> + + <!-- Jersey --> + <dependency> + <groupId>com.sun.jersey</groupId> + <artifactId>jersey-client</artifactId> + <version>${jersey1.version}</version> + </dependency> + <dependency> + <groupId>com.sun.jersey</groupId> + <artifactId>jersey-server</artifactId> + <version>${jersey1.version}</version> + </dependency> + <dependency> + <groupId>com.sun.jersey</groupId> + <artifactId>jersey-json</artifactId> + <version>${jersey1.version}</version> + </dependency> + <dependency> + <groupId>com.sun.jersey</groupId> + <artifactId>jersey-servlet</artifactId> + <version>${jersey1.version}</version> + </dependency> + <!-- /Jersey --> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-jcs-core</artifactId> + <version>2.2</version> + </dependency> + <dependency> + <groupId>commons-codec</groupId> + <artifactId>commons-codec</artifactId> + <version>1.11</version> + </dependency> + + <!-- Testing --> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.cassandraunit</groupId> + <artifactId>cassandra-unit</artifactId> + <version>3.3.0.2</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.curator</groupId> + <artifactId>curator-test</artifactId> + <version>2.3.0</version> + <exclusions> + <exclusion> + <groupId>org.apache.zookeeper</groupId> + <artifactId>zookeeper</artifactId> + </exclusion> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + </exclusion> + </exclusions> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-all</artifactId> + <version>1.9.0</version> + <scope>test</scope> + </dependency> + <!-- /Testing --> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-handler</artifactId> + <version>4.0.56.Final</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <version>2.9.4</version> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <version>4.5.3</version> + </dependency> + <dependency> + <groupId>io.swagger</groupId> + <artifactId>swagger-jersey-jaxrs</artifactId> + <version>1.5.18</version> + </dependency> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + <version>19.0</version> + </dependency> + <dependency> + <groupId>org.mindrot</groupId> + <artifactId>jbcrypt</artifactId> + <version>0.4</version> + </dependency> + </dependencies> + + <reporting> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <version>2.10.3</version> + <configuration> + <author>true</author> + <breakiterator>true</breakiterator> + <version>true</version> + <links> + <link>https://docs.oracle.com/javase/7/docs/api/</link> + <link>https://tomcat.apache.org/tomcat-7.0-doc/jspapi/</link> + <link>http://docs.oracle.com/javaee/7/api/</link> + </links> + </configuration> + </plugin> + </plugins> + </reporting> + + <profiles> + <profile> + <id>docker</id> + <build> + <plugins> + <plugin> + <groupId>io.fabric8</groupId> + <artifactId>docker-maven-plugin</artifactId> + <version>0.19.1</version> + <configuration> + <verbose>true</verbose> + <apiVersion>1.23</apiVersion> + <registry>nexus3.onap.org:10003</registry> + <images> + <!-- MUSIC War --> + <image> + <name>onap/music/music</name> + <alias>docker_music</alias> + <build> + <cleanup>true</cleanup> + <tags> + <tag>${docker.tag}</tag> + <tag>${docker.latest.tag}</tag> + </tags> + <dockerFileDir>${project.basedir}</dockerFileDir> + <assembly> + <descriptorRef>artifact</descriptorRef> + </assembly> + </build> + </image> + <!-- Cassandra --> + <image> + <name>onap/music/cassandra_music</name> + <alias>docker_cassandra</alias> + <build> + <cleanup>true</cleanup> + <tags> + <tag>3.0-${timestamp}</tag> + <tag>3.0-latest</tag> + </tags> + <dockerFileDir>${project.basedir}/distribution/cassandra</dockerFileDir> + </build> + </image> + <!-- Zookeeper --> + <!-- <image> <name>onap/music/zookeeper_music</name> + <alias>docker_zookeeper</alias> <build> <cleanup>true</cleanup> <tags> <tag>3.4-${timestamp}</tag> + <tag>3.4-latest</tag> </tags> <dockerFileDir>${project.basedir}/distribution/zookeeper</dockerFileDir> + </build> </image> --> + <!-- tomcat 8.5 --> + <!-- <image> <name>onap/music/tomcat_music</name> + <alias>docker_tomcat</alias> <build> <cleanup>true</cleanup> <tags> <tag>8.5-${timestamp}</tag> + <tag>8.5-latest</tag> </tags> <dockerFileDir>${project.basedir}/distribution/tomcat</dockerFileDir> + </build> </image>\ --> + </images> + </configuration> + <executions> + <execution> + <id>clean-images</id> + <phase>pre-clean</phase> + <goals> + <goal>remove</goal> + </goals> + <configuration> + <removeAll>true</removeAll> + <image>music</image> + </configuration> + </execution> + <execution> + <id>generate-images</id> + <phase>package</phase> + <goals> + <goal>build</goal> + </goals> + </execution> + <execution> + <id>push-images</id> + <phase>deploy</phase> + <goals> + <goal>push</goal> + </goals> + <configuration> + <image>onap/music/music</image> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> + <distributionManagement> + <repository> + <id>ecomp-releases</id> + <name>Release Repository</name> + <url>${nexusproxy}/${releaseNexusPath}</url> + </repository> + <snapshotRepository> + <id>ecomp-snapshots</id> + <name>Snapshot Repository</name> + <url>${nexusproxy}/${snapshotNexusPath}</url> + </snapshotRepository> + <!-- added for javadoc --> + <site> + <id>ecomp-site</id> + <url>dav:${nexusproxy}${sitePath}</url> + </site> + </distributionManagement> +</project> diff --git a/jar/src/main/java/LICENSE.txt b/jar/src/main/java/LICENSE.txt new file mode 100644 index 00000000..cc6cdea5 --- /dev/null +++ b/jar/src/main/java/LICENSE.txt @@ -0,0 +1,24 @@ + +The following license applies to all files in this and sub-directories. Licenses +are included in individual source files where appropriate, and if it differs +from this text, it supersedes this. Any file that does not have license text +defaults to being covered by this text; not all files support the addition of +licenses. +# +# ------------------------------------------------------------------------- +# 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. +# +# ------------------------------------------------------------------------- +#
\ No newline at end of file diff --git a/jar/src/main/java/org/onap/music/datastore/MusicDataStore.java b/jar/src/main/java/org/onap/music/datastore/MusicDataStore.java new file mode 100644 index 00000000..71006f73 --- /dev/null +++ b/jar/src/main/java/org/onap/music/datastore/MusicDataStore.java @@ -0,0 +1,469 @@ +/* + * ============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; + +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +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.Cluster; +import com.datastax.driver.core.ColumnDefinitions; +import com.datastax.driver.core.ColumnDefinitions.Definition; +import com.datastax.driver.core.ConsistencyLevel; +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.KeyspaceMetadata; +import com.datastax.driver.core.Metadata; +import com.datastax.driver.core.PreparedStatement; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.Session; +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.datastax.driver.core.policies.RoundRobinPolicy; +import com.datastax.driver.core.HostDistance; +import com.datastax.driver.core.PoolingOptions; + + +/** + * @author nelson24 + * + */ +public class MusicDataStore { + + private Session session; + private Cluster cluster; + + + + /** + * @param session + */ + public void setSession(Session session) { + this.session = session; + } + + /** + * @param session + */ + public Session getSession() { + return session; + } + + /** + * @param cluster + */ + public void setCluster(Cluster cluster) { + this.cluster = cluster; + } + + + + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicDataStore.class); + + /** + * + */ + public MusicDataStore() { + connectToCassaCluster(); + } + + + /** + * @param cluster + * @param session + */ + public MusicDataStore(Cluster cluster, Session session) { + this.session = session; + this.cluster = cluster; + } + + /** + * + * @param remoteIp + * @throws MusicServiceException + */ + public MusicDataStore(String remoteIp) { + try { + connectToCassaCluster(remoteIp); + } catch (MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + } + } + + /** + * + * @return + */ + private ArrayList<String> getAllPossibleLocalIps() { + ArrayList<String> allPossibleIps = new ArrayList<String>(); + try { + Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); + while (en.hasMoreElements()) { + NetworkInterface ni = (NetworkInterface) en.nextElement(); + Enumeration<InetAddress> ee = ni.getInetAddresses(); + while (ee.hasMoreElements()) { + InetAddress ia = (InetAddress) ee.nextElement(); + allPossibleIps.add(ia.getHostAddress()); + } + } + } catch (SocketException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), AppMessages.CONNCECTIVITYERROR, ErrorSeverity.ERROR, ErrorTypes.CONNECTIONERROR); + }catch(Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), ErrorSeverity.ERROR, ErrorTypes.GENERALSERVICEERROR); + } + return allPossibleIps; + } + + /** + * This method iterates through all available IP addresses and connects to multiple cassandra + * clusters. + */ + private void connectToCassaCluster() { + Iterator<String> it = getAllPossibleLocalIps().iterator(); + String address = "localhost"; + String[] addresses = null; + address = MusicUtil.getMyCassaHost(); + addresses = address.split(","); + + logger.info(EELFLoggerDelegate.applicationLogger, + "Connecting to cassa cluster: Iterating through possible ips:" + + getAllPossibleLocalIps()); + PoolingOptions poolingOptions = new PoolingOptions(); + poolingOptions + .setConnectionsPerHost(HostDistance.LOCAL, 4, 10) + .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()); + cluster = Cluster.builder().withPort(9042) + .withCredentials(MusicUtil.getCassName(), MusicUtil.getCassPwd()) + //.withLoadBalancingPolicy(new RoundRobinPolicy()) + .withPoolingOptions(poolingOptions) + .addContactPoints(addresses).build(); + } + else + cluster = Cluster.builder().withPort(9042) + //.withLoadBalancingPolicy(new RoundRobinPolicy()) + .addContactPoints(addresses).build(); + + Metadata metadata = cluster.getMetadata(); + logger.info(EELFLoggerDelegate.applicationLogger, "Connected to cassa cluster " + + metadata.getClusterName() + " at " + address); + session = cluster.connect(); + + break; + } catch (NoHostAvailableException e) { + address = it.next(); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.HOSTUNAVAILABLE, ErrorSeverity.ERROR, ErrorTypes.CONNECTIONERROR); + } + } + } + + /** + * + */ + public void close() { + session.close(); + } + + /** + * This method connects to cassandra cluster on specific address. + * + * @param address + */ + private void connectToCassaCluster(String address) throws MusicServiceException { + String[] addresses = null; + addresses = address.split(","); + PoolingOptions poolingOptions = new PoolingOptions(); + poolingOptions + .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(9042) + .withCredentials(MusicUtil.getCassName(), MusicUtil.getCassPwd()) + //.withLoadBalancingPolicy(new RoundRobinPolicy()) + .withPoolingOptions(poolingOptions) + .addContactPoints(addresses).build(); + } + else { + cluster = Cluster.builder().withPort(9042) + //.withLoadBalancingPolicy(new RoundRobinPolicy()) + .withPoolingOptions(poolingOptions) + .addContactPoints(addresses).build(); + } + Metadata metadata = cluster.getMetadata(); + logger.info(EELFLoggerDelegate.applicationLogger, "Connected to cassa cluster " + + metadata.getClusterName() + " at " + address); + try { + session = cluster.connect(); + } catch (Exception ex) { + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(),AppMessages.CASSANDRACONNECTIVITY, ErrorSeverity.ERROR, ErrorTypes.SERVICEUNAVAILABLE); + throw new MusicServiceException( + "Error while connecting to Cassandra cluster.. " + ex.getMessage()); + } + } + + /** + * + * @param keyspace + * @param tableName + * @param columnName + * @return DataType + */ + public DataType returnColumnDataType(String keyspace, String tableName, String columnName) { + KeyspaceMetadata ks = cluster.getMetadata().getKeyspace(keyspace); + TableMetadata table = ks.getTable(tableName); + return table.getColumn(columnName).getType(); + + } + + /** + * + * @param keyspace + * @param tableName + * @return TableMetadata + */ + public TableMetadata returnColumnMetadata(String keyspace, String tableName) { + KeyspaceMetadata ks = cluster.getMetadata().getKeyspace(keyspace); + return ks.getTable(tableName); + } + + + /** + * Utility function to return the Java specific object type. + * + * @param row + * @param colName + * @param colType + * @return + */ + public Object getColValue(Row row, String colName, DataType colType) { + + switch (colType.getName()) { + case VARCHAR: + return row.getString(colName); + case UUID: + return row.getUUID(colName); + case VARINT: + return row.getVarint(colName); + case BIGINT: + return row.getLong(colName); + case INT: + return row.getInt(colName); + case FLOAT: + return row.getFloat(colName); + case DOUBLE: + return row.getDouble(colName); + case BOOLEAN: + return row.getBool(colName); + case MAP: + return row.getMap(colName, String.class, String.class); + default: + return null; + } + } + + public boolean doesRowSatisfyCondition(Row row, Map<String, Object> condition) throws Exception { + ColumnDefinitions colInfo = row.getColumnDefinitions(); + + for (Map.Entry<String, Object> entry : condition.entrySet()) { + String colName = entry.getKey(); + DataType colType = colInfo.getType(colName); + Object columnValue = getColValue(row, colName, colType); + Object conditionValue = MusicUtil.convertToActualDataType(colType, entry.getValue()); + if (columnValue.equals(conditionValue) == false) + return false; + } + return true; + } + + /** + * Utility function to store ResultSet values in to a MAP for output. + * + * @param results + * @return MAP + */ + public Map<String, HashMap<String, Object>> marshalData(ResultSet results) { + Map<String, HashMap<String, Object>> resultMap = + new HashMap<String, HashMap<String, Object>>(); + int counter = 0; + for (Row row : results) { + ColumnDefinitions colInfo = row.getColumnDefinitions(); + HashMap<String, Object> resultOutput = new HashMap<String, Object>(); + for (Definition definition : colInfo) { + if (!definition.getName().equals("vector_ts")) + resultOutput.put(definition.getName(), + getColValue(row, definition.getName(), definition.getType())); + } + resultMap.put("row " + counter, resultOutput); + counter++; + } + return resultMap; + } + + + // Prepared Statements 1802 additions + /** + * This Method performs DDL and DML operations on Cassandra using specified consistency level + * + * @param queryObject Object containing cassandra prepared query and values. + * @param consistency Specify consistency level for data synchronization across cassandra + * replicas + * @return Boolean Indicates operation success or failure + * @throws MusicServiceException + * @throws MusicQueryException + */ + public boolean executePut(PreparedQueryObject queryObject, String consistency) + throws MusicServiceException, MusicQueryException { + + boolean result = false; + + if (!MusicUtil.isValidQueryObject(!queryObject.getValues().isEmpty(), queryObject)) { + logger.error(EELFLoggerDelegate.errorLogger, queryObject.getQuery(),AppMessages.QUERYERROR, ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicQueryException("Ill formed queryObject for the request = " + "[" + + queryObject.getQuery() + "]"); + } + logger.info(EELFLoggerDelegate.applicationLogger, + "In preprared Execute Put: the actual insert query:" + + queryObject.getQuery() + "; the values" + + queryObject.getValues()); + PreparedStatement preparedInsert = null; + try { + + preparedInsert = session.prepare(queryObject.getQuery()); + + } catch(InvalidQueryException iqe) { + logger.error(EELFLoggerDelegate.errorLogger, iqe.getMessage(),AppMessages.QUERYERROR, ErrorSeverity.CRITICAL, ErrorTypes.QUERYERROR); + throw new MusicQueryException(iqe.getMessage()); + }catch(Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.QUERYERROR, ErrorSeverity.CRITICAL, ErrorTypes.QUERYERROR); + throw new MusicQueryException(e.getMessage()); + } + + try { + if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + logger.info(EELFLoggerDelegate.applicationLogger, "Executing critical put query"); + preparedInsert.setConsistencyLevel(ConsistencyLevel.QUORUM); + } else if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) { + logger.info(EELFLoggerDelegate.applicationLogger, "Executing simple put query"); + preparedInsert.setConsistencyLevel(ConsistencyLevel.ONE); + } + + ResultSet rs = session.execute(preparedInsert.bind(queryObject.getValues().toArray())); + result = rs.wasApplied(); + + } + catch (AlreadyExistsException ae) { + logger.error(EELFLoggerDelegate.errorLogger, ae.getMessage(),AppMessages.SESSIONFAILED+ " [" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicServiceException(ae.getMessage()); + } + catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.SESSIONFAILED+ " [" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicQueryException("Executing Session Failure for Request = " + "[" + + queryObject.getQuery() + "]" + " Reason = " + e.getMessage()); + } + + + return result; + } + + /** + * This method performs DDL operations on Cassandra using consistency level ONE. + * + * @param queryObject Object containing cassandra prepared query and values. + * @return ResultSet + * @throws MusicServiceException + * @throws MusicQueryException + */ + public ResultSet executeEventualGet(PreparedQueryObject queryObject) + throws MusicServiceException, MusicQueryException { + + if (!MusicUtil.isValidQueryObject(!queryObject.getValues().isEmpty(), queryObject)) { + logger.error(EELFLoggerDelegate.errorLogger, "",AppMessages.QUERYERROR+ " [" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicQueryException("Ill formed queryObject for the request = " + "[" + + queryObject.getQuery() + "]"); + } + logger.info(EELFLoggerDelegate.applicationLogger, + "Executing Eventual get query:" + queryObject.getQuery()); + + ResultSet results = null; + try { + PreparedStatement preparedEventualGet = session.prepare(queryObject.getQuery()); + preparedEventualGet.setConsistencyLevel(ConsistencyLevel.ONE); + results = session.execute(preparedEventualGet.bind(queryObject.getValues().toArray())); + + } catch (Exception ex) { + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(),AppMessages.UNKNOWNERROR+ "[" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicServiceException(ex.getMessage()); + } + return results; + } + + /** + * + * This method performs DDL operation on Cassandra using consistency level QUORUM. + * + * @param queryObject Object containing cassandra prepared query and values. + * @return ResultSet + * @throws MusicServiceException + * @throws MusicQueryException + */ + public ResultSet executeCriticalGet(PreparedQueryObject queryObject) + throws MusicServiceException, MusicQueryException { + if (!MusicUtil.isValidQueryObject(!queryObject.getValues().isEmpty(), queryObject)) { + logger.error(EELFLoggerDelegate.errorLogger, "",AppMessages.QUERYERROR+ " [" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicQueryException("Error processing Prepared Query Object for the request = " + "[" + + queryObject.getQuery() + "]"); + } + logger.info(EELFLoggerDelegate.applicationLogger, + "Executing Critical get query:" + queryObject.getQuery()); + PreparedStatement preparedEventualGet = session.prepare(queryObject.getQuery()); + preparedEventualGet.setConsistencyLevel(ConsistencyLevel.QUORUM); + ResultSet results = null; + try { + results = session.execute(preparedEventualGet.bind(queryObject.getValues().toArray())); + } catch (Exception ex) { + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(),AppMessages.UNKNOWNERROR+ "[" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicServiceException(ex.getMessage()); + } + return results; + + } + +} diff --git a/jar/src/main/java/org/onap/music/datastore/PreparedQueryObject.java b/jar/src/main/java/org/onap/music/datastore/PreparedQueryObject.java new file mode 100644 index 00000000..694d9acd --- /dev/null +++ b/jar/src/main/java/org/onap/music/datastore/PreparedQueryObject.java @@ -0,0 +1,79 @@ +/* + * ============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; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author srupane + * + */ +public class PreparedQueryObject { + + + private List<Object> values; + private StringBuilder query; + + + + /** + * + */ + public PreparedQueryObject() { + + this.values = new ArrayList<>(); + this.query = new StringBuilder(); + } + + /** + * @return + */ + public List<Object> getValues() { + return values; + } + + /** + * @param o + */ + public void addValue(Object o) { + this.values.add(o); + } + + /** + * @param s + */ + public void appendQueryString(String s) { + this.query.append(s); + } + + /** + * @return + */ + public String getQuery() { + return this.query.toString(); + } + + + +} diff --git a/jar/src/main/java/org/onap/music/datastore/jsonobjects/AAFResponse.java b/jar/src/main/java/org/onap/music/datastore/jsonobjects/AAFResponse.java new file mode 100644 index 00000000..df6089ee --- /dev/null +++ b/jar/src/main/java/org/onap/music/datastore/jsonobjects/AAFResponse.java @@ -0,0 +1,42 @@ +/* + * ============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.ArrayList; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel(value = "JsonTable", description = "Reponse class for AAF request") +public class AAFResponse { + + private ArrayList<NameSpace> ns = null; + + @ApiModelProperty(value = "Namespace value") + public ArrayList<NameSpace> getNs() { + return ns; + } + + public void setNs(ArrayList<NameSpace> ns) { + this.ns = ns; + } + +} diff --git a/jar/src/main/java/org/onap/music/datastore/jsonobjects/JSONObject.java b/jar/src/main/java/org/onap/music/datastore/jsonobjects/JSONObject.java new file mode 100644 index 00000000..8de0a2cd --- /dev/null +++ b/jar/src/main/java/org/onap/music/datastore/jsonobjects/JSONObject.java @@ -0,0 +1,37 @@ +package org.onap.music.datastore.jsonobjects; +/* + * ============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============================================= + * ==================================================================== + */ + + +public class JSONObject { + + private String data; + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } + +} diff --git a/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonDelete.java b/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonDelete.java new file mode 100644 index 00000000..a5db4be5 --- /dev/null +++ b/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonDelete.java @@ -0,0 +1,87 @@ +/* + * ============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.ArrayList; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel(value = "JsonTable", description = "Json model for delete") +@JsonIgnoreProperties(ignoreUnknown = true) +public class JsonDelete { + + private ArrayList<String> columns = null; + private Map<String, String> consistencyInfo; + private Map<String, Object> conditions; + String ttl, timestamp; + + + @ApiModelProperty(value = "Conditions") + public Map<String, Object> getConditions() { + return conditions; + } + + public void setConditions(Map<String, Object> conditions) { + this.conditions = conditions; + } + + @ApiModelProperty(value = "Consistency level", allowableValues = "eventual,critical,atomic") + public Map<String, String> getConsistencyInfo() { + return consistencyInfo; + } + + public void setConsistencyInfo(Map<String, String> consistencyInfo) { + this.consistencyInfo = consistencyInfo; + } + + @ApiModelProperty(value = "Column values") + public ArrayList<String> getColumns() { + return columns; + } + + public void setColumns(ArrayList<String> columns) { + this.columns = columns; + } + + + @ApiModelProperty(value = "Time to live information") + public String getTtl() { + return ttl; + } + + public void setTtl(String ttl) { + this.ttl = ttl; + } + + @ApiModelProperty(value = "Time stamp") + public String getTimestamp() { + return timestamp; + } + + public void setTimestamp(String timestamp) { + this.timestamp = timestamp; + } +} diff --git a/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java b/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java new file mode 100644 index 00000000..a58552c6 --- /dev/null +++ b/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java @@ -0,0 +1,122 @@ +/* + * ============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.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Map; + +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") +@JsonIgnoreProperties(ignoreUnknown = true) +public class JsonInsert implements Serializable { + private String keyspaceName; + private String tableName; + private Map<String, Object> values; + private String ttl; + private String timestamp; + private Map<String, Object> row_specification; + private Map<String, String> consistencyInfo; + + @ApiModelProperty(value = "keyspace") + public String getKeyspaceName() { + return keyspaceName; + } + + public void setKeyspaceName(String keyspaceName) { + this.keyspaceName = keyspaceName; + } + + @ApiModelProperty(value = "Table name") + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + + @ApiModelProperty(value = "Consistency level", allowableValues = "eventual,critical,atomic") + public Map<String, String> getConsistencyInfo() { + return consistencyInfo; + } + + public void setConsistencyInfo(Map<String, String> consistencyInfo) { + this.consistencyInfo = consistencyInfo; + } + + @ApiModelProperty(value = "Time to live information") + public String getTtl() { + return ttl; + } + + public void setTtl(String ttl) { + this.ttl = ttl; + } + + @ApiModelProperty(value = "Time stamp") + public String getTimestamp() { + return timestamp; + } + + public void setTimestamp(String timestamp) { + this.timestamp = timestamp; + } + + @ApiModelProperty(value = "values returned") + public Map<String, Object> getValues() { + return values; + } + + public void setValues(Map<String, Object> values) { + this.values = values; + } + + @ApiModelProperty(value = "Information for selecting specific rows for insert") + public Map<String, Object> getRow_specification() { + return row_specification; + } + + public void setRow_specification(Map<String, Object> row_specification) { + this.row_specification = row_specification; + } + + public byte[] serialize() { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutput out = null; + try { + out = new ObjectOutputStream(bos); + out.writeObject(this); + } catch (IOException e) { + e.printStackTrace(); + } + return bos.toByteArray(); + } + +} diff --git a/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonKeySpace.java b/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonKeySpace.java new file mode 100644 index 00000000..54de02fd --- /dev/null +++ b/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonKeySpace.java @@ -0,0 +1,77 @@ +/* + * ============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.Map; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel(value = "JsonTable", description = "Json model creating new keyspace") +@JsonIgnoreProperties(ignoreUnknown = true) +public class JsonKeySpace { + private String keyspaceName; + private Map<String, Object> replicationInfo; + private String durabilityOfWrites; + private Map<String, String> consistencyInfo; + + @ApiModelProperty(value = "Consistency level", allowableValues = "eventual,critical,atomic") + public Map<String, String> getConsistencyInfo() { + return consistencyInfo; + } + + public void setConsistencyInfo(Map<String, String> consistencyInfo) { + this.consistencyInfo = consistencyInfo; + } + + @ApiModelProperty(value = "Replication information") + public Map<String, Object> getReplicationInfo() { + return replicationInfo; + } + + public void setReplicationInfo(Map<String, Object> replicationInfo) { + this.replicationInfo = replicationInfo; + } + + @ApiModelProperty(value = "Durability", allowableValues = "true,false") + public String getDurabilityOfWrites() { + return durabilityOfWrites; + } + + public void setDurabilityOfWrites(String durabilityOfWrites) { + this.durabilityOfWrites = durabilityOfWrites; + } + + @ApiModelProperty(value = "Keyspace name") + public String getKeyspaceName() { + return keyspaceName; + } + + public void setKeyspaceName(String keyspaceName) { + this.keyspaceName = keyspaceName; + } + + + +} diff --git a/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonLeasedLock.java b/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonLeasedLock.java new file mode 100644 index 00000000..497e17d1 --- /dev/null +++ b/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonLeasedLock.java @@ -0,0 +1,52 @@ +/* + * ============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 = "JsonTable", description = "model for leased lock") +@JsonIgnoreProperties(ignoreUnknown = true) +public class JsonLeasedLock { + long leasePeriod; + String notifyUrl; + + @ApiModelProperty(value = "Lease period") + public long getLeasePeriod() { + return leasePeriod; + } + + public void setLeasePeriod(long leasePeriod) { + 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/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonOnboard.java b/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonOnboard.java new file mode 100755 index 00000000..0bac1e31 --- /dev/null +++ b/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonOnboard.java @@ -0,0 +1,83 @@ +/* + * ============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; + + @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/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonSelect.java b/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonSelect.java new file mode 100644 index 00000000..64bc3887 --- /dev/null +++ b/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonSelect.java @@ -0,0 +1,59 @@ +/* + * ============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.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class JsonSelect implements Serializable { + private Map<String, String> consistencyInfo; + + + public Map<String, String> getConsistencyInfo() { + return consistencyInfo; + } + + public void setConsistencyInfo(Map<String, String> consistencyInfo) { + this.consistencyInfo = consistencyInfo; + } + + public byte[] serialize() { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutput out = null; + try { + out = new ObjectOutputStream(bos); + out.writeObject(this); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return bos.toByteArray(); + } + +} diff --git a/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonTable.java b/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonTable.java new file mode 100644 index 00000000..5d508adb --- /dev/null +++ b/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonTable.java @@ -0,0 +1,117 @@ +/* + * ============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.Map; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel(value = "JsonTable", description = "Defines the Json for Creating a new Table.") +@JsonIgnoreProperties(ignoreUnknown = true) +public class JsonTable { + private String keyspaceName; + private String tableName; + + private Map<String, String> fields; + private Map<String, Object> properties; + private String primaryKey; + private String sortingKey; + private String clusteringOrder; + private Map<String, String> consistencyInfo; + + @ApiModelProperty(value = "Consistency level", allowableValues = "eventual,critical,atomic") + public Map<String, String> getConsistencyInfo() { + return consistencyInfo; + } + + public void setConsistencyInfo(Map<String, String> consistencyInfo) { + this.consistencyInfo = consistencyInfo; + } + + @ApiModelProperty(value = "Properties") + public Map<String, Object> getProperties() { + return properties; + } + + public void setProperties(Map<String, Object> properties) { + this.properties = properties; + } + + @ApiModelProperty(value = "Fields") + public Map<String, String> getFields() { + return fields; + } + + public void setFields(Map<String, String> fields) { + this.fields = fields; + } + + @ApiModelProperty(value = "KeySpace Name") + public String getKeyspaceName() { + return keyspaceName; + } + + public void setKeyspaceName(String keyspaceName) { + this.keyspaceName = keyspaceName; + } + + @ApiModelProperty(value = "Table Name") + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + + @ApiModelProperty(value = "Sorting Key") + public String getSortingKey() { + return sortingKey; + } + + public void setSortingKey(String sortingKey) { + this.sortingKey = sortingKey; + } + + @ApiModelProperty(value = "Clustering Order", notes = "") + public String getClusteringOrder() { + return clusteringOrder; + } + + public void setClusteringOrder(String clusteringOrder) { + this.clusteringOrder = clusteringOrder; + } + + @ApiModelProperty(value = "Primary Key") + public String getPrimaryKey() { + return primaryKey; + } + + public void setPrimaryKey(String primaryKey) { + this.primaryKey = primaryKey; + } + + +} diff --git a/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonUpdate.java b/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonUpdate.java new file mode 100644 index 00000000..3ab5ea0d --- /dev/null +++ b/jar/src/main/java/org/onap/music/datastore/jsonobjects/JsonUpdate.java @@ -0,0 +1,132 @@ +/* + * ============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.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Map; + +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) +public class JsonUpdate implements Serializable { + private String keyspaceName; + private String tableName; + private Map<String, Object> values; + private String ttl, timestamp; + private Map<String, String> consistencyInfo; + private Map<String, Object> conditions; + private Map<String, Object> row_specification; + + @ApiModelProperty(value = "Conditions") + public Map<String, Object> getConditions() { + return conditions; + } + + public void setConditions(Map<String, Object> conditions) { + this.conditions = conditions; + } + + @ApiModelProperty(value = "Information for selecting sepcific rows") + public Map<String, Object> getRow_specification() { + return row_specification; + } + + public void setRow_specification(Map<String, Object> row_specification) { + this.row_specification = row_specification; + } + + + @ApiModelProperty(value = "Keyspace name") + public String getKeyspaceName() { + return keyspaceName; + } + + public void setKeyspaceName(String keyspaceName) { + this.keyspaceName = keyspaceName; + } + + @ApiModelProperty(value = "Table name") + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + + @ApiModelProperty(value = "Consistency level", allowableValues = "eventual,critical,atomic") + public Map<String, String> getConsistencyInfo() { + return consistencyInfo; + } + + public void setConsistencyInfo(Map<String, String> consistencyInfo) { + this.consistencyInfo = consistencyInfo; + } + + @ApiModelProperty(value = "Time to live value") + public String getTtl() { + return ttl; + } + + public void setTtl(String ttl) { + this.ttl = ttl; + } + + @ApiModelProperty(value = "Time stamp") + public String getTimestamp() { + return timestamp; + } + + public void setTimestamp(String timestamp) { + this.timestamp = timestamp; + } + + @ApiModelProperty(value = "Column values") + public Map<String, Object> getValues() { + return values; + } + + public void setValues(Map<String, Object> values) { + this.values = values; + } + + public byte[] serialize() { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutput out = null; + try { + out = new ObjectOutputStream(bos); + out.writeObject(this); + } catch (IOException e) { + e.printStackTrace(); + } + return bos.toByteArray(); + } + +} diff --git a/jar/src/main/java/org/onap/music/datastore/jsonobjects/NameSpace.java b/jar/src/main/java/org/onap/music/datastore/jsonobjects/NameSpace.java new file mode 100644 index 00000000..232353c1 --- /dev/null +++ b/jar/src/main/java/org/onap/music/datastore/jsonobjects/NameSpace.java @@ -0,0 +1,47 @@ +/* + * ============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/jar/src/main/java/org/onap/music/eelf/healthcheck/MusicHealthCheck.java b/jar/src/main/java/org/onap/music/eelf/healthcheck/MusicHealthCheck.java new file mode 100644 index 00000000..1f4abea1 --- /dev/null +++ b/jar/src/main/java/org/onap/music/eelf/healthcheck/MusicHealthCheck.java @@ -0,0 +1,175 @@ +/* + * ============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.eelf.healthcheck; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Iterator; + + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.mindrot.jbcrypt.BCrypt; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.datastore.jsonobjects.JsonOnboard; +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.MusicLockingException; +import org.onap.music.lockingservice.MusicLockingService; +import org.onap.music.main.CachingUtil; +import org.onap.music.main.MusicCore; +import org.onap.music.main.MusicUtil; +import org.onap.music.main.ResultType; +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.ResultSet; + + + + +/** + * @author inam + * + */ +public class MusicHealthCheck { + + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicUtil.class); + + private String cassandrHost; + private String zookeeperHost; + + + + + + + + + public String getCassandraStatus() { + logger.info(EELFLoggerDelegate.applicationLogger,"Getting Status for Cassandra"); + if(this.getAdminKeySpace()) { + return "ACTIVE"; + }else { + logger.info(EELFLoggerDelegate.applicationLogger,"Cassandra Service is not responding"); + return "INACTIVE"; + } + } + + + private Boolean getAdminKeySpace() { + + String appName = ""; + + PreparedQueryObject pQuery = new PreparedQueryObject(); + pQuery.appendQueryString( + "select * from admin.keyspace_master"); + //pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); + try { + ResultSet rs = MusicCore.get(pQuery); + + if(rs != null) { + return Boolean.TRUE; + }else { + return Boolean.FALSE; + } + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(),AppMessages.CASSANDRACONNECTIVITY, ErrorTypes.CONNECTIONERROR, ErrorSeverity.CRITICAL); + } + + return Boolean.FALSE; + + + } + + public String getZookeeperStatus() { + + + String host = MusicUtil.getMyZkHost(); + logger.info(EELFLoggerDelegate.applicationLogger,"Getting Status for Zookeeper Host: "+host); + try { + MusicLockingService lockingService = MusicCore.getLockingServiceHandle(); + //additionally need to call the ZK to create,aquire and delete lock + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(),AppMessages.LOCKINGERROR, ErrorTypes.CONNECTIONERROR, ErrorSeverity.CRITICAL); + return "INACTIVE"; + } + + logger.info(EELFLoggerDelegate.applicationLogger,"Zookeeper is Active and Running"); + return "ACTIVE"; + + //return "Zookeeper is not responding"; + + } + + + + + public String getCassandrHost() { + return cassandrHost; + } + + + + + public void setCassandrHost(String cassandrHost) { + this.cassandrHost = cassandrHost; + } + + + + + public String getZookeeperHost() { + return zookeeperHost; + } + + + + + public void setZookeeperHost(String zookeeperHost) { + this.zookeeperHost = zookeeperHost; + } + + + + + + + + + + + + + + + + + + + +} diff --git a/jar/src/main/java/org/onap/music/eelf/logging/EELFLoggerDelegate.java b/jar/src/main/java/org/onap/music/eelf/logging/EELFLoggerDelegate.java new file mode 100644 index 00000000..0c290b6f --- /dev/null +++ b/jar/src/main/java/org/onap/music/eelf/logging/EELFLoggerDelegate.java @@ -0,0 +1,354 @@ +/* + * ============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.eelf.logging; + +import static com.att.eelf.configuration.Configuration.MDC_SERVER_FQDN; +import static com.att.eelf.configuration.Configuration.MDC_SERVER_IP_ADDRESS; +import static com.att.eelf.configuration.Configuration.MDC_SERVICE_INSTANCE_ID; +import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME; +import java.net.InetAddress; +import java.text.MessageFormat; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import javax.servlet.http.HttpServletRequest; +import org.slf4j.MDC; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.att.eelf.configuration.SLF4jWrapper; + +public class EELFLoggerDelegate extends SLF4jWrapper implements EELFLogger { + + public static final EELFLogger errorLogger = EELFManager.getInstance().getErrorLogger(); + public static final EELFLogger applicationLogger = + EELFManager.getInstance().getApplicationLogger(); + public static final EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger(); + public static final EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger(); + public static final EELFLogger debugLogger = EELFManager.getInstance().getDebugLogger(); + + private String className; + private static ConcurrentMap<String, EELFLoggerDelegate> classMap = new ConcurrentHashMap<>(); + + public EELFLoggerDelegate(final String className) { + super(className); + this.className = className; + } + + /** + * Convenience method that gets a logger for the specified class. + * + * @see #getLogger(String) + * + * @param clazz + * @return Instance of EELFLoggerDelegate + */ + public static EELFLoggerDelegate getLogger(Class<?> clazz) { + return getLogger(clazz.getName()); + } + + /** + * Gets a logger for the specified class name. If the logger does not already exist in the map, + * this creates a new logger. + * + * @param className If null or empty, uses EELFLoggerDelegate as the class name. + * @return Instance of EELFLoggerDelegate + */ + public static EELFLoggerDelegate getLogger(final String className) { + String classNameNeverNull = className == null || "".equals(className) + ? EELFLoggerDelegate.class.getName() + : className; + EELFLoggerDelegate delegate = classMap.get(classNameNeverNull); + if (delegate == null) { + delegate = new EELFLoggerDelegate(className); + classMap.put(className, delegate); + } + return delegate; + } + + /** + * Logs a message at the lowest level: trace. + * + * @param logger + * @param msg + */ + public void trace(EELFLogger logger, String msg) { + if (logger.isTraceEnabled()) { + logger.trace(msg); + } + } + + /** + * Logs a message with parameters at the lowest level: trace. + * + * @param logger + * @param msg + * @param arguments + */ + public void trace(EELFLogger logger, String msg, Object... arguments) { + if (logger.isTraceEnabled()) { + logger.trace(msg, arguments); + } + } + + /** + * Logs a message and throwable at the lowest level: trace. + * + * @param logger + * @param msg + * @param th + */ + public void trace(EELFLogger logger, String msg, Throwable th) { + if (logger.isTraceEnabled()) { + logger.trace(msg, th); + } + } + + /** + * Logs a message at the second-lowest level: debug. + * + * @param logger + * @param msg + */ + public void debug(EELFLogger logger, String msg) { + if (logger.isDebugEnabled()) { + logger.debug(msg); + } + } + + /** + * Logs a message with parameters at the second-lowest level: debug. + * + * @param logger + * @param msg + * @param arguments + */ + public void debug(EELFLogger logger, String msg, Object... arguments) { + if (logger.isDebugEnabled()) { + logger.debug(msg, arguments); + } + } + + /** + * Logs a message and throwable at the second-lowest level: debug. + * + * @param logger + * @param msg + * @param th + */ + public void debug(EELFLogger logger, String msg, Throwable th) { + if (logger.isDebugEnabled()) { + logger.debug(msg, th); + } + } + + /** + * Logs a message at info level. + * + * @param logger + * @param msg + */ + public void info(EELFLogger logger, String msg) { + logger.info(className + " - "+msg); + } + + /** + * Logs a message with parameters at info level. + * + * @param logger + * @param msg + * @param arguments + */ + public void info(EELFLogger logger, String msg, Object... arguments) { + logger.info(msg, arguments); + } + + /** + * Logs a message and throwable at info level. + * + * @param logger + * @param msg + * @param th + */ + public void info(EELFLogger logger, String msg, Throwable th) { + logger.info(msg, th); + } + + /** + * Logs a message at warn level. + * + * @param logger + * @param msg + */ + public void warn(EELFLogger logger, String msg) { + logger.warn(msg); + } + + /** + * Logs a message with parameters at warn level. + * + * @param logger + * @param msg + * @param arguments + */ + public void warn(EELFLogger logger, String msg, Object... arguments) { + logger.warn(msg, arguments); + } + + /** + * Logs a message and throwable at warn level. + * + * @param logger + * @param msg + * @param th + */ + public void warn(EELFLogger logger, String msg, Throwable th) { + logger.warn(msg, th); + } + + /** + * Logs a message at error level. + * + * @param logger + * @param msg + */ + public void error(EELFLogger logger, String msg) { + logger.error(className+ " - " + msg); + } + + /** + * Logs a message with parameters at error level. + * + * @param logger + * @param msg + * @param arguments + */ + public void error(EELFLogger logger, String msg, Object... arguments) { + logger.warn(msg, arguments); + } + + /** + * Logs a message and throwable at error level. + * + * @param logger + * @param msg + * @param th + */ + public void error(EELFLogger logger, String msg, Throwable th) { + logger.warn(msg, th); + } + + /** + * Logs a message with the associated alarm severity at error level. + * + * @param logger + * @param msg + * @param severtiy + */ + public void error(EELFLogger logger, String msg, Object /* AlarmSeverityEnum */ severtiy) { + logger.error(msg); + } + + /** + * Initializes the logger context. + */ + public void init() { + setGlobalLoggingContext(); + final String msg = + "############################ Logging is started. ############################"; + // These loggers emit the current date-time without being told. + info(applicationLogger, msg); + error(errorLogger, msg); + debug(debugLogger, msg); + info(auditLogger, msg); + info(metricsLogger, msg); + } + + /** + * Builds a message using a template string and the arguments. + * + * @param message + * @param args + * @return + */ + private String formatMessage(String message, Object... args) { + StringBuilder sbFormattedMessage = new StringBuilder(); + if (args != null && args.length > 0 && message != null && message != "") { + MessageFormat mf = new MessageFormat(message); + sbFormattedMessage.append(mf.format(args)); + } else { + sbFormattedMessage.append(message); + } + + return sbFormattedMessage.toString(); + } + + /** + * Loads all the default logging fields into the MDC context. + */ + private void setGlobalLoggingContext() { + MDC.put(MDC_SERVICE_INSTANCE_ID, ""); + try { + MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getHostName()); + MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress()); + } catch (Exception e) { + errorLogger.error("setGlobalLoggingContext failed", e); + } + } + + public static void mdcPut(String key, String value) { + MDC.put(key, value); + } + + public static String mdcGet(String key) { + return MDC.get(key); + } + + public static void mdcRemove(String key) { + MDC.remove(key); + } + + /** + * Loads the RequestId/TransactionId into the MDC which it should be receiving with an each + * incoming REST API request. Also, configures few other request based logging fields into the + * MDC context. + * + * @param req + * @param appName + */ + public void setRequestBasedDefaultsIntoGlobalLoggingContext(HttpServletRequest req, + String appName) { + // Load the default fields + setGlobalLoggingContext(); + + // Load the request based fields + if (req != null) { + // Rest Path + MDC.put(MDC_SERVICE_NAME, req.getServletPath()); + + // Client IPAddress i.e. IPAddress of the remote host who is making + // this request. + String clientIPAddress = req.getHeader("X-FORWARDED-FOR"); + if (clientIPAddress == null) { + clientIPAddress = req.getRemoteAddr(); + } + } + } +} diff --git a/jar/src/main/java/org/onap/music/eelf/logging/format/AppMessages.java b/jar/src/main/java/org/onap/music/eelf/logging/format/AppMessages.java new file mode 100644 index 00000000..2c7952b2 --- /dev/null +++ b/jar/src/main/java/org/onap/music/eelf/logging/format/AppMessages.java @@ -0,0 +1,183 @@ +/* + * ============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.eelf.logging.format; + +/** + * @author inam + * + */ +public enum AppMessages { + + + + /* + * 100-199 Security/Permission Related - Authentication problems + * [ERR100E] Missing Information + * [ERR101E] Authentication error occured + * + * 200-299 Availability/Timeout Related/IO - connectivity error - connection timeout + * [ERR200E] Connectivity + * [ERR201E] Host not available + * [ERR202E] Error while connecting to Cassandra cluster + * [ERR203E] IO Error has occured + * [ERR204E] Execution Interrupted + * [ERR205E] Session Expired + * [ERR206E] Cache not authenticated + * + * + * 300-399 Data Access/Integrity Related + * [ERR300E] Incorrect data + * + * 400-499 - Cassandra Query Related + * [ERR400E] Error while processing prepared query object + * [ERR401E] Executing Session Failure for Request + * [ERR402E] Ill formed queryObject for the request + * [ERR403E] Error processing Prepared Query Object + * + * 500-599 - Zookeepr/Locking Related + * [ERR500E] Invalid lock + * [ERR501E] Locking Error has occured + * [ERR502E] Zookeeper error has occured + * [ERR503E] Failed to aquire lock store handle + * [ERR504E] Failed to create Lock Reference + * [ERR505E] Lock does not exist + * [ERR506E] Failed to aquire lock + * [ERR507E] Lock not aquired + * [ERR508E] Lock state not set + * [ERR509E] Lock not destroyed + * [ERR510E] Lock not released + * [ERR511E] Lock not deleted + * [ERR512E] Failed to get ZK Lock Handle + * + * + * 600 - 699 - Music Service Errors + * [ERR600E] Error initializing the cache + * + * 700-799 Schema Interface Type/Validation - received Pay-load checksum is + * invalid - received JSON is not valid + * + * 800-899 Business/Flow Processing Related - check out to service is not + * allowed - Roll-back is done - failed to generate heat file + * + * + * 900-999 Unknown Errors - Unexpected exception + * [ERR900E] Unexpected error occured + * [ERR901E] Number format exception + * + * + * 1000-1099 Reserved - do not use + * + */ + + + + + MISSINGINFO("[ERR100E]", "Missing Information ","Details: NA", "Please check application credentials and/or headers"), + AUTHENTICATIONERROR("[ERR101E]", "Authentication error occured ","Details: NA", "Please verify application credentials"), + CONNCECTIVITYERROR("[ERR200E]"," Connectivity error","Details: NA ","Please check connectivity to external resources"), + HOSTUNAVAILABLE("[ERR201E]","Host not available","Details: NA","Please verify the host details"), + CASSANDRACONNECTIVITY("[ERR202E]","Error while connecting to Cassandra cluster",""," Please check cassandra cluster details"), + IOERROR("[ERR203E]","IO Error has occured","","Please check IO"), + EXECUTIONINTERRUPTED("[ERR204E]"," Execution Interrupted","",""), + SESSIONEXPIRED("[ERR205E]"," Session Expired","","Session has expired."), + CACHEAUTHENTICATION("[ERR206E]","Cache not authenticated",""," Cache not authenticated"), + + INCORRECTDATA("[ERR300E]"," Incorrect data",""," Please verify the request payload and try again"), + MULTIPLERECORDS("[ERR301E]"," Multiple records found",""," Please verify the request payload and try again"), + ALREADYEXIST("[ERR302E]"," Record already exist",""," Please verify the request payload and try again"), + MISSINGDATA("[ERR300E]"," Incorrect data",""," Please verify the request payload and try again"), + + QUERYERROR("[ERR400E]","Error while processing prepared query object",""," Please verify the query"), + SESSIONFAILED("[ERR401E]","Executing Session Failure for Request","","Please verify the session and request"), + + INVALIDLOCK("[ERR500E]"," Invalid lock or acquire failed",""," Lock is not valid to aquire"), + LOCKINGERROR("[ERR501E]"," Locking Error has occured",""," Locking Error has occured"), + KEEPERERROR("[ERR502E]"," Zookeeper error has occured","","Please check zookeeper details"), + LOCKHANDLE("[ERR503E]","Failed to aquire lock store handle",""," Failed to aquire lock store handle"), + CREATELOCK("[ERR504E]","Failed to aquire lock store handle ","","Failed to aquire lock store handle "), + LOCKSTATE("[ERR508E]"," Lock state not set",""," Lock state not set"), + DESTROYLOCK("[ERR509E]"," Lock not destroyed",""," Lock not destroyed"), + RELEASELOCK("[ERR510E]"," Lock not released",""," Lock not released"), + DELTELOCK("[ERR511E]",""," Lock not deleted "," Lock not deleted "), + CACHEERROR("[ERR600E]"," Error initializing the cache",""," Error initializing the cache"), + + UNKNOWNERROR("[ERR900E]"," Unexpected error occured",""," Please check logs for details"); + + + + ErrorTypes eType; + ErrorSeverity alarmSeverity; + ErrorSeverity errorSeverity; + String errorCode; + String errorDescription; + String details; + String resolution; + + + AppMessages(String errorCode, String errorDescription, String details,String resolution) { + + this.errorCode = errorCode; + this.errorDescription = errorDescription; + this.details = details; + this.resolution = resolution; + } + + + + + AppMessages(ErrorTypes eType, ErrorSeverity alarmSeverity, + ErrorSeverity errorSeverity, String errorCode, String errorDescription, String details, + String resolution) { + + this.eType = eType; + this.alarmSeverity = alarmSeverity; + this.errorSeverity = errorSeverity; + this.errorCode = errorCode; + this.errorDescription = errorDescription; + this.details = details; + this.resolution = resolution; + } + + public String getDetails() { + return this.details; + } + + public String getResolution() { + return this.resolution; + } + + public String getErrorCode() { + return this.errorCode; + } + + public String getErrorDescription() { + return this.errorDescription; + } + + + + + + + +} diff --git a/jar/src/main/java/org/onap/music/eelf/logging/format/ErrorCodes.java b/jar/src/main/java/org/onap/music/eelf/logging/format/ErrorCodes.java new file mode 100644 index 00000000..b18c1771 --- /dev/null +++ b/jar/src/main/java/org/onap/music/eelf/logging/format/ErrorCodes.java @@ -0,0 +1,106 @@ +/* + * ============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.eelf.logging.format; + + + +/** + * @author inam + * + */ +public enum ErrorCodes { + + + /* + * 100-199 Security/Permission Related - Authentication problems + * [ERR100E] Missing Information + * [ERR101E] Authentication error occured + * + * 200-299 Availability/Timeout Related/IO - connectivity error - connection timeout + * [ERR200E] Connectivity + * [ERR201E] Host not available + * [ERR202E] Error while connecting to Cassandra cluster + * [ERR203E] IO Error has occured + * [ERR204E] Execution Interrupted + * [ERR205E] Session Expired + * [ERR206E] Cache not authenticated + * + * + * 300-399 Data Access/Integrity Related + * + * 400-499 - Cassandra Query Related + * [ERR400E] Error while processing prepared query object + * [ERR401E] Executing Session Failure for Request + * [ERR402E] Ill formed queryObject for the request + * [ERR403E] Error processing Prepared Query Object + * + * 500-599 - Zookeepr/Locking Related + * [ERR500E] Invalid lock + * [ERR501E] Locking Error has occured + * [ERR502E] Zookeeper error has occured + * [ERR503E] Failed to aquire lock store handle + * [ERR504E] Failed to create Lock Reference + * [ERR505E] Lock does not exist + * [ERR506E] Failed to aquire lock + * [ERR507E] Lock not aquired + * [ERR508E] Lock state not set + * [ERR509E] Lock not destroyed + * [ERR510E] Lock not released + * [ERR511E] Lock not deleted + * [ERR512E] Failed to get ZK Lock Handle + * + * + * 600 - 699 - Music Service Errors + * [ERR600E] Error initializing the cache + * + * 700-799 Schema Interface Type/Validation - received Pay-load checksum is + * invalid - received JSON is not valid + * + * 800-899 Business/Flow Processing Related - check out to service is not + * allowed - Roll-back is done - failed to generate heat file + * + * + * 900-999 Unknown Errors - Unexpected exception + * [ERR900E] Unexpected error occured + * [ERR901E] Number format exception + * + * + * 1000-1099 Reserved - do not use + * + */ + + /*SUCCESS("Success"), FAILURE("Failure"); + + private String result; + + ResultType(String result) { + this.result = result; + } + + public String getResult() { + return result; + } +*/ + + + +} diff --git a/jar/src/main/java/org/onap/music/eelf/logging/format/ErrorSeverity.java b/jar/src/main/java/org/onap/music/eelf/logging/format/ErrorSeverity.java new file mode 100644 index 00000000..cda5dd31 --- /dev/null +++ b/jar/src/main/java/org/onap/music/eelf/logging/format/ErrorSeverity.java @@ -0,0 +1,37 @@ +/* + * ============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.eelf.logging.format; + +/** + * @author inam + * + */ +public enum ErrorSeverity { + INFO, + WARN, + ERROR, + FATAL, + CRITICAL, + MAJOR, + MINOR, + NONE, +} diff --git a/jar/src/main/java/org/onap/music/eelf/logging/format/ErrorTypes.java b/jar/src/main/java/org/onap/music/eelf/logging/format/ErrorTypes.java new file mode 100644 index 00000000..2536f4a4 --- /dev/null +++ b/jar/src/main/java/org/onap/music/eelf/logging/format/ErrorTypes.java @@ -0,0 +1,44 @@ +/* + * ============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.eelf.logging.format; + +import com.att.eelf.i18n.EELFResolvableErrorEnum; + +/** + * @author inam + * + */ +public enum ErrorTypes implements EELFResolvableErrorEnum { + + + CONNECTIONERROR, + SESSIONEXPIRED, + AUTHENTICATIONERROR, + SERVICEUNAVAILABLE, + QUERYERROR, + DATAERROR, + GENERALSERVICEERROR, + MUSICSERVICEERROR, + LOCKINGERROR, + UNKNOWN, + +} diff --git a/jar/src/main/java/org/onap/music/exceptions/MusicExceptionMapper.java b/jar/src/main/java/org/onap/music/exceptions/MusicExceptionMapper.java new file mode 100644 index 00000000..14a23d1f --- /dev/null +++ b/jar/src/main/java/org/onap/music/exceptions/MusicExceptionMapper.java @@ -0,0 +1,53 @@ +/* + * ============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.exceptions; + +import java.io.EOFException; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +import org.codehaus.jackson.map.exc.UnrecognizedPropertyException; +import org.onap.music.main.ResultType; +import org.onap.music.response.jsonobjects.JsonResponse; + +@Provider +public class MusicExceptionMapper implements ExceptionMapper<Exception> { + @Override + public Response toResponse(Exception exception) { + if(exception instanceof UnrecognizedPropertyException) { + return Response.status(Response.Status.BAD_REQUEST). + entity(new JsonResponse(ResultType.FAILURE).setError("Unknown field :"+((UnrecognizedPropertyException) exception).getUnrecognizedPropertyName()).toMap()). + build(); + } + else if(exception instanceof EOFException) { + return Response.status(Response.Status.BAD_REQUEST). + entity(new JsonResponse(ResultType.FAILURE).setError("Request body cannot be empty").toMap()). + build(); + } + else { + return Response.status(Response.Status.BAD_REQUEST). + entity(new JsonResponse(ResultType.FAILURE).setError(exception.getMessage()).toMap()). + build(); + } + } +} diff --git a/jar/src/main/java/org/onap/music/exceptions/MusicLockingException.java b/jar/src/main/java/org/onap/music/exceptions/MusicLockingException.java new file mode 100644 index 00000000..1a9e45d9 --- /dev/null +++ b/jar/src/main/java/org/onap/music/exceptions/MusicLockingException.java @@ -0,0 +1,74 @@ +/* + * ============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.exceptions; + +/** + * @author inam + * + */ +public class MusicLockingException extends Exception { + + /** + * + */ + public MusicLockingException() { + + } + + /** + * @param message + */ + public MusicLockingException(String message) { + super(message); + + } + + /** + * @param cause + */ + public MusicLockingException(Throwable cause) { + super(cause); + + } + + /** + * @param message + * @param cause + */ + public MusicLockingException(String message, Throwable cause) { + super(message, cause); + + } + + /** + * @param message + * @param cause + * @param enableSuppression + * @param writableStackTrace + */ + public MusicLockingException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + + } + +} diff --git a/jar/src/main/java/org/onap/music/exceptions/MusicPolicyVoilationException.java b/jar/src/main/java/org/onap/music/exceptions/MusicPolicyVoilationException.java new file mode 100644 index 00000000..bade21a4 --- /dev/null +++ b/jar/src/main/java/org/onap/music/exceptions/MusicPolicyVoilationException.java @@ -0,0 +1,79 @@ +/* + * ============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.exceptions; + +/** + * @author inam + * + */ +public class MusicPolicyVoilationException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * + */ + public MusicPolicyVoilationException() { + // TODO Auto-generated constructor stub + } + + /** + * @param message + */ + public MusicPolicyVoilationException(String message) { + super(message); + // TODO Auto-generated constructor stub + } + + /** + * @param cause + */ + public MusicPolicyVoilationException(Throwable cause) { + super(cause); + // TODO Auto-generated constructor stub + } + + /** + * @param message + * @param cause + */ + public MusicPolicyVoilationException(String message, Throwable cause) { + super(message, cause); + // TODO Auto-generated constructor stub + } + + /** + * @param message + * @param cause + * @param enableSuppression + * @param writableStackTrace + */ + public MusicPolicyVoilationException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + // TODO Auto-generated constructor stub + } + +} diff --git a/jar/src/main/java/org/onap/music/exceptions/MusicQueryException.java b/jar/src/main/java/org/onap/music/exceptions/MusicQueryException.java new file mode 100644 index 00000000..24b8568b --- /dev/null +++ b/jar/src/main/java/org/onap/music/exceptions/MusicQueryException.java @@ -0,0 +1,89 @@ +/* + * ============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.exceptions; + + + +/** + * @author inam + * + */ +public class MusicQueryException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 1L; + private int errorCode; + + + /** + * + */ + public MusicQueryException() { + super(); + } + + /** + * @param message + */ + public MusicQueryException(String message) { + super(message); + } + + + + /** + * @param message + */ + public MusicQueryException(String message, int errorCode) { + super(message); + this.errorCode = errorCode; + } + + /** + * @param cause + */ + public MusicQueryException(Throwable cause) { + super(cause); + } + + /** + * @param message + * @param cause + */ + public MusicQueryException(String message, Throwable cause) { + super(message, cause); + } + + /** + * @param message + * @param cause + * @param enableSuppression + * @param writableStackTrace + */ + public MusicQueryException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + +} diff --git a/jar/src/main/java/org/onap/music/exceptions/MusicServiceException.java b/jar/src/main/java/org/onap/music/exceptions/MusicServiceException.java new file mode 100644 index 00000000..a3b1fc56 --- /dev/null +++ b/jar/src/main/java/org/onap/music/exceptions/MusicServiceException.java @@ -0,0 +1,84 @@ +/* + * ============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.exceptions; + +/** + * @author inam + * + */ +public class MusicServiceException extends Exception { + + + private int errorCode; + private String errorMessage; + + public int getErrorCode() { + return errorCode; + } + + + public void setErrorCode(int errorCode) { + this.errorCode = errorCode; + } + + + public String getErrorMessage() { + return errorMessage; + } + + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + + public MusicServiceException() { + super(); + } + + + public MusicServiceException(String message) { + super(message); + + } + + + public MusicServiceException(Throwable cause) { + super(cause); + + } + + + public MusicServiceException(String message, Throwable cause) { + super(message, cause); + + } + + + public MusicServiceException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + + } + +} diff --git a/jar/src/main/java/org/onap/music/lockingservice/LockListener.java b/jar/src/main/java/org/onap/music/lockingservice/LockListener.java new file mode 100644 index 00000000..33188e60 --- /dev/null +++ b/jar/src/main/java/org/onap/music/lockingservice/LockListener.java @@ -0,0 +1,39 @@ +/* + * ============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.lockingservice; + +/** + * This class has two methods which are call back methods when a lock is acquired and when the lock + * is released. + * + */ +public interface LockListener { + /** + * call back called when the lock is acquired + */ + public void lockAcquired(); + + /** + * call back called when the lock is released. + */ + public void lockReleased(); +} diff --git a/jar/src/main/java/org/onap/music/lockingservice/MusicLockState.java b/jar/src/main/java/org/onap/music/lockingservice/MusicLockState.java new file mode 100644 index 00000000..6c31410f --- /dev/null +++ b/jar/src/main/java/org/onap/music/lockingservice/MusicLockState.java @@ -0,0 +1,137 @@ +/* + * ============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.lockingservice; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectInputStream; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.io.Serializable; +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; + +// the state variable that will be stored in zookeeper, capturing the transitions of +public class MusicLockState implements Serializable { + public enum LockStatus { + UNLOCKED, BEING_LOCKED, LOCKED + };// captures the state of the lock + + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicLockState.class); + LockStatus lockStatus; + boolean needToSyncQuorum = false; + String lockHolder; + long leasePeriod = Long.MAX_VALUE, leaseStartTime = -1; + + private String errorMessage = null; + + public MusicLockState(String errorMessage) { + this.errorMessage = errorMessage; + } + + public MusicLockState(LockStatus lockStatus, String lockHolder) { + this.lockStatus = lockStatus; + this.lockHolder = lockHolder; + } + + public MusicLockState(LockStatus lockStatus, String lockHolder, boolean needToSyncQuorum) { + this.lockStatus = lockStatus; + this.lockHolder = lockHolder; + this.needToSyncQuorum = needToSyncQuorum; + } + + + public long getLeasePeriod() { + return leasePeriod; + } + + public boolean isNeedToSyncQuorum() { + return needToSyncQuorum; + } + + + + public void setLeasePeriod(long leasePeriod) { + this.leasePeriod = leasePeriod; + } + + + public long getLeaseStartTime() { + return leaseStartTime; + } + + + public void setLeaseStartTime(long leaseStartTime) { + this.leaseStartTime = leaseStartTime; + } + + + + public LockStatus getLockStatus() { + return lockStatus; + } + + public void setLockStatus(LockStatus lockStatus) { + this.lockStatus = lockStatus; + } + + public String getLockHolder() { + return lockHolder; + } + + public void setLockHolder(String lockHolder) { + this.lockHolder = lockHolder; + } + + public String getErrorMessage() { + return errorMessage; + } + + public byte[] serialize() { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutput out = null; + try { + out = new ObjectOutputStream(bos); + out.writeObject(this); + } catch (IOException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.IOERROR, ErrorSeverity.ERROR, ErrorTypes.CONNECTIONERROR); + } + return bos.toByteArray(); + } + + public static MusicLockState deSerialize(byte[] data) { + ByteArrayInputStream bis = new ByteArrayInputStream(data); + Object o = null; + ObjectInput in = null; + try { + in = new ObjectInputStream(bis); + o = in.readObject(); + } catch (ClassNotFoundException | IOException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.UNKNOWNERROR, ErrorSeverity.ERROR, ErrorTypes.UNKNOWN); + } + return (MusicLockState) o; + } +} diff --git a/jar/src/main/java/org/onap/music/lockingservice/MusicLockingService.java b/jar/src/main/java/org/onap/music/lockingservice/MusicLockingService.java new file mode 100644 index 00000000..4070238a --- /dev/null +++ b/jar/src/main/java/org/onap/music/lockingservice/MusicLockingService.java @@ -0,0 +1,184 @@ +/* + * ============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.lockingservice; + + +import java.io.IOException; +import java.util.StringTokenizer; +import java.util.concurrent.CountDownLatch; + +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.Watcher.Event.KeeperState; +import org.apache.zookeeper.ZooKeeper; +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.MusicLockingException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.main.MusicUtil; +import java.util.concurrent.TimeUnit; + + +public class MusicLockingService implements Watcher { + + + private static final int SESSION_TIMEOUT = 180000; + ZkStatelessLockService zkLockHandle = null; + private CountDownLatch connectedSignal = new CountDownLatch(1); + private static EELFLoggerDelegate logger = + EELFLoggerDelegate.getLogger(MusicLockingService.class); + + public MusicLockingService() throws MusicServiceException { + try { + ZooKeeper zk = new ZooKeeper(MusicUtil.getMyZkHost(), SESSION_TIMEOUT, this); + connectedSignal.await(); + zkLockHandle = new ZkStatelessLockService(zk); + } catch (IOException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.IOERROR, ErrorSeverity.ERROR, ErrorTypes.CONNECTIONERROR); + throw new MusicServiceException("IO Error has occured" + e.getMessage()); + } catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + throw new MusicServiceException("Exception Occured " + e.getMessage()); + } + } + + public MusicLockingService(int timeout) throws MusicServiceException { + CountDownLatch connectedSignal1 = new CountDownLatch(1); + try { + ZooKeeper zk1 = new ZooKeeper(MusicUtil.getMyZkHost(), SESSION_TIMEOUT, this); + connectedSignal1.await(timeout, TimeUnit.SECONDS); + if(!zk1.getState().isConnected()) { + throw new MusicServiceException("Unable to Connect. Some nodes are down."); + } + } catch (IOException e ) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.IOERROR, ErrorSeverity.ERROR, ErrorTypes.CONNECTIONERROR); + throw new MusicServiceException("IO Error has occured" + e.getMessage()); + } catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + throw new MusicServiceException("Exception Occured " + e.getMessage()); + } + } + + public ZkStatelessLockService getzkLockHandle() { + return zkLockHandle; + } + + public MusicLockingService(String lockServer) { + try { + ZooKeeper zk = new ZooKeeper(lockServer, SESSION_TIMEOUT, this); + connectedSignal.await(); + zkLockHandle = new ZkStatelessLockService(zk); + } catch (IOException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.IOERROR, ErrorSeverity.ERROR, ErrorTypes.CONNECTIONERROR); + }catch( InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + }catch(Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.UNKNOWNERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + } + } + + public void createLockaIfItDoesNotExist(String lockName) { + if (!zkLockHandle.checkIfLockExists(lockName)) { + String lockHolder = null; + MusicLockState ml = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder); + byte[] data = ml.serialize(); + zkLockHandle.createLock(lockName, data); + } + } + + public void setLockState(String lockName, MusicLockState mls) { + byte[] data = mls.serialize(); + zkLockHandle.setNodeData(lockName, data); + } + + public MusicLockState getLockState(String lockName) throws MusicLockingException { + + byte[] data = null; + try{ + data = zkLockHandle.getNodeData(lockName); + }catch (Exception ex){ + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(),AppMessages.UNKNOWNERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + } + if(data !=null) + return MusicLockState.deSerialize(data); + else { + logger.error(EELFLoggerDelegate.errorLogger,"",AppMessages.INVALIDLOCK, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + throw new MusicLockingException("Invalid lock or acquire failed"); + } + } + + public String createLockId(String lockName) { + String lockIdWithSlash = zkLockHandle.createLockId(lockName); + return lockIdWithSlash.replace('/', '$'); + } + + public boolean isMyTurn(String lockIdWithDollar) { + String lockId = lockIdWithDollar.replace('$', '/'); + StringTokenizer st = new StringTokenizer(lockId); + String lockName = "/" + st.nextToken("/"); + try { + return zkLockHandle.lock(lockName, lockId); + } catch (KeeperException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.LOCKINGERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + }catch( InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + }catch(Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.UNKNOWNERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + } + return false; + } + + public void unlockAndDeleteId(String lockIdWithDollar) throws KeeperException.NoNodeException { + String lockId = lockIdWithDollar.replace('$', '/'); + zkLockHandle.unlock(lockId); + } + + public void deleteLock(String lockName) throws MusicLockingException { + if(lockIdExists(lockName)) + zkLockHandle.deleteLock(lockName); + else{ + throw new MusicLockingException("Lock does not exist.Please check the lock: " + lockName + " and try again"); + } + } + + public String whoseTurnIsIt(String lockName) { + String lockHolder = zkLockHandle.currentLockHolder(lockName); + return lockHolder.replace('/', '$'); + + } + + public void process(WatchedEvent event) { // Watcher interface + if (event.getState() == KeeperState.SyncConnected) { + connectedSignal.countDown(); + } + } + + + public void close() { + zkLockHandle.close(); + } + + public boolean lockIdExists(String lockIdWithDollar) { + String lockId = lockIdWithDollar.replace('$', '/'); + return zkLockHandle.checkIfLockExists(lockId); + } + +} diff --git a/jar/src/main/java/org/onap/music/lockingservice/ProtocolSupport.java b/jar/src/main/java/org/onap/music/lockingservice/ProtocolSupport.java new file mode 100644 index 00000000..4082b3b8 --- /dev/null +++ b/jar/src/main/java/org/onap/music/lockingservice/ProtocolSupport.java @@ -0,0 +1,208 @@ +/* + * ============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.lockingservice; + +import org.apache.zookeeper.CreateMode; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.ZooDefs; +import org.apache.zookeeper.ZooKeeper; +import org.apache.zookeeper.data.ACL; +import org.apache.zookeeper.data.Stat; +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.lockingservice.ZooKeeperOperation; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * A base class for protocol implementations which provides a number of higher level helper methods + * for working with ZooKeeper along with retrying synchronous operations if the connection to + * ZooKeeper closes such as {@link #retryOperation(ZooKeeperOperation)} + * + */ +class ProtocolSupport { + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ProtocolSupport.class); + + protected ZooKeeper zookeeper; + private AtomicBoolean closed = new AtomicBoolean(false); + private long retryDelay = 500L; + private int retryCount = 10; + private List<ACL> acl = ZooDefs.Ids.OPEN_ACL_UNSAFE; + + /** + * Closes this strategy and releases any ZooKeeper resources; but keeps the ZooKeeper instance + * open + */ + public void close() { + if (closed.compareAndSet(false, true)) { + doClose(); + } + } + + /** + * return zookeeper client instance + * + * @return zookeeper client instance + */ + public ZooKeeper getZookeeper() { + return zookeeper; + } + + /** + * return the acl its using + * + * @return the acl. + */ + public List<ACL> getAcl() { + return acl; + } + + /** + * set the acl + * + * @param acl the acl to set to + */ + public void setAcl(List<ACL> acl) { + this.acl = acl; + } + + /** + * get the retry delay in milliseconds + * + * @return the retry delay + */ + public long getRetryDelay() { + return retryDelay; + } + + /** + * Sets the time waited between retry delays + * + * @param retryDelay the retry delay + */ + public void setRetryDelay(long retryDelay) { + this.retryDelay = retryDelay; + } + + /** + * Allow derived classes to perform some custom closing operations to release resources + */ + protected void doClose() { + throw new UnsupportedOperationException(); + } + + + /** + * Perform the given operation, retrying if the connection fails + * + * @return object. it needs to be cast to the callee's expected return type. + * @param operation FILL IN + * @throws KeeperException FILL IN + * @throws InterruptedException FILL IN + */ + protected Object retryOperation(ZooKeeperOperation operation) + throws KeeperException, InterruptedException { + KeeperException exception = null; + for (int i = 0; i < retryCount; i++) { + try { + return operation.execute(); + } catch (KeeperException.SessionExpiredException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.SESSIONEXPIRED+" for: " + zookeeper + " so reconnecting due to: " + e, ErrorSeverity.ERROR, ErrorTypes.SESSIONEXPIRED); + throw e; + } catch (KeeperException.ConnectionLossException e) { + if (exception == null) { + exception = e; + } + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.CONNCECTIVITYERROR, ErrorSeverity.ERROR, ErrorTypes.SESSIONEXPIRED); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),"Attempt " + i + " failed with connection loss so attempting to reconnect: " + e); + + retryDelay(i); + } + } + throw exception; + } + + /** + * Ensures that the given path exists with no data, the current ACL and no flags + * + * @param path the lock path + */ + protected void ensurePathExists(String path) { + ensureExists(path, null, acl, CreateMode.PERSISTENT); + } + + /** + * Ensures that the given path exists with the given data, ACL and flags + * + * @param path the lock path + * @param data the data + * @param acl list of ACLs applying to the path + * @param flags create mode flags + */ + protected void ensureExists(final String path, final byte[] data, final List<ACL> acl, + final CreateMode flags) { + try { + retryOperation(new ZooKeeperOperation() { + public boolean execute() throws KeeperException, InterruptedException { + Stat stat = zookeeper.exists(path, false); + if (stat != null) { + return true; + } + zookeeper.create(path, data, acl, flags); + return true; + } + }); + } catch (KeeperException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.KEEPERERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + } catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + } + } + + /** + * Returns true if this protocol has been closed + * + * @return true if this protocol is closed + */ + protected boolean isClosed() { + return closed.get(); + } + + /** + * Performs a retry delay if this is not the first attempt + * + * @param attemptCount the number of the attempts performed so far + */ + protected void retryDelay(int attemptCount) { + if (attemptCount > 0) { + try { + Thread.sleep(attemptCount * retryDelay); + } catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.GENERALSERVICEERROR); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),"Thread failed to sleep: " + e); + Thread.currentThread().interrupt(); + } + } + } +} diff --git a/jar/src/main/java/org/onap/music/lockingservice/ZNodeName.java b/jar/src/main/java/org/onap/music/lockingservice/ZNodeName.java new file mode 100644 index 00000000..0c190f14 --- /dev/null +++ b/jar/src/main/java/org/onap/music/lockingservice/ZNodeName.java @@ -0,0 +1,118 @@ +/* + * ============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.lockingservice; + +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; + +/** + * Represents an ephemeral znode name which has an ordered sequence number and can be sorted in + * order + * + */ +class ZNodeName implements Comparable<ZNodeName> { + private final String name; + private String prefix; + private int sequence = -1; + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ZNodeName.class); + + public ZNodeName(String name) { + if (name == null) { + throw new NullPointerException("id cannot be null"); + } + this.name = name; + this.prefix = name; + int idx = name.lastIndexOf('-'); + if (idx >= 0) { + this.prefix = name.substring(0, idx); + try { + this.sequence = Integer.parseInt(name.substring(idx + 1)); + // If an exception occurred we misdetected a sequence suffix, + // so return -1. + } catch (NumberFormatException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),"Number format exception "+idx, ErrorSeverity.ERROR, ErrorTypes.GENERALSERVICEERROR); + } catch (ArrayIndexOutOfBoundsException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),"Array out of bounds for "+idx, ErrorSeverity.ERROR, ErrorTypes.GENERALSERVICEERROR); + } + } + } + + @Override + public String toString() { + return name.toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + ZNodeName sequence = (ZNodeName) o; + + if (!name.equals(sequence.name)) + return false; + + return true; + } + + @Override + public int hashCode() { + return name.hashCode() + 37; + } + + public int compareTo(ZNodeName that) { + int answer = this.prefix.compareTo(that.prefix); + if (answer == 0) { + int s1 = this.sequence; + int s2 = that.sequence; + if (s1 == -1 && s2 == -1) { + return this.name.compareTo(that.name); + } + answer = s1 == -1 ? 1 : s2 == -1 ? -1 : s1 - s2; + } + return answer; + } + + /** + * Returns the name of the znode + */ + public String getName() { + return name; + } + + /** + * Returns the sequence number + */ + public int getZNodeName() { + return sequence; + } + + /** + * Returns the text prefix before the sequence number + */ + public String getPrefix() { + return prefix; + } +} diff --git a/jar/src/main/java/org/onap/music/lockingservice/ZkStatelessLockService.java b/jar/src/main/java/org/onap/music/lockingservice/ZkStatelessLockService.java new file mode 100644 index 00000000..e99df255 --- /dev/null +++ b/jar/src/main/java/org/onap/music/lockingservice/ZkStatelessLockService.java @@ -0,0 +1,339 @@ +/* + * ============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.lockingservice; + + +import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; +import org.apache.zookeeper.CreateMode; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.KeeperException.NoNodeException; +import org.apache.zookeeper.ZooDefs; +import org.apache.zookeeper.ZooKeeper; +import org.apache.zookeeper.data.ACL; +import org.apache.zookeeper.data.Stat; +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; + +/** + * A <a href="package.html">protocol to implement an exclusive write lock or to elect a leader</a>. + * <p/> + * You invoke {@link #lock()} to start the process of grabbing the lock; you may get the lock then + * or it may be some time later. + * <p/> + * You can register a listener so that you are invoked when you get the lock; otherwise you can ask + * if you have the lock by calling {@link #isOwner()} + * + */ +public class ZkStatelessLockService extends ProtocolSupport { + public ZkStatelessLockService(ZooKeeper zk) { + zookeeper = zk; + } + + private static EELFLoggerDelegate logger = + EELFLoggerDelegate.getLogger(ZkStatelessLockService.class); + + protected void createLock(final String path, final byte[] data) { + final List<ACL> acl = ZooDefs.Ids.OPEN_ACL_UNSAFE; + try { + retryOperation(new ZooKeeperOperation() { + public boolean execute() throws KeeperException, InterruptedException { + zookeeper.create(path, data, acl, CreateMode.PERSISTENT); + return true; + } + }); + }catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + }catch (KeeperException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.KEEPERERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + } + } + + public void close() { + try { + zookeeper.close(); + }catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + } + } + + public void setNodeData(final String lockName, final byte[] data) { + try { + retryOperation(new ZooKeeperOperation() { + public boolean execute() throws KeeperException, InterruptedException { + zookeeper.getSessionId(); + zookeeper.setData("/" + lockName, data, -1); + return true; + } + }); + }catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + }catch (KeeperException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.KEEPERERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + } + + } + + public byte[] getNodeData(final String lockName) { + try { + if (zookeeper.exists("/" + lockName, null) != null) + return zookeeper.getData("/" + lockName, false, null); + else + return null; + + }catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + }catch (KeeperException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.KEEPERERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + } + return null; + } + + public boolean checkIfLockExists(String lockName) { + boolean result = false; + try { + Stat stat = zookeeper.exists(lockName, false); + if (stat != null) { + result = true; + } + }catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + }catch (KeeperException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.KEEPERERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + } + return result; + } + + public void createNode(String nodeName) { + ensurePathExists(nodeName); + } + + public String createLockId(String dir) { + ensurePathExists(dir); + LockZooKeeperOperation zop = new LockZooKeeperOperation(dir); + try { + retryOperation(zop); + }catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + }catch (KeeperException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.KEEPERERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + } + return zop.getId(); + } + + /** + * Attempts to acquire the exclusive write lock returning whether or not it was acquired. Note + * that the exclusive lock may be acquired some time later after this method has been invoked + * due to the current lock owner going away. + */ + public synchronized boolean lock(String dir, String lockId) + throws KeeperException, InterruptedException { + if (isClosed()) { + return false; + } + LockZooKeeperOperation zop = new LockZooKeeperOperation(dir, lockId); + return (Boolean) retryOperation(zop); + } + + /** + * Removes the lock or associated znode if you no longer require the lock. this also removes + * your request in the queue for locking in case you do not already hold the lock. + * + * @throws RuntimeException throws a runtime exception if it cannot connect to zookeeper. + * @throws NoNodeException + */ + public synchronized void unlock(String lockId) throws RuntimeException, KeeperException.NoNodeException { + final String id = lockId; + if (!isClosed() && id != null) { + try { + ZooKeeperOperation zopdel = new ZooKeeperOperation() { + public boolean execute() throws KeeperException, InterruptedException { + zookeeper.delete(id, -1); + return Boolean.TRUE; + } + }; + zopdel.execute(); + } catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + // set that we have been interrupted. + Thread.currentThread().interrupt(); + } catch (KeeperException.NoNodeException e) { + // do nothing + throw new KeeperException.NoNodeException("Lock doesn't exists. Release lock operation failed."); + } catch (KeeperException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.KEEPERERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + throw (RuntimeException) new RuntimeException(e.getMessage()).initCause(e); + } + } + } + + public synchronized String currentLockHolder(String mainLock) { + final String id = mainLock; + if (!isClosed() && id != null) { + List<String> names; + try { + names = zookeeper.getChildren(id, false); + if (names.isEmpty()) + return ""; + SortedSet<ZNodeName> sortedNames = new TreeSet<ZNodeName>(); + for (String name : names) { + sortedNames.add(new ZNodeName(id + "/" + name)); + } + return sortedNames.first().getName(); + } catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + // set that we have been interrupted. + Thread.currentThread().interrupt(); + } catch (KeeperException.NoNodeException e) { + // do nothing + } catch (KeeperException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.KEEPERERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + throw (RuntimeException) new RuntimeException(e.getMessage()).initCause(e); + } + } + return "No lock holder!"; + } + + public synchronized void deleteLock(String mainLock) { + final String id = mainLock; + if (!isClosed() && id != null) { + try { + ZooKeeperOperation zopdel = new ZooKeeperOperation() { + public boolean execute() throws KeeperException, InterruptedException { + List<String> names = zookeeper.getChildren(id, false); + for (String name : names) { + zookeeper.delete(id + "/" + name, -1); + } + zookeeper.delete(id, -1); + return Boolean.TRUE; + } + }; + zopdel.execute(); + } catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + // set that we have been interrupted. + Thread.currentThread().interrupt(); + } catch (KeeperException.NoNodeException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.KEEPERERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + // do nothing + } catch (KeeperException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.KEEPERERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + throw (RuntimeException) new RuntimeException(e.getMessage()).initCause(e); + } + } + + } + + /** + * a zoookeeper operation that is mainly responsible for all the magic required for locking. + */ + private class LockZooKeeperOperation implements ZooKeeperOperation { + + /** + * find if we have been created earlier if not create our node + * + * @param prefix the prefix node + * @param zookeeper the zookeeper client + * @param dir the dir parent + * @throws KeeperException + * @throws InterruptedException + */ + private String dir; + private String id = null; + + public String getId() { + return id; + } + + public LockZooKeeperOperation(String dir) { + this.dir = dir; + } + + public LockZooKeeperOperation(String dir, String id) { + this.dir = dir; + this.id = id; + } + + /** + * the command that is run and retried for actually obtaining the lock + * + * @return if the command was successful or not + */ + public boolean execute() throws KeeperException, InterruptedException { + do { + if (id == null) { + String prefix = "x-"; + byte[] data = {0x12, 0x34}; + id = zookeeper.create(dir + "/" + prefix, data, getAcl(), + CreateMode.PERSISTENT_SEQUENTIAL); + + if (logger.isDebugEnabled()) { + logger.debug(EELFLoggerDelegate.debugLogger, "Created id: " + id); + } + if (id != null) + break; + } + if (id != null) { + List<String> names = zookeeper.getChildren(dir, false); + if (names.isEmpty()) { + logger.info(EELFLoggerDelegate.applicationLogger, "No children in: " + dir + + " when we've just " + "created one! Lets recreate it..."); + // lets force the recreation of the id + id = null; + return Boolean.FALSE; + + } else { + // lets sort them explicitly (though they do seem to come back in order + // ususally :) + ZNodeName idName = new ZNodeName(id); + SortedSet<ZNodeName> sortedNames = new TreeSet<ZNodeName>(); + for (String name : names) { + sortedNames.add(new ZNodeName(dir + "/" + name)); + } + if (!sortedNames.contains(idName)) + return Boolean.FALSE; + + SortedSet<ZNodeName> lessThanMe = sortedNames.headSet(idName); + if (!lessThanMe.isEmpty()) { + ZNodeName lastChildName = lessThanMe.last(); + String lastChildId = lastChildName.getName(); + if (logger.isDebugEnabled()) { + logger.debug(EELFLoggerDelegate.debugLogger, "watching less than me node: " + lastChildId); + } + Stat stat = zookeeper.exists(lastChildId, false); + if (stat != null) { + return Boolean.FALSE; + } else { + logger.info(EELFLoggerDelegate.applicationLogger, + "Could not find the" + " stats for less than me: " + + lastChildName.getName()); + } + } else + return Boolean.TRUE; + } + } + } while (id == null); + return Boolean.FALSE; + } + } + +} + diff --git a/jar/src/main/java/org/onap/music/lockingservice/ZooKeeperOperation.java b/jar/src/main/java/org/onap/music/lockingservice/ZooKeeperOperation.java new file mode 100644 index 00000000..7020d14d --- /dev/null +++ b/jar/src/main/java/org/onap/music/lockingservice/ZooKeeperOperation.java @@ -0,0 +1,42 @@ +/* + * ============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.lockingservice; + +import org.apache.zookeeper.KeeperException; + +/** + * A callback object which can be used for implementing retry-able operations in the + * {@link org.onap.music.lockingservice.ProtocolSupport} class + * + */ +public interface ZooKeeperOperation { + + /** + * Performs the operation - which may be involved multiple times if the connection + * to ZooKeeper closes during this operation + * + * @return the result of the operation or null + * @throws KeeperException FILL IN + * @throws InterruptedException FILL IN + */ + public boolean execute() throws KeeperException, InterruptedException; +} diff --git a/jar/src/main/java/org/onap/music/main/CachingUtil.java b/jar/src/main/java/org/onap/music/main/CachingUtil.java new file mode 100755 index 00000000..aa06aae2 --- /dev/null +++ b/jar/src/main/java/org/onap/music/main/CachingUtil.java @@ -0,0 +1,420 @@ +/* + * ============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.util.Arrays; +import java.util.Calendar; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.UUID; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.jcs.JCS; +import org.apache.commons.jcs.access.CacheAccess; +import org.codehaus.jackson.map.ObjectMapper; +import org.mindrot.jbcrypt.BCrypt; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.datastore.jsonobjects.AAFResponse; +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.MusicServiceException; + +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.exceptions.InvalidQueryException; +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; + +/** + * All Caching related logic is handled by this class and a schedule cron runs to update cache. + * + * @author Vikram + * + */ +public class CachingUtil implements Runnable { + + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(CachingUtil.class); + + private static CacheAccess<String, String> musicCache = JCS.getInstance("musicCache"); + private static CacheAccess<String, Map<String, String>> aafCache = JCS.getInstance("aafCache"); + private static CacheAccess<String, String> appNameCache = JCS.getInstance("appNameCache"); + private static CacheAccess<String, Map<String, String>> musicValidateCache = JCS.getInstance("musicValidateCache"); + private static Map<String, Number> userAttempts = new HashMap<>(); + private static Map<String, Calendar> lastFailedTime = new HashMap<>(); + + public boolean isCacheRefreshNeeded() { + if (aafCache.get("initBlankMap") == null) + return true; + return false; + } + + public void initializeMusicCache() { + logger.info(EELFLoggerDelegate.applicationLogger,"Initializing Music Cache..."); + musicCache.put("isInitialized", "true"); + } + + public void initializeAafCache() throws MusicServiceException { + logger.info(EELFLoggerDelegate.applicationLogger,"Resetting and initializing AAF Cache..."); + + String query = "SELECT uuid, application_name, keyspace_name, username, password FROM admin.keyspace_master WHERE is_api = ? allow filtering"; + PreparedQueryObject pQuery = new PreparedQueryObject(); + pQuery.appendQueryString(query); + try { + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), false)); + } catch (Exception e1) { + logger.error(EELFLoggerDelegate.errorLogger, e1.getMessage(),AppMessages.CACHEERROR, ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + e1.printStackTrace(); + } + ResultSet rs = MusicCore.get(pQuery); + Iterator<Row> it = rs.iterator(); + Map<String, String> map = null; + while (it.hasNext()) { + Row row = it.next(); + String nameSpace = row.getString("keyspace_name"); + String userId = row.getString("username"); + String password = row.getString("password"); + String keySpace = row.getString("application_name"); + try { + userAttempts.put(nameSpace, 0); + AAFResponse responseObj = triggerAAF(nameSpace, userId, password); + if (responseObj.getNs().size() > 0) { + map = new HashMap<>(); + map.put(userId, password); + aafCache.put(nameSpace, map); + musicCache.put(keySpace, nameSpace); + logger.debug("Cronjob: Cache Updated with AAF response for namespace " + + nameSpace); + } + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.UNKNOWNERROR, ErrorSeverity.INFO, ErrorTypes.GENERALSERVICEERROR); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),"Something at AAF was changed for ns: " + nameSpace+" So not updating Cache for the namespace. "); + e.printStackTrace(); + } + } + + } + + @Override + public void run() { + logger.info(EELFLoggerDelegate.applicationLogger,"Scheduled task invoked. Refreshing Cache..."); + try { + initializeAafCache(); + } catch (MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.UNKNOWNERROR, ErrorSeverity.INFO, ErrorTypes.GENERALSERVICEERROR); + } + } + + public static boolean authenticateAAFUser(String nameSpace, String userId, String password, + String keySpace) throws Exception { + + if (aafCache.get(nameSpace) != null) { + if (keySpace != null && !musicCache.get(keySpace).equals(nameSpace)) { + logger.info(EELFLoggerDelegate.applicationLogger,"Create new application for the same namespace."); + } else if (aafCache.get(nameSpace).get(userId).equals(password)) { + logger.info(EELFLoggerDelegate.applicationLogger,"Authenticated with cache value.."); + // reset invalid attempts to 0 + userAttempts.put(nameSpace, 0); + return true; + } else { + // call AAF update cache with new password + if (userAttempts.get(nameSpace) == null) + userAttempts.put(nameSpace, 0); + if ((Integer) userAttempts.get(nameSpace) >= 3) { + logger.info(EELFLoggerDelegate.applicationLogger,"Reached max attempts. Checking if time out.."); + logger.info(EELFLoggerDelegate.applicationLogger,"Failed time: "+lastFailedTime.get(nameSpace).getTime()); + Calendar calendar = Calendar.getInstance(); + long delayTime = (calendar.getTimeInMillis()-lastFailedTime.get(nameSpace).getTimeInMillis()); + logger.info(EELFLoggerDelegate.applicationLogger,"Delayed time: "+delayTime); + if( delayTime > 120000) { + logger.info(EELFLoggerDelegate.applicationLogger,"Resetting failed attempt."); + userAttempts.put(nameSpace, 0); + } else { + logger.info(EELFLoggerDelegate.applicationLogger,"No more attempts allowed. Please wait for atleast 2 min."); + throw new Exception("No more attempts allowed. Please wait for atleast 2 min."); + } + } + logger.error(EELFLoggerDelegate.errorLogger,"",AppMessages.CACHEAUTHENTICATION,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); + logger.info(EELFLoggerDelegate.applicationLogger,"Check AAF again..."); + } + } + + AAFResponse responseObj = triggerAAF(nameSpace, userId, password); + if (responseObj.getNs().size() > 0) { + if (responseObj.getNs().get(0).getAdmin().contains(userId)) { + //Map<String, String> map = new HashMap<>(); + //map.put(userId, password); + //aafCache.put(nameSpace, map); + return true; + } + } + logger.info(EELFLoggerDelegate.applicationLogger,"Invalid user. Cache not updated"); + return false; + } + + private static AAFResponse triggerAAF(String nameSpace, String userId, String password) + throws Exception { + if (MusicUtil.getAafEndpointUrl() == null) { + logger.error(EELFLoggerDelegate.errorLogger,"",AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); + throw new Exception("AAF endpoint is not set. Please specify in the properties file."); + } + Client client = Client.create(); + // WebResource webResource = + // client.resource("https://aaftest.test.att.com:8095/proxy/authz/nss/"+nameSpace); + WebResource webResource = client.resource(MusicUtil.getAafEndpointUrl().concat(nameSpace)); + String plainCreds = userId + ":" + password; + byte[] plainCredsBytes = plainCreds.getBytes(); + byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes); + String base64Creds = new String(base64CredsBytes); + + ClientResponse response = webResource.accept(MediaType.APPLICATION_JSON) + .header("Authorization", "Basic " + base64Creds) + .header("content-type", "application/json").get(ClientResponse.class); + if (response.getStatus() != 200) { + if (userAttempts.get(nameSpace) == null) + userAttempts.put(nameSpace, 0); + if ((Integer) userAttempts.get(nameSpace) >= 2) { + lastFailedTime.put(nameSpace, Calendar.getInstance()); + userAttempts.put(nameSpace, ((Integer) userAttempts.get(nameSpace) + 1)); + throw new Exception( + "Reached max invalid attempts. Please contact admin and retry with valid credentials."); + } + userAttempts.put(nameSpace, ((Integer) userAttempts.get(nameSpace) + 1)); + throw new Exception( + "Unable to authenticate. Please check the AAF credentials against namespace."); + // TODO Allow for 2-3 times and forbid any attempt to trigger AAF with invalid values + // for specific time. + } + response.getHeaders().put(HttpHeaders.CONTENT_TYPE, + Arrays.asList(MediaType.APPLICATION_JSON)); + // AAFResponse output = response.getEntity(AAFResponse.class); + response.bufferEntity(); + String x = response.getEntity(String.class); + AAFResponse responseObj = new ObjectMapper().readValue(x, AAFResponse.class); + + return responseObj; + } + + public static void updateMusicCache(String keyspace, String nameSpace) { + logger.info(EELFLoggerDelegate.applicationLogger,"Updating musicCache for keyspace " + keyspace + " with nameSpace " + nameSpace); + musicCache.put(keyspace, nameSpace); + } + + public static void updateMusicValidateCache(String nameSpace, String userId, String password) { + logger.info(EELFLoggerDelegate.applicationLogger,"Updating musicCache for nameSpacce " + nameSpace + " with userId " + userId); + Map<String, String> map = new HashMap<>(); + map.put(userId, password); + musicValidateCache.put(nameSpace, map); + } + + public static void updateisAAFCache(String namespace, String isAAF) { + appNameCache.put(namespace, isAAF); + } + + public static String isAAFApplication(String namespace) throws MusicServiceException { + String isAAF = appNameCache.get(namespace); + if (isAAF == null) { + PreparedQueryObject pQuery = new PreparedQueryObject(); + pQuery.appendQueryString( + "SELECT is_aaf from admin.keyspace_master where application_name = '" + + namespace + "' allow filtering"); + Row rs = null; + try { + rs = MusicCore.get(pQuery).one(); + } catch(InvalidQueryException e) { + logger.error(EELFLoggerDelegate.errorLogger,"Exception admin keyspace not configured."+e.getMessage()); + throw new MusicServiceException("Please make sure admin.keyspace_master table is configured."); + } + try { + isAAF = String.valueOf(rs.getBool("is_aaf")); + if(isAAF != null) + appNameCache.put(namespace, isAAF); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), AppMessages.QUERYERROR,ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + e.printStackTrace(); + } + } + return isAAF; + } + + public static String getUuidFromMusicCache(String keyspace) throws MusicServiceException { + String uuid = null; + if (uuid == null) { + PreparedQueryObject pQuery = new PreparedQueryObject(); + pQuery.appendQueryString( + "SELECT uuid from admin.keyspace_master where keyspace_name = '" + + keyspace + "' allow filtering"); + Row rs = MusicCore.get(pQuery).one(); + try { + uuid = rs.getUUID("uuid").toString(); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,"Exception occured during uuid retrieval from DB."+e.getMessage()); + e.printStackTrace(); + } + } + return uuid; + } + + public static String getAppName(String keyspace) throws MusicServiceException { + String appName = null; + PreparedQueryObject pQuery = new PreparedQueryObject(); + pQuery.appendQueryString( + "SELECT application_name from admin.keyspace_master where keyspace_name = '" + + keyspace + "' allow filtering"); + Row rs = MusicCore.get(pQuery).one(); + try { + appName = rs.getString("application_name"); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), AppMessages.QUERYERROR, ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + e.printStackTrace(); + } + return appName; + } + + public static String generateUUID() { + String uuid = UUID.randomUUID().toString(); + logger.info(EELFLoggerDelegate.applicationLogger,"New AID generated: "+uuid); + return uuid; + } + + public static Map<String, Object> validateRequest(String nameSpace, String userId, + String password, String keyspace, String aid, String operation) { + Map<String, Object> resultMap = new HashMap<>(); + if (!"createKeySpace".equals(operation)) { + if (nameSpace == null) { + resultMap.put("Exception", "Application namespace is mandatory."); + } + } + return resultMap; + + } + + public static Map<String, Object> verifyOnboarding(String ns, String userId, String password) { + Map<String, Object> resultMap = new HashMap<>(); + if (ns == null || userId == null || password == null) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); + logger.error(EELFLoggerDelegate.errorLogger,"One or more required headers is missing. userId: "+userId+" :: password: "+password); + resultMap.put("Exception", + "One or more required headers appName(ns), userId, password is missing. Please check."); + return resultMap; + } + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString( + "select * from admin.keyspace_master where application_name = ? allow filtering"); + try { + queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), ns)); + } catch(Exception e) { + resultMap.put("Exception", + "Unable to process input data. Invalid input data type. Please check ns, userId and password values. "+e.getMessage()); + return resultMap; + } + Row rs = null; + try { + rs = MusicCore.get(queryObject).one(); + } catch (MusicServiceException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + resultMap.put("Exception", "Unable to process operation. Error is "+e.getMessage()); + return resultMap; + } catch (InvalidQueryException e) { + logger.error(EELFLoggerDelegate.errorLogger,"Exception admin keyspace not configured."+e.getMessage()); + resultMap.put("Exception", "Please make sure admin.keyspace_master table is configured."); + return resultMap; + } + if (rs == null) { + logger.error(EELFLoggerDelegate.errorLogger,"Application is not onboarded. Please contact admin."); + resultMap.put("Exception", "Application is not onboarded. Please contact admin."); + } else { + if(!(rs.getString("username").equals(userId)) || !(BCrypt.checkpw(password, rs.getString("password")))) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.AUTHENTICATIONERROR, ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); + logger.error(EELFLoggerDelegate.errorLogger,"Namespace, UserId and password doesn't match. namespace: "+ns+" and userId: "+userId); + resultMap.put("Exception", "Namespace, UserId and password doesn't match. namespace: "+ns+" and userId: "+userId); + return resultMap; + } + } + return resultMap; + } + + public static Map<String, Object> authenticateAIDUser(String nameSpace, String userId, String password, + String keyspace) { + Map<String, Object> resultMap = new HashMap<>(); + String pwd = null; + if((musicCache.get(keyspace) != null) && (musicValidateCache.get(nameSpace) != null) + && (musicValidateCache.get(nameSpace).containsKey(userId))) { + if(!musicCache.get(keyspace).equals(nameSpace)) { + resultMap.put("Exception", "Namespace and keyspace doesn't match"); + return resultMap; + } + if(!BCrypt.checkpw(password,musicValidateCache.get(nameSpace).get(userId))) { + resultMap.put("Exception", "Namespace, userId and password doesn't match"); + return resultMap; + } + return resultMap; + } + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString( + "select * from admin.keyspace_master where keyspace_name = ? allow filtering"); + try { + queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), keyspace)); + } catch (Exception e) { + e.printStackTrace(); + } + Row rs = null; + try { + rs = MusicCore.get(queryObject).one(); + } catch (MusicServiceException e) { + e.printStackTrace(); + resultMap.put("Exception", "Unable to process operation. Error is "+e.getMessage()); + return resultMap; + } + if(rs == null) { + resultMap.put("Exception", "Please make sure keyspace:"+keyspace+" exists."); + return resultMap; + } + else { + String user = rs.getString("username"); + pwd = rs.getString("password"); + String ns = rs.getString("application_name"); + if(!ns.equals(nameSpace)) { + resultMap.put("Exception", "Namespace and keyspace doesn't match"); + return resultMap; + } + if(!user.equals(userId)) { + resultMap.put("Exception", "Invalid userId :"+userId); + return resultMap; + } + if(!BCrypt.checkpw(password, pwd)) { + resultMap.put("Exception", "Invalid password"); + return resultMap; + } + } + CachingUtil.updateMusicCache(keyspace, nameSpace); + CachingUtil.updateMusicValidateCache(nameSpace, userId, pwd); + return resultMap; + } +} diff --git a/jar/src/main/java/org/onap/music/main/CronJobManager.java b/jar/src/main/java/org/onap/music/main/CronJobManager.java new file mode 100644 index 00000000..fb4a2ac3 --- /dev/null +++ b/jar/src/main/java/org/onap/music/main/CronJobManager.java @@ -0,0 +1,47 @@ +/* + * ============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.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; + +@WebListener +public class CronJobManager implements ServletContextListener { + + private ScheduledExecutorService scheduler; + + @Override + public void contextInitialized(ServletContextEvent event) { + scheduler = Executors.newSingleThreadScheduledExecutor(); + scheduler.scheduleAtFixedRate(new CachingUtil(), 0, 24, TimeUnit.HOURS); + } + + @Override + public void contextDestroyed(ServletContextEvent event) { + scheduler.shutdownNow(); + } + +} diff --git a/jar/src/main/java/org/onap/music/main/MusicCore.java b/jar/src/main/java/org/onap/music/main/MusicCore.java new file mode 100644 index 00000000..cad384a3 --- /dev/null +++ b/jar/src/main/java/org/onap/music/main/MusicCore.java @@ -0,0 +1,992 @@ +/* + * ============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.StringWriter; +import java.util.HashMap; +import java.util.Map; +import java.util.StringTokenizer; + +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.KeeperException.NoNodeException; +import org.onap.music.datastore.MusicDataStore; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.datastore.jsonobjects.JsonKeySpace; +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.MusicLockingException; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.lockingservice.MusicLockState; +import org.onap.music.lockingservice.MusicLockState.LockStatus; +import org.onap.music.lockingservice.MusicLockingService; + +import com.datastax.driver.core.ColumnDefinitions; +import com.datastax.driver.core.ColumnDefinitions.Definition; +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.TableMetadata; + +/** + * This class ..... + * + * + */ +public class MusicCore { + + public static MusicLockingService mLockHandle = null; + public static MusicDataStore mDstoreHandle = null; + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicCore.class); + + public static class Condition { + Map<String, Object> conditions; + PreparedQueryObject selectQueryForTheRow; + + public Condition(Map<String, Object> conditions, PreparedQueryObject selectQueryForTheRow) { + this.conditions = conditions; + this.selectQueryForTheRow = selectQueryForTheRow; + } + + public boolean testCondition() throws Exception { + // first generate the row + ResultSet results = quorumGet(selectQueryForTheRow); + Row row = results.one(); + return getDSHandle().doesRowSatisfyCondition(row, conditions); + } + } + + + public static MusicLockingService getLockingServiceHandle() throws MusicLockingException { + logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring lock store handle"); + long start = System.currentTimeMillis(); + + if (mLockHandle == null) { + try { + mLockHandle = new MusicLockingService(); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKHANDLE,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + throw new MusicLockingException("Failed to aquire Locl store handle " + e); + } + } + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire lock store handle:" + (end - start) + " ms"); + return mLockHandle; + } + + /** + * + * @param remoteIp + * @return + */ + public static MusicDataStore getDSHandle(String remoteIp) { + logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring data store handle"); + long start = System.currentTimeMillis(); + if (mDstoreHandle == null) { + try { + MusicUtil.loadProperties(); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "No properties file defined. Falling back to default."); + } + mDstoreHandle = new MusicDataStore(remoteIp); + } + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire data store handle:" + (end - start) + " ms"); + return mDstoreHandle; + } + + /** + * + * @return + * @throws MusicServiceException + */ + public static MusicDataStore getDSHandle() throws MusicServiceException { + logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring data store handle"); + long start = System.currentTimeMillis(); + if (mDstoreHandle == null) { + try { + MusicUtil.loadProperties(); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "No properties file defined. Falling back to default."); + } + // Quick Fix - Best to put this into every call to getDSHandle? + if (! MusicUtil.getMyCassaHost().equals("localhost") ) { + mDstoreHandle = new MusicDataStore(MusicUtil.getMyCassaHost()); + } else { + mDstoreHandle = new MusicDataStore(); + } + } + if(mDstoreHandle.getSession() == null) { + String message = "Connection to Cassandra has not been enstablished." + + " Please check connection properites and reboot."; + logger.info(EELFLoggerDelegate.applicationLogger, message); + throw new MusicServiceException(message); + } + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire data store handle:" + (end - start) + " ms"); + return mDstoreHandle; + } + + public static String createLockReference(String lockName) { + logger.info(EELFLoggerDelegate.applicationLogger,"Creating lock reference for lock name:" + lockName); + long start = System.currentTimeMillis(); + String lockId = null; + try { + lockId = getLockingServiceHandle().createLockId("/" + lockName); + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.CREATELOCK+lockName,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + + } + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to create lock reference:" + (end - start) + " ms"); + return lockId; + } + + /** + * + * @param key + * @return + */ + public static boolean isTableOrKeySpaceLock(String key) { + String[] splitString = key.split("\\."); + if (splitString.length > 2) + return false; + else + return true; + } + + /** + * + * @param key + * @return + */ + public static MusicLockState getMusicLockState(String key) { + long start = System.currentTimeMillis(); + try { + String[] splitString = key.split("\\."); + String keyspaceName = splitString[0]; + String tableName = splitString[1]; + String primaryKey = splitString[2]; + MusicLockState mls; + String lockName = keyspaceName + "." + tableName + "." + primaryKey; + mls = getLockingServiceHandle().getLockState(lockName); + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to get lock state:" + (end - start) + " ms"); + return mls; + } catch (NullPointerException | MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + } + return null; + } + + public static ReturnType acquireLockWithLease(String key, String lockId, long leasePeriod) { + try { + long start = System.currentTimeMillis(); + /* check if the current lock has exceeded its lease and if yes, release that lock */ + MusicLockState mls = getMusicLockState(key); + if (mls != null) { + if (mls.getLockStatus().equals(LockStatus.LOCKED)) { + logger.info(EELFLoggerDelegate.applicationLogger,"The current lock holder for " + key + " is " + mls.getLockHolder() + + ". Checking if it has exceeded lease"); + long currentLockPeriod = System.currentTimeMillis() - mls.getLeaseStartTime(); + long currentLeasePeriod = mls.getLeasePeriod(); + if (currentLockPeriod > currentLeasePeriod) { + logger.info(EELFLoggerDelegate.applicationLogger,"Lock period " + currentLockPeriod + + " has exceeded lease period " + currentLeasePeriod); + boolean voluntaryRelease = false; + String currentLockHolder = mls.getLockHolder(); + mls = releaseLock(currentLockHolder, voluntaryRelease); + } + } + } else + logger.error(EELFLoggerDelegate.errorLogger,key, AppMessages.INVALIDLOCK,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + + /* + * call the traditional acquire lock now and if the result returned is true, set the + * begin time-stamp and lease period + */ + if (acquireLock(key, lockId).getResult() == ResultType.SUCCESS) { + mls = getMusicLockState(key);// get latest state + if ( mls == null ) { + logger.info(EELFLoggerDelegate.applicationLogger,"Music Lock State is null"); + return new ReturnType(ResultType.FAILURE, "Could not acquire lock, Lock State is null"); + } + if (mls.getLeaseStartTime() == -1) {// set it again only if it is not set already + mls.setLeaseStartTime(System.currentTimeMillis()); + mls.setLeasePeriod(leasePeriod); + getLockingServiceHandle().setLockState(key, mls); + } + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire leased lock:" + (end - start) + " ms"); + return new ReturnType(ResultType.SUCCESS, "Accquired lock"); + } else { + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to fail to acquire leased lock:" + (end - start) + " ms"); + return new ReturnType(ResultType.FAILURE, "Could not acquire lock"); + } + } catch (Exception e) { + StringWriter sw = new StringWriter(); + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR506E] Failed to aquire lock ",ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + + String exceptionAsString = sw.toString(); + return new ReturnType(ResultType.FAILURE, + "Exception thrown in acquireLockWithLease:\n" + exceptionAsString); + } + } + + public static ReturnType acquireLock(String key, String lockId) throws MusicLockingException { + /* + * first check if I am on top. Since ids are not reusable there is no need to check + * lockStatus If the status is unlocked, then the above call will automatically return + * false. + */ + Boolean result = false; + try { + result = getLockingServiceHandle().isMyTurn(lockId); + } catch (MusicLockingException e2) { + logger.error(EELFLoggerDelegate.errorLogger,AppMessages.INVALIDLOCK + lockId + " " + e2); + throw new MusicLockingException(); + } + if (!result) { + logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Not your turn, someone else has the lock"); + try { + if (!getLockingServiceHandle().lockIdExists(lockId)) { + logger.info(EELFLoggerDelegate.applicationLogger, "In acquire lock: this lockId doesn't exist"); + return new ReturnType(ResultType.FAILURE, "Lockid doesn't exist"); + } + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK+lockId,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + throw new MusicLockingException(); + } + logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: returning failure"); + return new ReturnType(ResultType.FAILURE, "Not your turn, someone else has the lock"); + } + + + // this is for backward compatibility where locks could also be acquired on just + // keyspaces or tables. + if (isTableOrKeySpaceLock(key)) { + logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: A table or keyspace lock so no need to perform sync...so returning true"); + return new ReturnType(ResultType.SUCCESS, "A table or keyspace lock so no need to perform sync...so returning true"); + } + + // read the lock name corresponding to the key and if the status is locked or being locked, + // then return false + MusicLockState currentMls = null; + MusicLockState newMls = null; + try { + currentMls = getMusicLockState(key); + String currentLockHolder = currentMls.getLockHolder(); + if (lockId.equals(currentLockHolder)) { + logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: You already have the lock!"); + return new ReturnType(ResultType.SUCCESS, "You already have the lock!"); + } + } catch (NullPointerException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK+lockId,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + } + + // change status to "being locked". This state transition is necessary to ensure syncing + // before granting the lock + String lockHolder = null; + boolean needToSyncQuorum = false; + if (currentMls != null) + needToSyncQuorum = currentMls.isNeedToSyncQuorum(); + + + newMls = new MusicLockState(MusicLockState.LockStatus.BEING_LOCKED, lockHolder, + needToSyncQuorum); + try { + getLockingServiceHandle().setLockState(key, newMls); + } catch (MusicLockingException e1) { + logger.error(EELFLoggerDelegate.errorLogger,e1.getMessage(), AppMessages.LOCKSTATE+key,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + } + logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Set lock state to being_locked"); + + // do syncing if this was a forced lock release + if (needToSyncQuorum) { + logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Since there was a forcible release, need to sync quorum!"); + try { + syncQuorum(key); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,"Failed to set Lock state " + e); + } + } + + // change status to locked + lockHolder = lockId; + needToSyncQuorum = false; + newMls = new MusicLockState(MusicLockState.LockStatus.LOCKED, lockHolder, needToSyncQuorum); + try { + getLockingServiceHandle().setLockState(key, newMls); + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKSTATE+key,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + } + logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Set lock state to locked and assigned current lock ref " + + lockId + " as holder"); + + return new ReturnType(result?ResultType.SUCCESS:ResultType.FAILURE, "Set lock state to locked and assigned a lock holder"); + } + + + + /** + * + * @param keyspaceName + * @param kspObject + * @return + * @throws Exception + */ + public boolean createKeyspace(String keyspaceName, JsonKeySpace kspObject) throws Exception { + return true; + } + + + private static void syncQuorum(String key) throws Exception { + logger.info(EELFLoggerDelegate.applicationLogger,"Performing sync operation---"); + String[] splitString = key.split("\\."); + String keyspaceName = splitString[0]; + String tableName = splitString[1]; + String primaryKeyValue = splitString[2]; + PreparedQueryObject selectQuery = new PreparedQueryObject(); + PreparedQueryObject updateQuery = new PreparedQueryObject(); + + // get the primary key d + TableMetadata tableInfo = returnColumnMetadata(keyspaceName, tableName); + String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName();// we only support single + // primary key + DataType primaryKeyType = tableInfo.getPrimaryKey().get(0).getType(); + Object cqlFormattedPrimaryKeyValue = + MusicUtil.convertToActualDataType(primaryKeyType, primaryKeyValue); + + // get the row of data from a quorum + selectQuery.appendQueryString("SELECT * FROM " + keyspaceName + "." + tableName + " WHERE " + + primaryKeyName + "= ?" + ";"); + selectQuery.addValue(cqlFormattedPrimaryKeyValue); + ResultSet results = null; + try { + results = getDSHandle().executeCriticalGet(selectQuery); + // write it back to a quorum + Row row = results.one(); + ColumnDefinitions colInfo = row.getColumnDefinitions(); + int totalColumns = colInfo.size(); + int counter = 1; + StringBuilder fieldValueString = new StringBuilder(""); + for (Definition definition : colInfo) { + String colName = definition.getName(); + if (colName.equals(primaryKeyName)) + continue; + DataType colType = definition.getType(); + Object valueObj = getDSHandle().getColValue(row, colName, colType); + Object valueString = MusicUtil.convertToActualDataType(colType, valueObj); + fieldValueString.append(colName + " = ?"); + updateQuery.addValue(valueString); + if (counter != (totalColumns - 1)) + fieldValueString.append(","); + counter = counter + 1; + } + updateQuery.appendQueryString("UPDATE " + keyspaceName + "." + tableName + " SET " + + fieldValueString + " WHERE " + primaryKeyName + "= ? " + ";"); + updateQuery.addValue(cqlFormattedPrimaryKeyValue); + + getDSHandle().executePut(updateQuery, "critical"); + } catch (MusicServiceException | MusicQueryException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.QUERYERROR +""+updateQuery ,ErrorSeverity.MAJOR, ErrorTypes.QUERYERROR); + } + } + + + + + /** + * + * @param query + * @return ResultSet + */ + public static ResultSet quorumGet(PreparedQueryObject query) { + ResultSet results = null; + try { + results = getDSHandle().executeCriticalGet(query); + } catch (MusicServiceException | MusicQueryException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.MAJOR, ErrorTypes.GENERALSERVICEERROR); + + } + return results; + + } + + /** + * + * @param results + * @return + * @throws MusicServiceException + */ + public static Map<String, HashMap<String, Object>> marshallResults(ResultSet results) throws MusicServiceException { + return getDSHandle().marshalData(results); + } + + /** + * + * @param lockName + * @return + */ + public static String whoseTurnIsIt(String lockName) { + + try { + return getLockingServiceHandle().whoseTurnIsIt("/" + lockName) + ""; + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKINGERROR+lockName ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + } + return null; + + + } + + /** + * + * @param lockId + * @return + */ + public static String getLockNameFromId(String lockId) { + StringTokenizer st = new StringTokenizer(lockId); + return st.nextToken("$"); + } + + public static void destroyLockRef(String lockId) { + long start = System.currentTimeMillis(); + try { + getLockingServiceHandle().unlockAndDeleteId(lockId); + } catch (MusicLockingException | NoNodeException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.DESTROYLOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + } + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to destroy lock reference:" + (end - start) + " ms"); + } + + public static MusicLockState releaseLock(String lockId, boolean voluntaryRelease) { + long start = System.currentTimeMillis(); + try { + getLockingServiceHandle().unlockAndDeleteId(lockId); + } catch (MusicLockingException e1) { + logger.error(EELFLoggerDelegate.errorLogger,e1.getMessage(), AppMessages.RELEASELOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + } catch (KeeperException.NoNodeException nne) { + logger.error(EELFLoggerDelegate.errorLogger,"Failed to release Lock " + lockId + " " + nne); + MusicLockState mls = new MusicLockState("Lock doesn't exists. Release lock operation failed."); + return mls; + } + String lockName = getLockNameFromId(lockId); + MusicLockState mls; + String lockHolder = null; + if (voluntaryRelease) { + mls = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder); + logger.info(EELFLoggerDelegate.applicationLogger,"In unlock: lock voluntarily released for " + lockId); + } else { + boolean needToSyncQuorum = true; + mls = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder, + needToSyncQuorum); + logger.info(EELFLoggerDelegate.applicationLogger,"In unlock: lock forcibly released for " + lockId); + } + try { + getLockingServiceHandle().setLockState(lockName, mls); + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.RELEASELOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + } + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to release lock:" + (end - start) + " ms"); + return mls; + } + + public static void voluntaryReleaseLock(String lockId) throws MusicLockingException{ + try { + getLockingServiceHandle().unlockAndDeleteId(lockId); + } catch (KeeperException.NoNodeException e) { + // ??? No way + } + } + + /** + * + * @param lockName + * @throws MusicLockingException + */ + public static void deleteLock(String lockName) throws MusicLockingException { + long start = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Deleting lock for " + lockName); + try { + getLockingServiceHandle().deleteLock("/" + lockName); + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.DELTELOCK+lockName ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + throw new MusicLockingException(e.getMessage()); + } + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to delete lock:" + (end - start) + " ms"); + } + + + + /** + * + * @param keyspace + * @param tablename + * @return + * @throws MusicServiceException + */ + public static TableMetadata returnColumnMetadata(String keyspace, String tablename) throws MusicServiceException { + return getDSHandle().returnColumnMetadata(keyspace, tablename); + } + + + /** + * + * @param nodeName + */ + public static void pureZkCreate(String nodeName) { + try { + getLockingServiceHandle().getzkLockHandle().createNode(nodeName); + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + } + } + + /** + * + * @param nodeName + * @param data + */ + public static void pureZkWrite(String nodeName, byte[] data) { + long start = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Performing zookeeper write to " + nodeName); + try { + getLockingServiceHandle().getzkLockHandle().setNodeData(nodeName, data); + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + } + logger.info(EELFLoggerDelegate.applicationLogger,"Performed zookeeper write to " + nodeName); + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the actual zk put:" + (end - start) + " ms"); + } + + /** + * + * @param nodeName + * @return + */ + public static byte[] pureZkRead(String nodeName) { + long start = System.currentTimeMillis(); + byte[] data = null; + try { + data = getLockingServiceHandle().getzkLockHandle().getNodeData(nodeName); + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + } + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the actual zk put:" + (end - start) + " ms"); + return data; + } + + + + // Prepared Query Additions. + + /** + * + * @param keyspaceName + * @param tableName + * @param primaryKey + * @param queryObject + * @return ReturnType + * @throws MusicServiceException + */ + public static ReturnType eventualPut(PreparedQueryObject queryObject) { + boolean result = false; + try { + result = getDSHandle().executePut(queryObject, MusicUtil.EVENTUAL); + } catch (MusicServiceException | MusicQueryException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() + " " + ex.getCause() + " " + ex); + return new ReturnType(ResultType.FAILURE, ex.getMessage()); + } + if (result) { + return new ReturnType(ResultType.SUCCESS, "Success"); + } else { + return new ReturnType(ResultType.FAILURE, "Failure"); + } + } + + /** + * + * @param keyspaceName + * @param tableName + * @param primaryKey + * @param queryObject + * @param lockId + * @return + */ + public static ReturnType criticalPut(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject, String lockId, Condition conditionInfo) { + long start = System.currentTimeMillis(); + + try { + MusicLockState mls = getLockingServiceHandle() + .getLockState(keyspaceName + "." + tableName + "." + primaryKey); + if (mls.getLockHolder().equals(lockId) == true) { + if (conditionInfo != null) + try { + if (conditionInfo.testCondition() == false) + return new ReturnType(ResultType.FAILURE, + "Lock acquired but the condition is not true"); + } catch (Exception e) { + return new ReturnType(ResultType.FAILURE, + "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n" + + e.getMessage()); + } + getDSHandle().executePut(queryObject, MusicUtil.CRITICAL); + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the critical put:" + (end - start) + " ms"); + return new ReturnType(ResultType.SUCCESS, "Update performed"); + } else + return new ReturnType(ResultType.FAILURE, + "Cannot perform operation since you are the not the lock holder"); + } catch (MusicQueryException | MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); + return new ReturnType(ResultType.FAILURE, + "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n" + + e.getMessage()); + }catch(MusicLockingException ex){ + return new ReturnType(ResultType.FAILURE,ex.getMessage()); + } + + } + + /** + * + * @param queryObject + * @param consistency + * @return Boolean Indicates success or failure + * @throws MusicServiceException + * + * + */ + public static ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) throws MusicServiceException { + // 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 = getDSHandle().executePut(queryObject, consistency); + } catch (MusicQueryException | MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); + throw new MusicServiceException(ex.getMessage()); + } + return result?ResultType.SUCCESS:ResultType.FAILURE; + } + + /** + * This method performs DDL operation on cassandra. + * + * @param queryObject query object containing prepared query and values + * @return ResultSet + * @throws MusicServiceException + */ + public static ResultSet get(PreparedQueryObject queryObject) throws MusicServiceException { + ResultSet results = null; + try { + results = getDSHandle().executeEventualGet(queryObject); + } catch (MusicQueryException | MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); + throw new MusicServiceException(e.getMessage()); + } + return results; + } + + /** + * This method performs DDL operations on cassandra, if the the resource is available. Lock ID + * is used to check if the resource is free. + * + * @param keyspaceName name of the keyspace + * @param tableName name of the table + * @param primaryKey primary key value + * @param queryObject query object containing prepared query and values + * @param lockId lock ID to check if the resource is free to perform the operation. + * @return ResultSet + */ + public static ResultSet criticalGet(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject, String lockId) throws MusicServiceException { + ResultSet results = null; + try { + MusicLockState mls = getLockingServiceHandle() + .getLockState(keyspaceName + "." + tableName + "." + primaryKey); + if (mls.getLockHolder().equals(lockId)) { + results = getDSHandle().executeCriticalGet(queryObject); + } else + throw new MusicServiceException("YOU DO NOT HAVE THE LOCK"); + } catch (MusicQueryException | MusicServiceException | MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); + } + return results; + } + + /** + * This method performs DML operation on cassandra, when the lock of the dd is acquired. + * + * @param keyspaceName name of the keyspace + * @param tableName name of the table + * @param primaryKey primary key value + * @param queryObject query object containing prepared query and values + * @return ReturnType + * @throws MusicLockingException + */ + public static ReturnType atomicPut(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException { + + long start = System.currentTimeMillis(); + String key = keyspaceName + "." + tableName + "." + primaryKey; + String lockId = createLockReference(key); + long lockCreationTime = System.currentTimeMillis(); + ReturnType lockAcqResult = acquireLock(key, lockId); + long lockAcqTime = System.currentTimeMillis(); + if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) { + logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId); + ReturnType criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey, + queryObject, lockId, conditionInfo); + long criticalPutTime = System.currentTimeMillis(); + voluntaryReleaseLock(lockId); + long lockDeleteTime = System.currentTimeMillis(); + String timingInfo = "|lock creation time:" + (lockCreationTime - start) + + "|lock accquire time:" + (lockAcqTime - lockCreationTime) + + "|critical put time:" + (criticalPutTime - lockAcqTime) + + "|lock delete time:" + (lockDeleteTime - criticalPutTime) + "|"; + criticalPutResult.setTimingInfo(timingInfo); + return criticalPutResult; + } else { + logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId); + destroyLockRef(lockId); + return lockAcqResult; + } + } + + /** + * this function is mainly for the benchmarks to see the effect of lock deletion. + * + * @param keyspaceName + * @param tableName + * @param primaryKey + * @param queryObject + * @param conditionInfo + * @return + * @throws MusicLockingException + */ + public static ReturnType atomicPutWithDeleteLock(String keyspaceName, String tableName, + String primaryKey, PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException { + + long start = System.currentTimeMillis(); + String key = keyspaceName + "." + tableName + "." + primaryKey; + String lockId = createLockReference(key); + long lockCreationTime = System.currentTimeMillis(); + long leasePeriod = MusicUtil.getDefaultLockLeasePeriod(); + ReturnType lockAcqResult = acquireLock(key, lockId); + long lockAcqTime = System.currentTimeMillis(); + if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) { + logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId); + ReturnType criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey, + queryObject, lockId, conditionInfo); + long criticalPutTime = System.currentTimeMillis(); + deleteLock(key); + long lockDeleteTime = System.currentTimeMillis(); + String timingInfo = "|lock creation time:" + (lockCreationTime - start) + + "|lock accquire time:" + (lockAcqTime - lockCreationTime) + + "|critical put time:" + (criticalPutTime - lockAcqTime) + + "|lock delete time:" + (lockDeleteTime - criticalPutTime) + "|"; + criticalPutResult.setTimingInfo(timingInfo); + return criticalPutResult; + } else { + logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId); + deleteLock(key); + return lockAcqResult; + } + } + + + + + /** + * This method performs DDL operation on cassasndra, when the lock for the resource is acquired. + * + * @param keyspaceName name of the keyspace + * @param tableName name of the table + * @param primaryKey primary key value + * @param queryObject query object containing prepared query and values + * @return ResultSet + * @throws MusicServiceException + * @throws MusicLockingException + */ + public static ResultSet atomicGet(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException { + String key = keyspaceName + "." + tableName + "." + primaryKey; + String lockId = createLockReference(key); + long leasePeriod = MusicUtil.getDefaultLockLeasePeriod(); + ReturnType lockAcqResult = acquireLock(key, lockId); + if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) { + logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId); + ResultSet result = + criticalGet(keyspaceName, tableName, primaryKey, queryObject, lockId); + voluntaryReleaseLock(lockId); + return result; + } else { + destroyLockRef(lockId); + logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId); + return null; + } + } + + public static ResultSet atomicGetWithDeleteLock(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException { + String key = keyspaceName + "." + tableName + "." + primaryKey; + String lockId = createLockReference(key); + long leasePeriod = MusicUtil.getDefaultLockLeasePeriod(); + + ReturnType lockAcqResult = acquireLock(key, lockId); + + if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) { + logger.info(EELFLoggerDelegate.applicationLogger, "acquired lock with id " + lockId); + ResultSet result = criticalGet(keyspaceName, tableName, primaryKey, queryObject, lockId); + deleteLock(key); + return result; + } else { + deleteLock(key); + logger.info(EELFLoggerDelegate.applicationLogger, "unable to acquire lock, id " + lockId); + return null; + } + } + + + + /** + * authenticate user logic + * + * @param nameSpace + * @param userId + * @param password + * @param keyspace + * @param aid + * @param operation + * @return + * @throws Exception + */ + public static Map<String, Object> autheticateUser(String nameSpace, String userId, + String password, String keyspace, String aid, String operation) + throws Exception { + Map<String, Object> resultMap = new HashMap<>(); + String uuid = null; + resultMap = CachingUtil.validateRequest(nameSpace, userId, password, keyspace, aid, + operation); + if (!resultMap.isEmpty()) + return resultMap; + String isAAFApp = null; + try { + isAAFApp= CachingUtil.isAAFApplication(nameSpace); + } catch(MusicServiceException e) { + resultMap.put("Exception", e.getMessage()); + return resultMap; + } + if(isAAFApp == null) { + resultMap.put("Exception", "Namespace: "+nameSpace+" doesn't exist. Please make sure ns(appName)" + + " is correct and Application is onboarded."); + return resultMap; + } + boolean isAAF = Boolean.valueOf(isAAFApp); + if (userId == null || password == null) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); + logger.error(EELFLoggerDelegate.errorLogger,"One or more required headers is missing. userId: " + userId + + " :: password: " + password); + resultMap.put("Exception", + "UserId and Password are mandatory for the operation " + operation); + return resultMap; + } + if(!isAAF && !(operation.equals("createKeySpace"))) { + resultMap = CachingUtil.authenticateAIDUser(nameSpace, userId, password, keyspace); + if (!resultMap.isEmpty()) + return resultMap; + + } + if (isAAF && nameSpace != null && userId != null && password != null) { + boolean isValid = true; + try { + isValid = CachingUtil.authenticateAAFUser(nameSpace, userId, password, keyspace); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); + logger.error(EELFLoggerDelegate.errorLogger,"Got exception while AAF authentication for namespace " + nameSpace); + resultMap.put("Exception", e.getMessage()); + } + if (!isValid) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); + resultMap.put("Exception", "User not authenticated..."); + } + if (!resultMap.isEmpty()) + return resultMap; + + } + + if (operation.equals("createKeySpace")) { + logger.info(EELFLoggerDelegate.applicationLogger,"AID is not provided. Creating new UUID for keyspace."); + PreparedQueryObject pQuery = new PreparedQueryObject(); + pQuery.appendQueryString( + "select uuid from admin.keyspace_master where application_name=? and username=? and keyspace_name=? allow filtering"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), nameSpace)); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), + MusicUtil.DEFAULTKEYSPACENAME)); + + try { + Row rs = MusicCore.get(pQuery).one(); + uuid = rs.getUUID("uuid").toString(); + resultMap.put("uuid", "existing"); + } catch (Exception e) { + logger.info(EELFLoggerDelegate.applicationLogger,"No UUID found in DB. So creating new UUID."); + uuid = CachingUtil.generateUUID(); + resultMap.put("uuid", "new"); + } + resultMap.put("aid", uuid); + } + + return resultMap; + } + + /** + * @param lockName + * @return + */ + public static Map<String, Object> validateLock(String lockName) { + Map<String, Object> resultMap = new HashMap<>(); + String[] locks = lockName.split("\\."); + if(locks.length < 3) { + resultMap.put("Exception", "Invalid lock. Please make sure lock is of the type keyspaceName.tableName.primaryKey"); + return resultMap; + } + String keyspace= locks[0]; + if(keyspace.startsWith("$")) + keyspace = keyspace.substring(1); + resultMap.put("keyspace",keyspace); + return resultMap; + } +} diff --git a/jar/src/main/java/org/onap/music/main/MusicDigest.java b/jar/src/main/java/org/onap/music/main/MusicDigest.java new file mode 100644 index 00000000..893cb51f --- /dev/null +++ b/jar/src/main/java/org/onap/music/main/MusicDigest.java @@ -0,0 +1,78 @@ +/* + * ============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; + +/** + * + * + */ +public class MusicDigest { + private String evPutStatus; + private String vectorTs; + + /** + * @param evPutStatus + * @param vectorTs + */ + public MusicDigest(String evPutStatus, String vectorTs) { + this.evPutStatus = evPutStatus; + this.vectorTs = vectorTs; + } + + /** + * @return + */ + public String getEvPutStatus() { + return evPutStatus; + } + + /** + * @param evPutStatus + */ + public void setEvPutStatus(String evPutStatus) { + this.evPutStatus = evPutStatus; + } + + /** + * @return + */ + public String getVectorTs() { + return vectorTs; + } + + /** + * @param vectorTs + */ + public void setVectorTs(String vectorTs) { + this.vectorTs = vectorTs; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + public String toString() { + return vectorTs + "|" + evPutStatus; + } +} + diff --git a/jar/src/main/java/org/onap/music/main/MusicUtil.java b/jar/src/main/java/org/onap/music/main/MusicUtil.java new file mode 100755 index 00000000..f18570db --- /dev/null +++ b/jar/src/main/java/org/onap/music/main/MusicUtil.java @@ -0,0 +1,560 @@ +/* + * ============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.File; +import java.io.FileNotFoundException; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Scanner; +import java.util.UUID; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import com.datastax.driver.core.DataType; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + + +/** + * @author nelson24 + * + * Properties This will take Properties and load them into MusicUtil. + * This is a hack for now. Eventually it would bebest to do this in + * another way. + * + */ +public class MusicUtil { + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicUtil.class); + + public static final String ATOMIC = "atomic"; + public static final String EVENTUAL = "eventual"; + public static final String CRITICAL = "critical"; + public static final String ATOMICDELETELOCK = "atomic_delete_lock"; + public static final String DEFAULTKEYSPACENAME = "TBD"; + private static final String XLATESTVERSION = "X-latestVersion"; + private static final String XMINORVERSION = "X-minorVersion"; + private static final String XPATCHVERSION = "X-patchVersion"; + + private static final String LOCALHOST = "localhost"; + private static final String PROPERTIES_FILE = "/opt/app/music/etc/music.properties"; + + private static int myId = 0; + private static ArrayList<String> allIds = new ArrayList<>(); + private static String publicIp = ""; + private static ArrayList<String> allPublicIps = new ArrayList<>(); + private static String myZkHost = LOCALHOST; + private static String myCassaHost = LOCALHOST; + private static String defaultMusicIp = LOCALHOST; + private static boolean debug = true; + private static String version = "2.3.0"; + private static String musicRestIp = LOCALHOST; + private static String musicPropertiesFilePath = PROPERTIES_FILE; + private static long defaultLockLeasePeriod = 6000; + private static final String[] propKeys = new String[] { "zookeeper.host", "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" }; + + private static String cassName = "cassandra"; + private static String cassPwd = "cassandra"; + private static String aafEndpointUrl = null; + + private MusicUtil() { + throw new IllegalStateException("Utility Class"); + } + + + /** + * @return the cassName + */ + public static String getCassName() { + return cassName; + } + + /** + * @return the cassPwd + */ + public static String getCassPwd() { + return cassPwd; + } + + /** + * @return the aafEndpointUrl + */ + public static String getAafEndpointUrl() { + return aafEndpointUrl; + } + + /** + * + * @param aafEndpointUrl + */ + public static void setAafEndpointUrl(String aafEndpointUrl) { + MusicUtil.aafEndpointUrl = aafEndpointUrl; + } + + /** + * + * @return + */ + public static int getMyId() { + return myId; + } + + /** + * + * @param myId + */ + public static void setMyId(int myId) { + MusicUtil.myId = myId; + } + + /** + * + * @return + */ + public static List<String> getAllIds() { + return allIds; + } + + /** + * + * @param allIds + */ + public static void setAllIds(List<String> allIds) { + MusicUtil.allIds = (ArrayList<String>) allIds; + } + + /** + * + * @return + */ + public static String getPublicIp() { + return publicIp; + } + + /** + * + * @param publicIp + */ + public static void setPublicIp(String publicIp) { + MusicUtil.publicIp = publicIp; + } + + /** + * + * @return + */ + public static List<String> getAllPublicIps() { + return allPublicIps; + } + + /** + * + * @param allPublicIps + */ + public static void setAllPublicIps(List<String> allPublicIps) { + MusicUtil.allPublicIps = (ArrayList<String>) allPublicIps; + } + + /** + * Returns An array of property names that should be in the Properties + * files. + * + * @return + */ + public static String[] getPropkeys() { + return propKeys; + } + + /** + * Get MusicRestIp - default = localhost property file value - music.rest.ip + * + * @return + */ + public static String getMusicRestIp() { + return musicRestIp; + } + + /** + * Set MusicRestIp + * + * @param musicRestIp + */ + public static void setMusicRestIp(String musicRestIp) { + MusicUtil.musicRestIp = musicRestIp; + } + + /** + * Get MusicPropertiesFilePath - Default = /opt/music/music.properties + * property file value - music.properties + * + * @return + */ + public static String getMusicPropertiesFilePath() { + return musicPropertiesFilePath; + } + + /** + * Set MusicPropertiesFilePath + * + * @param musicPropertiesFilePath + */ + public static void setMusicPropertiesFilePath(String musicPropertiesFilePath) { + MusicUtil.musicPropertiesFilePath = musicPropertiesFilePath; + } + + /** + * Get DefaultLockLeasePeriod - Default = 6000 property file value - + * lock.lease.period + * + * @return + */ + public static long getDefaultLockLeasePeriod() { + return defaultLockLeasePeriod; + } + + /** + * Set DefaultLockLeasePeriod + * + * @param defaultLockLeasePeriod + */ + public static void setDefaultLockLeasePeriod(long defaultLockLeasePeriod) { + MusicUtil.defaultLockLeasePeriod = defaultLockLeasePeriod; + } + + /** + * Set Debug + * + * @param debug + */ + public static void setDebug(boolean debug) { + MusicUtil.debug = debug; + } + + /** + * Is Debug - Default = true property file value - debug + * + * @return + */ + public static boolean isDebug() { + return debug; + } + + /** + * Set Version + * + * @param version + */ + public static void setVersion(String version) { + MusicUtil.version = version; + } + + /** + * Return the version property file value - version + * + * @return + */ + public static String getVersion() { + return version; + } + + /** + * Get MyZkHost - Zookeeper Hostname - Default = localhost property file + * value - zookeeper.host + * + * @return + */ + public static String getMyZkHost() { + return myZkHost; + } + + /** + * Set MyZkHost - Zookeeper Hostname + * + * @param myZkHost + */ + public static void setMyZkHost(String myZkHost) { + MusicUtil.myZkHost = myZkHost; + } + + /** + * Get MyCassHost - Cassandra Hostname - Default = localhost property file + * value - cassandra.host + * + * @return + */ + public static String getMyCassaHost() { + return myCassaHost; + } + + /** + * Set MyCassHost - Cassandra Hostname + * + * @param myCassaHost + */ + 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; + } + + /** + * + * @return + */ + public static String getTestType() { + String testType = ""; + try { + Scanner fileScanner = new Scanner(new File("")); + testType = fileScanner.next();// ignore the my id line + String batchSize = fileScanner.next();// ignore the my public ip + // line + fileScanner.close(); + } catch (FileNotFoundException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + } + return testType; + + } + + /** + * + * @param time + */ + public static void sleep(long time) { + try { + Thread.sleep(time); + } catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + Thread.currentThread().interrupt(); + } + } + + /** + * Utility function to check if the query object is valid. + * + * @param withparams + * @param queryObject + * @return + */ + public static boolean isValidQueryObject(boolean withparams, PreparedQueryObject queryObject) { + if (withparams) { + int noOfValues = queryObject.getValues().size(); + int noOfParams = 0; + char[] temp = queryObject.getQuery().toCharArray(); + for (int i = 0; i < temp.length; i++) { + if (temp[i] == '?') + noOfParams++; + } + return (noOfValues == noOfParams); + } else { + return !queryObject.getQuery().isEmpty(); + } + + } + + public static void setCassName(String cassName) { + MusicUtil.cassName = cassName; + } + + public static void setCassPwd(String cassPwd) { + MusicUtil.cassPwd = cassPwd; + } + + public static String convertToCQLDataType(DataType type, Object valueObj) throws Exception { + + String value = ""; + switch (type.getName()) { + case UUID: + value = valueObj + ""; + break; + case TEXT: + case VARCHAR: + String valueString = valueObj + ""; + valueString = valueString.replace("'", "''"); + value = "'" + valueString + "'"; + break; + case MAP: { + Map<String, Object> otMap = (Map<String, Object>) valueObj; + value = "{" + jsonMaptoSqlString(otMap, ",") + "}"; + break; + } + default: + value = valueObj + ""; + break; + } + return value; + } + + /** + * + * @param colType + * @param valueObj + * @return + * @throws MusicTypeConversionException + * @throws Exception + */ + public static Object convertToActualDataType(DataType colType, Object valueObj) throws Exception { + String valueObjString = valueObj + ""; + switch (colType.getName()) { + case UUID: + return UUID.fromString(valueObjString); + case VARINT: + return BigInteger.valueOf(Long.parseLong(valueObjString)); + case BIGINT: + return Long.parseLong(valueObjString); + case INT: + return Integer.parseInt(valueObjString); + case FLOAT: + return Float.parseFloat(valueObjString); + case DOUBLE: + return Double.parseDouble(valueObjString); + case BOOLEAN: + return Boolean.parseBoolean(valueObjString); + case MAP: + return (Map<String, Object>) valueObj; + default: + return valueObjString; + } + } + + /** + * + * Utility function to parse json map into sql like string + * + * @param jMap + * @param lineDelimiter + * @return + */ + + public static String jsonMaptoSqlString(Map<String, Object> jMap, String lineDelimiter) throws Exception{ + StringBuilder sqlString = new StringBuilder(); + int counter = 0; + for (Map.Entry<String, Object> entry : jMap.entrySet()) { + Object ot = entry.getValue(); + String value = ot + ""; + if (ot instanceof String) { + value = "'" + value.replace("'", "''") + "'"; + } + sqlString.append("'" + entry.getKey() + "':" + value); + if (counter != jMap.size() - 1) + sqlString.append(lineDelimiter); + counter = counter + 1; + } + return sqlString.toString(); + } + + @SuppressWarnings("unused") + public static String buildVersion(String major, String minor, String patch) { + if (minor != null) { + major += "." + minor; + if (patch != null) { + major += "." + patch; + } + } + return major; + } + + /** + * Currently this will build a header with X-latestVersion, X-minorVersion and X-pathcVersion + * X-latestVerstion will be equal to the latest full version. + * X-minorVersion - will be equal to the latest minor version. + * X-pathVersion - will be equal to the latest patch version. + * Future plans will change this. + * @param response + * @param major + * @param minor + * @param patch + * @return + */ + public static ResponseBuilder buildVersionResponse(String major, String minor, String patch) { + ResponseBuilder response = Response.noContent(); + String versionIn = buildVersion(major,minor,patch); + String version = MusicUtil.getVersion(); + String[] verArray = version.split("\\.",3); + if ( minor != null ) { + response.header(XMINORVERSION,minor); + } else { + response.header(XMINORVERSION,verArray[1]); + } + if ( patch != null ) { + response.header(XPATCHVERSION,patch); + } else { + response.header(XPATCHVERSION,verArray[2]); + } + response.header(XLATESTVERSION,version); + logger.info(EELFLoggerDelegate.applicationLogger,"Version In:" + versionIn); + return response; + } + + + public static void loadProperties() throws Exception { + Properties prop = new Properties(); + InputStream input = null; + try { + // load the properties file + input = MusicUtil.class.getClassLoader().getResourceAsStream("music.properties"); + prop.load(input); + } catch (Exception ex) { + logger.error(EELFLoggerDelegate.errorLogger, "Unable to find properties file."); + throw new Exception(); + } finally { + if (input != null) { + try { + input.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + // get the property value and return it + MusicUtil.setMyCassaHost(prop.getProperty("cassandra.host")); + String zkHosts = prop.getProperty("zookeeper.host"); + MusicUtil.setMyZkHost(zkHosts); + MusicUtil.setCassName(prop.getProperty("cassandra.user")); + MusicUtil.setCassPwd(prop.getProperty("cassandra.password")); + } + +} diff --git a/jar/src/main/java/org/onap/music/main/PropertiesListener.java b/jar/src/main/java/org/onap/music/main/PropertiesListener.java new file mode 100755 index 00000000..afd35387 --- /dev/null +++ b/jar/src/main/java/org/onap/music/main/PropertiesListener.java @@ -0,0 +1,151 @@ +/* + * ============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.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Properties; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; +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; + +@WebListener +public class PropertiesListener implements ServletContextListener { + private Properties prop; + + private static EELFLoggerDelegate logger = + EELFLoggerDelegate.getLogger(PropertiesListener.class); + + @Override + public void contextInitialized(ServletContextEvent servletContextEvent) { + prop = new Properties(); + Properties projectProp = new Properties(); + URL resource = getClass().getResource("/"); + String musicPropertiesFilePath = resource.getPath().replace("WEB-INF/classes/", + "WEB-INF/classes/project.properties"); + + // Open the file + try { + InputStream musicProps = null; + projectProp.load(new FileInputStream(musicPropertiesFilePath)); + if (projectProp.containsKey("music.properties")) { + musicProps = new FileInputStream(projectProp.getProperty("music.properties")); + } else { + musicProps = new FileInputStream(MusicUtil.getMusicPropertiesFilePath()); + } + prop.load(musicProps); + musicProps.close(); + prop.putAll(projectProp); + String[] propKeys = MusicUtil.getPropkeys(); + for (int k = 0; k < propKeys.length; k++) { + String key = propKeys[k]; + if (prop.containsKey(key) && prop.get(key) != null) { + logger.info(key + " : " + prop.getProperty(key)); + switch (key) { + case "zookeeper.host": + MusicUtil.setMyZkHost(prop.getProperty(key)); + break; + case "cassandra.host": + MusicUtil.setMyCassaHost(prop.getProperty(key)); + break; + case "music.ip": + MusicUtil.setDefaultMusicIp(prop.getProperty(key)); + break; + case "debug": + MusicUtil.setDebug(Boolean + .getBoolean(prop.getProperty(key).toLowerCase())); + break; + case "version": + MusicUtil.setVersion(prop.getProperty(key)); + break; + case "music.rest.ip": + MusicUtil.setMusicRestIp(prop.getProperty(key)); + break; + case "music.properties": + MusicUtil.setMusicPropertiesFilePath(prop.getProperty(key)); + break; + case "lock.lease.period": + MusicUtil.setDefaultLockLeasePeriod( + Long.parseLong(prop.getProperty(key))); + break; + case "my.id": + MusicUtil.setMyId(Integer.parseInt(prop.getProperty(key))); + break; + case "all.ids": + String[] ids = prop.getProperty(key).split(":"); + MusicUtil.setAllIds(new ArrayList<String>(Arrays.asList(ids))); + break; + case "public.ip": + MusicUtil.setPublicIp(prop.getProperty(key)); + break; + case "all.public.ips": + String[] ips = prop.getProperty(key).split(":"); + if (ips.length == 1) { + // Future use + } else if (ips.length > 1) { + MusicUtil.setAllPublicIps( + new ArrayList<String>(Arrays.asList(ips))); + } + break; + case "cassandra.user": + MusicUtil.setCassName(prop.getProperty(key)); + break; + case "cassandra.password": + MusicUtil.setCassPwd(prop.getProperty(key)); + break; + case "aaf.endpoint.url": + MusicUtil.setAafEndpointUrl(prop.getProperty(key)); + break; + default: + logger.error(EELFLoggerDelegate.errorLogger, + "No case found for " + key); + } + } + } + } catch (IOException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.IOERROR ,ErrorSeverity.CRITICAL, ErrorTypes.CONNECTIONERROR); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + } + + logger.info(EELFLoggerDelegate.applicationLogger, + "Starting MUSIC " + MusicUtil.getVersion() + " on node with id " + + MusicUtil.getMyId() + " and public ip " + + MusicUtil.getPublicIp() + "..."); + logger.info(EELFLoggerDelegate.applicationLogger, + "List of all MUSIC ids:" + MusicUtil.getAllIds().toString()); + logger.info(EELFLoggerDelegate.applicationLogger, + "List of all MUSIC public ips:" + MusicUtil.getAllPublicIps().toString()); + } + + @Override + public void contextDestroyed(ServletContextEvent servletContextEvent) { + prop = null; + } +} diff --git a/jar/src/main/java/org/onap/music/main/ResultType.java b/jar/src/main/java/org/onap/music/main/ResultType.java new file mode 100644 index 00000000..61ba0295 --- /dev/null +++ b/jar/src/main/java/org/onap/music/main/ResultType.java @@ -0,0 +1,41 @@ +/* + * ============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; + +public enum ResultType { + SUCCESS("Success"), FAILURE("Failure"), + SYNTAXERROR("SyntaxError"), EXCEPTION("Exception"), + BODYMISSING("Incomplete Request body. Please correct your input request and retry."); + + private String result; + + ResultType(String result) { + this.result = result; + } + + public String getResult() { + return result; + } + +} + + diff --git a/jar/src/main/java/org/onap/music/main/ReturnType.java b/jar/src/main/java/org/onap/music/main/ReturnType.java new file mode 100644 index 00000000..1453a1bf --- /dev/null +++ b/jar/src/main/java/org/onap/music/main/ReturnType.java @@ -0,0 +1,74 @@ +/* + * ============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.util.HashMap; +import java.util.Map; + +public class ReturnType { + private ResultType result; + private String message; + + public ReturnType(ResultType result, String message) { + super(); + this.result = result; + this.message = message; + } + + public String getTimingInfo() { + return timingInfo; + } + + public void setTimingInfo(String timingInfo) { + this.timingInfo = timingInfo; + } + + private String timingInfo; + + public ResultType getResult() { + return result; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String toJson() { + return "{ \"result\":\"" + result.getResult() + "\", \"message\":\"" + message + "\"}"; + } + + public String toString() { + return result + " | " + message; + } + + public Map<String, Object> toMap() { + Map<String, Object> newMap = new HashMap<>(); + newMap.put("result", result.getResult()); + newMap.put("message", message); + return newMap; + } + +} diff --git a/jar/src/main/java/org/onap/music/response/jsonobjects/JsonResponse.java b/jar/src/main/java/org/onap/music/response/jsonobjects/JsonResponse.java new file mode 100644 index 00000000..a406afce --- /dev/null +++ b/jar/src/main/java/org/onap/music/response/jsonobjects/JsonResponse.java @@ -0,0 +1,265 @@ +/* + * ============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.response.jsonobjects; + +import java.util.HashMap; +import java.util.Map; + +import org.onap.music.lockingservice.MusicLockState.LockStatus; +import org.onap.music.main.ResultType; +import org.powermock.core.spi.testresult.Result; + +import com.datastax.driver.core.ColumnDefinitions; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.ColumnDefinitions.Definition; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel(value = "JsonResponse", description = "General Response JSON") +public class JsonResponse { + + /* Status is required */ + private ResultType status; + + /* Standard informational fields */ + private String error; + private String message; + + /* versioning */ + private String musicVersion; + + /* Data Fields */ + private Map<String, HashMap<String, Object>> dataResult; + + /* Locking fields */ + private String lock; + private LockStatus lockStatus; + private String lockHolder; + private String lockLease; + + + /** + * Create a JSONLock Response + * Use setters to provide more information as in + * JsonLockResponse(ResultType.SUCCESS).setMessage("We did it").setLock(mylockname) + * @param status + */ + public JsonResponse(ResultType status) { + this.status = status; + } + + /** + * + * @return + */ + @ApiModelProperty(value = "Overall status of the response.", + allowableValues = "Success,Failure") + public ResultType getStatus() { + return status; + } + + /** + * + * @param status + */ + public JsonResponse setStatus(ResultType status) { + this.status = status; + return this; + } + + /** + * + * @return the error + */ + @ApiModelProperty(value = "Error value") + public String getError() { + return error; + } + + /** + * + * @param error + */ + public JsonResponse setError(String error) { + this.error = error; + return this; + } + + /** + * + * @return the message + */ + @ApiModelProperty(value = "Message value") + public String getMessage() { + return message; + } + + /** + * + * @param message + */ + public JsonResponse setMessage(String message) { + this.message = message; + return this; + } + + + /** + * + * @return the music version + */ + public String getMusicVersion() { + return this.musicVersion; + } + + /** + * + * @param version of music + * @return + */ + public JsonResponse setMusicVersion(String version) { + this.musicVersion = version; + return this; + } + + public Map<String, HashMap<String, Object>> getDataResult() { + return this.dataResult; + } + + public JsonResponse setDataResult(Map<String, HashMap<String, Object>> map) { + this.dataResult = map; + return this; + } + + /** + * + * @return + */ + public String getLock() { + return lock; + } + + /** + * + * @param lock + */ + public JsonResponse setLock(String lock) { + this.lock = lock; + return this; + } + + /** + * + * @return the lockStatus + */ + @ApiModelProperty(value = "Status of the lock") + public LockStatus getLockStatus() { + return lockStatus; + } + + /** + * + * @param lockStatus + */ + public JsonResponse setLockStatus(LockStatus lockStatus) { + this.lockStatus = lockStatus; + return this; + } + + /** + * + * + * @return the lockHolder + */ + @ApiModelProperty(value = "Holder of the Lock") + public String getLockHolder() { + return lockHolder; + } + + /** + * + * @param lockHolder + */ + public JsonResponse setLockHolder(String lockHolder) { + this.lockHolder = lockHolder; + return this; + } + + + + /** + * @return the lockLease + */ + public String getLockLease() { + return lockLease; + } + + /** + * @param lockLease the lockLease to set + */ + public JsonResponse setLockLease(String lockLease) { + this.lockLease = lockLease; + return this; + } + + /** + * Convert to Map + * + * @return + */ + public Map<String, Object> toMap() { + Map<String, Object> fullMap = new HashMap<>(); + fullMap.put("status", status); + if (error!=null) {fullMap.put("error", error);} + if (message!=null) {fullMap.put("message", message);} + + if (musicVersion!=null) {fullMap.put("version", musicVersion);} + + if (dataResult!=null) { + fullMap.put("result", dataResult); + } + + if (lock!=null) { + Map<String, Object> lockMap = new HashMap<>(); + if (lock!=null) {lockMap.put("lock", lock);} + if (lockStatus!=null) {lockMap.put("lock-status", lockStatus);} + if (lockHolder!=null) {lockMap.put("lock-holder", lockHolder);} + if (lockLease!=null) {lockMap.put("lock-lease", lockLease);} + fullMap.put("lock", lockMap); + } + + return fullMap; + } + + /** + * Convert to String + */ + @Override + public String toString() { + return "JsonLockResponse [status=" + status + ", error=" + error + ", message=" + message + + ", lock=" + lock + ", lockStatus=" + lockStatus + ", lockHolder=" + + lockHolder + "]"; + } + +} diff --git a/jar/src/main/java/org/onap/music/rest/RestMusicAdminAPI.java b/jar/src/main/java/org/onap/music/rest/RestMusicAdminAPI.java new file mode 100755 index 00000000..e7c7fb6c --- /dev/null +++ b/jar/src/main/java/org/onap/music/rest/RestMusicAdminAPI.java @@ -0,0 +1,372 @@ +/* + * ============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.rest; + + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.core.Response.Status; + +import org.mindrot.jbcrypt.BCrypt; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.datastore.jsonobjects.JsonOnboard; +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.main.CachingUtil; +import org.onap.music.main.MusicCore; +import org.onap.music.main.MusicUtil; +import org.onap.music.main.ResultType; +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +@Path("/v2/admin") +// @Path("/v{version: [0-9]+}/admin") +// @Path("/admin") +@Api(value = "Admin Api", hidden = true) +public class RestMusicAdminAPI { + private static EELFLoggerDelegate logger = + EELFLoggerDelegate.getLogger(RestMusicAdminAPI.class); + + /* + * API to onboard an application with MUSIC. This is the mandatory first step. + * + */ + @POST + @Path("/onboardAppWithMusic") + @ApiOperation(value = "Onboard application", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response onboardAppWithMusic(JsonOnboard jsonObj) throws Exception { + ResponseBuilder response = + Response.noContent().header("X-latestVersion", MusicUtil.getVersion()); + Map<String, Object> resultMap = new HashMap<>(); + String appName = jsonObj.getAppname(); + String userId = jsonObj.getUserId(); + String isAAF = jsonObj.getIsAAF(); + String password = jsonObj.getPassword(); + if (appName == null || userId == null || isAAF == null || password == null) { + logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGINFO, + ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR); + resultMap.put("Exception", + "Unauthorized: Please check the request parameters. Some of the required values appName(ns), userId, password, isAAF are missing."); + return Response.status(Status.UNAUTHORIZED).entity(resultMap).build(); + } + + PreparedQueryObject pQuery = new PreparedQueryObject(); + pQuery.appendQueryString( + "select uuid from admin.keyspace_master where application_name = ? allow filtering"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); + ResultSet rs = MusicCore.get(pQuery); + if (!rs.all().isEmpty()) { + resultMap.put("Exception", "Application " + appName + + " has already been onboarded. Please contact admin."); + return Response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + + pQuery = new PreparedQueryObject(); + String uuid = CachingUtil.generateUUID(); + pQuery.appendQueryString( + "INSERT INTO admin.keyspace_master (uuid, keyspace_name, application_name, is_api, " + + "password, username, is_aaf) VALUES (?,?,?,?,?,?,?)"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), + MusicUtil.DEFAULTKEYSPACENAME)); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "True")); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), BCrypt.hashpw(password, BCrypt.gensalt()))); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF)); + + String returnStr = MusicCore.eventualPut(pQuery).toString(); + if (returnStr.contains("Failure")) { + resultMap.put("Exception", + "Oops. Something wrong with onboarding process. Please retry later or contact admin."); + return Response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + CachingUtil.updateisAAFCache(appName, isAAF); + resultMap.put("Success", "Your application " + appName + " has been onboarded with MUSIC."); + resultMap.put("Generated AID", uuid); + return Response.status(Status.OK).entity(resultMap).build(); + } + + + @POST + @Path("/search") + @ApiOperation(value = "Search Onboard application", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response getOnboardedInfoSearch(JsonOnboard jsonObj) throws Exception { + Map<String, Object> resultMap = new HashMap<>(); + ResponseBuilder response = + Response.noContent().header("X-latestVersion", MusicUtil.getVersion()); + String appName = jsonObj.getAppname(); + String uuid = jsonObj.getAid(); + String isAAF = jsonObj.getIsAAF(); + + if (appName == null && uuid == null && isAAF == null) { + logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGINFO, + ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR); + resultMap.put("Exception", + "Unauthorized: Please check the request parameters. Enter atleast one of the following parameters: appName(ns), aid, isAAF."); + return Response.status(Status.UNAUTHORIZED).entity(resultMap).build(); + } + + PreparedQueryObject pQuery = new PreparedQueryObject(); + String cql = "select uuid, keyspace_name from admin.keyspace_master where "; + if (appName != null) + cql = cql + "application_name = ? AND "; + if (uuid != null) + cql = cql + "uuid = ? AND "; + if (isAAF != null) + cql = cql + "is_aaf = ?"; + + if (cql.endsWith("AND ")) + cql = cql.trim().substring(0, cql.length() - 4); + System.out.println("Query is: " + cql); + cql = cql + " allow filtering"; + System.out.println("Get OnboardingInfo CQL: " + cql); + pQuery.appendQueryString(cql); + if (appName != null) + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); + if (uuid != null) + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); + if (isAAF != null) + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), + Boolean.parseBoolean(isAAF))); + ResultSet rs = MusicCore.get(pQuery); + Iterator<Row> it = rs.iterator(); + while (it.hasNext()) { + Row row = (Row) it.next(); + resultMap.put(row.getUUID("uuid").toString(), row.getString("keyspace_name")); + } + if (resultMap.isEmpty()) { + if (uuid != null) { + resultMap.put("Exception", + "Please make sure Aid is correct and application is onboarded."); + return Response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } else { + resultMap.put("Exception", + "Application is not onboarded. Please make sure all the information is correct."); + return Response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + } + return Response.status(Status.OK).entity(resultMap).build(); + } + + + @DELETE + @Path("/onboardAppWithMusic") + @ApiOperation(value = "Delete Onboard application", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response deleteOnboardApp(JsonOnboard jsonObj) throws Exception { + Map<String, Object> resultMap = new HashMap<>(); + ResponseBuilder response = + Response.noContent().header("X-latestVersion", MusicUtil.getVersion()); + String appName = jsonObj.getAppname(); + String aid = jsonObj.getAid(); + PreparedQueryObject pQuery = new PreparedQueryObject(); + String consistency = MusicUtil.EVENTUAL;; + if (appName == null && aid == null) { + logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGINFO, + ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); + resultMap.put("Exception", "Please make sure either appName(ns) or Aid is present"); + return Response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + if (aid != null) { + pQuery.appendQueryString( + "SELECT keyspace_name FROM admin.keyspace_master WHERE uuid = ?"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), + UUID.fromString(aid))); + Row row = MusicCore.get(pQuery).one(); + if (row != null) { + String ks = row.getString("keyspace_name"); + if (!ks.equals(MusicUtil.DEFAULTKEYSPACENAME)) { + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString("DROP KEYSPACE IF EXISTS " + ks + ";"); + MusicCore.nonKeyRelatedPut(queryObject, consistency); + } + } + pQuery = new PreparedQueryObject(); + pQuery.appendQueryString("delete from admin.keyspace_master where uuid = ? IF EXISTS"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), + UUID.fromString(aid))); + ResultType result = MusicCore.nonKeyRelatedPut(pQuery, consistency); + if (result == ResultType.SUCCESS) { + resultMap.put("Success", "Your application has been deleted successfully"); + } else { + resultMap.put("Exception", + "Oops. Something went wrong. Please make sure Aid is correct or Application is onboarded"); + logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.INCORRECTDATA, + ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); + return Response.status(Status.BAD_REQUEST).entity(resultMap).build(); + + } + return Response.status(Status.OK).entity(resultMap).build(); + } + + pQuery.appendQueryString( + "select uuid from admin.keyspace_master where application_name = ? allow filtering"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); + ResultSet rs = MusicCore.get(pQuery); + List<Row> rows = rs.all(); + String uuid = null; + if (rows.size() == 0) { + resultMap.put("Exception", + "Application not found. Please make sure Application exists."); + logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.INCORRECTDATA, + ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); + return Response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } else if (rows.size() == 1) { + uuid = rows.get(0).getUUID("uuid").toString(); + pQuery = new PreparedQueryObject(); + pQuery.appendQueryString( + "SELECT keyspace_name FROM admin.keyspace_master WHERE uuid = ?"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), + UUID.fromString(uuid))); + Row row = MusicCore.get(pQuery).one(); + String ks = row.getString("keyspace_name"); + if (!ks.equals(MusicUtil.DEFAULTKEYSPACENAME)) { + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString("DROP KEYSPACE " + ks + ";"); + MusicCore.nonKeyRelatedPut(queryObject, consistency); + } + + pQuery = new PreparedQueryObject(); + pQuery.appendQueryString("delete from admin.keyspace_master where uuid = ?"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), + UUID.fromString(uuid))); + MusicCore.eventualPut(pQuery); + resultMap.put("Success", "Your application " + appName + " has been deleted."); + return Response.status(Status.OK).entity(resultMap).build(); + } else { + resultMap.put("Failure", + "More than one Aid exists for this application, so please provide Aid."); + logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MULTIPLERECORDS, + ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); + return Response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + } + + + @PUT + @Path("/onboardAppWithMusic") + @ApiOperation(value = "Update Onboard application", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response updateOnboardApp(JsonOnboard jsonObj) throws Exception { + Map<String, Object> resultMap = new HashMap<>(); + ResponseBuilder response = + Response.noContent().header("X-latestVersion", MusicUtil.getVersion()); + String aid = jsonObj.getAid(); + String appName = jsonObj.getAppname(); + String userId = jsonObj.getUserId(); + String isAAF = jsonObj.getIsAAF(); + String password = jsonObj.getPassword(); + String consistency = "eventual"; + PreparedQueryObject pQuery; + + if (aid == null) { + resultMap.put("Exception", "Please make sure Aid is present"); + logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGDATA, + ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); + return Response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + + if (appName == null && userId == null && password == null && isAAF == null) { + resultMap.put("Exception", + "No parameters found to update. Please update atleast one parameter."); + logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGDATA, + ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); + return Response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + + if (appName != null) { + pQuery = new PreparedQueryObject(); + pQuery.appendQueryString( + "select uuid from admin.keyspace_master where application_name = ? allow filtering"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); + ResultSet rs = MusicCore.get(pQuery); + if (!rs.all().isEmpty()) { + resultMap.put("Exception", "Application " + appName + + " has already been onboarded. Please contact admin."); + logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.ALREADYEXIST, + ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); + return Response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + } + + pQuery = new PreparedQueryObject(); + StringBuilder preCql = new StringBuilder("UPDATE admin.keyspace_master SET "); + if (appName != null) + preCql.append(" application_name = ?,"); + if (userId != null) + preCql.append(" username = ?,"); + if (password != null) + preCql.append(" password = ?,"); + if (isAAF != null) + preCql.append(" is_aaf = ?,"); + preCql.deleteCharAt(preCql.length() - 1); + preCql.append(" WHERE uuid = ? IF EXISTS"); + pQuery.appendQueryString(preCql.toString()); + if (appName != null) + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); + if (userId != null) + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); + if (password != null) + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), BCrypt.hashpw(password, BCrypt.gensalt()))); + if (isAAF != null) + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF)); + + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), UUID.fromString(aid))); + ResultType result = MusicCore.nonKeyRelatedPut(pQuery, consistency); + + if (result == ResultType.SUCCESS) { + resultMap.put("Success", "Your application has been updated successfully"); + } else { + resultMap.put("Exception", + "Oops. Something went wrong. Please make sure Aid is correct and application is onboarded"); + logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.INCORRECTDATA, + ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); + return Response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + + return Response.status(Status.OK).entity(resultMap).build(); + } +} diff --git a/jar/src/main/java/org/onap/music/rest/RestMusicBmAPI.java b/jar/src/main/java/org/onap/music/rest/RestMusicBmAPI.java new file mode 100644 index 00000000..55eb47f2 --- /dev/null +++ b/jar/src/main/java/org/onap/music/rest/RestMusicBmAPI.java @@ -0,0 +1,307 @@ +/* + * ============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.rest; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.UriInfo; +import org.onap.music.datastore.jsonobjects.JsonInsert; +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.main.MusicCore; +import org.onap.music.main.MusicUtil; +import org.onap.music.main.ResultType; +import org.onap.music.main.ReturnType; +import org.onap.music.datastore.PreparedQueryObject; +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.TableMetadata; +import io.swagger.annotations.Api; +//import io.swagger.annotations.ApiOperation; +//import io.swagger.annotations.ApiParam; + +/* + * These are functions created purely for benchmarking purposes. Commented out Swagger - This should + * be undocumented API + * + */ +@Path("/v{version: [0-9]+}/benchmarks/") +@Api(value = "Benchmark API", hidden = true) +public class RestMusicBmAPI { + + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicBmAPI.class); + + // pure zk calls... + + /** + * + * @param nodeName + * @throws Exception + */ + @POST + @Path("/purezk/{name}") + @Consumes(MediaType.APPLICATION_JSON) + public void pureZkCreate(@PathParam("name") String nodeName) throws Exception { + MusicCore.pureZkCreate("/" + nodeName); + } + + + /** + * + * @param insObj + * @param nodeName + * @throws Exception + */ + @PUT + @Path("/purezk/{name}") + @Consumes(MediaType.APPLICATION_JSON) + public void pureZkUpdate(JsonInsert insObj, @PathParam("name") String nodeName) + throws Exception { + logger.info(EELFLoggerDelegate.applicationLogger,"--------------Zk normal update-------------------------"); + long start = System.currentTimeMillis(); + MusicCore.pureZkWrite(nodeName, insObj.serialize()); + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Total time taken for Zk normal update:" + (end - start) + " ms"); + } + + /** + * + * @param nodeName + * @return + * @throws Exception + */ + @GET + @Path("/purezk/{name}") + @Consumes(MediaType.TEXT_PLAIN) + public byte[] pureZkGet(@PathParam("name") String nodeName) throws Exception { + return MusicCore.pureZkRead(nodeName); + } + + /** + * + * @param insObj + * @param lockName + * @param nodeName + * @throws Exception + */ + @PUT + @Path("/purezk/atomic/{lockname}/{name}") + @Consumes(MediaType.APPLICATION_JSON) + public void pureZkAtomicPut(JsonInsert updateObj, @PathParam("lockname") String lockname, + @PathParam("name") String nodeName) throws Exception { + long startTime = System.currentTimeMillis(); + String operationId = UUID.randomUUID().toString();// just for debugging purposes. + String consistency = updateObj.getConsistencyInfo().get("type"); + + logger.info(EELFLoggerDelegate.applicationLogger,"--------------Zookeeper " + consistency + " update-" + operationId + + "-------------------------"); + + byte[] data = updateObj.serialize(); + long jsonParseCompletionTime = System.currentTimeMillis(); + + String lockId = MusicCore.createLockReference(lockname); + + long lockCreationTime = System.currentTimeMillis(); + + long leasePeriod = MusicUtil.getDefaultLockLeasePeriod(); + ReturnType lockAcqResult = MusicCore.acquireLockWithLease(lockname, lockId, leasePeriod); + long lockAcqTime = System.currentTimeMillis(); + long zkPutTime = 0, lockReleaseTime = 0; + + if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) { + logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId); + MusicCore.pureZkWrite(lockname, data); + zkPutTime = System.currentTimeMillis(); + boolean voluntaryRelease = true; + if (consistency.equals("atomic")) + MusicCore.releaseLock(lockId, voluntaryRelease); + else if (consistency.equals("atomic_delete_lock")) + MusicCore.deleteLock(lockname); + lockReleaseTime = System.currentTimeMillis(); + } else { + MusicCore.destroyLockRef(lockId); + } + + long actualUpdateCompletionTime = System.currentTimeMillis(); + + + long endTime = System.currentTimeMillis(); + + String lockingInfo = "|lock creation time:" + (lockCreationTime - jsonParseCompletionTime) + + "|lock accquire time:" + (lockAcqTime - lockCreationTime) + + "|zk put time:" + (zkPutTime - lockAcqTime); + + if (consistency.equals("atomic")) + lockingInfo = lockingInfo + "|lock release time:" + (lockReleaseTime - zkPutTime) + "|"; + else if (consistency.equals("atomic_delete_lock")) + lockingInfo = lockingInfo + "|lock delete time:" + (lockReleaseTime - zkPutTime) + "|"; + + String timingString = "Time taken in ms for Zookeeper " + consistency + " update-" + + operationId + ":" + "|total operation time:" + (endTime - startTime) + + "|json parsing time:" + (jsonParseCompletionTime - startTime) + + "|update time:" + (actualUpdateCompletionTime - jsonParseCompletionTime) + + lockingInfo; + + logger.info(EELFLoggerDelegate.applicationLogger,timingString); + } + + /** + * + * @param insObj + * @param lockName + * @param nodeName + * @throws Exception + */ + @GET + @Path("/purezk/atomic/{lockname}/{name}") + @Consumes(MediaType.APPLICATION_JSON) + public void pureZkAtomicGet(JsonInsert insObj, @PathParam("lockname") String lockName, + @PathParam("name") String nodeName) throws Exception { + logger.info("--------------Zk atomic read-------------------------"); + long start = System.currentTimeMillis(); + String lockId = MusicCore.createLockReference(lockName); + long leasePeriod = MusicUtil.getDefaultLockLeasePeriod(); + ReturnType lockAcqResult = MusicCore.acquireLockWithLease(lockName, lockId, leasePeriod); + if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) { + logger.info("acquired lock with id " + lockId); + MusicCore.pureZkRead(nodeName); + boolean voluntaryRelease = true; + MusicCore.releaseLock(lockId, voluntaryRelease); + } else { + MusicCore.destroyLockRef(lockId); + } + + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger,"Total time taken for Zk atomic read:" + (end - start) + " ms"); + } + + /** + * + * doing an update directly to cassa but through the rest api + * + * @param insObj + * @param keyspace + * @param tablename + * @param info + * @return + * @throws Exception + */ + @PUT + @Path("/cassa/keyspaces/{keyspace}/tables/{tablename}/rows") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public boolean updateTableCassa(JsonInsert insObj, @PathParam("keyspace") String keyspace, + @PathParam("tablename") String tablename, @Context UriInfo info) + throws Exception { + long startTime = System.currentTimeMillis(); + String operationId = UUID.randomUUID().toString();// just for debugging purposes. + String consistency = insObj.getConsistencyInfo().get("type"); + logger.info(EELFLoggerDelegate.applicationLogger,"--------------Cassandra " + consistency + " update-" + operationId + + "-------------------------"); + PreparedQueryObject queryObject = new PreparedQueryObject(); + Map<String, Object> valuesMap = insObj.getValues(); + TableMetadata tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename); + String vectorTs = "'" + Thread.currentThread().getId() + System.currentTimeMillis() + "'"; + String fieldValueString = "vector_ts= ? ,"; + queryObject.addValue(vectorTs); + + int counter = 0; + for (Map.Entry<String, Object> entry : valuesMap.entrySet()) { + Object valueObj = entry.getValue(); + DataType colType = tableInfo.getColumn(entry.getKey()).getType(); + Object valueString = MusicUtil.convertToActualDataType(colType, valueObj); + fieldValueString = fieldValueString + entry.getKey() + "= ?"; + queryObject.addValue(valueString); + if (counter != valuesMap.size() - 1) + fieldValueString = fieldValueString + ","; + counter = counter + 1; + } + + // get the row specifier + String rowSpec = ""; + counter = 0; + queryObject.appendQueryString("UPDATE " + keyspace + "." + tablename + " "); + MultivaluedMap<String, String> rowParams = info.getQueryParameters(); + String primaryKey = ""; + 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 = tableInfo.getColumn(entry.getKey()).getType(); + Object formattedValue = MusicUtil.convertToActualDataType(colType, indValue); + primaryKey = primaryKey + indValue; + rowSpec = rowSpec + keyName + "= ? "; + queryObject.addValue(formattedValue); + if (counter != rowParams.size() - 1) + rowSpec = rowSpec + " AND "; + counter = counter + 1; + } + + + 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(" SET " + fieldValueString + " WHERE " + rowSpec + ";"); + + long jsonParseCompletionTime = System.currentTimeMillis(); + + boolean operationResult = true; + MusicCore.getDSHandle().executePut(queryObject, insObj.getConsistencyInfo().get("type")); + + long actualUpdateCompletionTime = System.currentTimeMillis(); + + long endTime = System.currentTimeMillis(); + + String timingString = "Time taken in ms for Cassandra " + consistency + " update-" + + operationId + ":" + "|total operation time:" + (endTime - startTime) + + "|json parsing time:" + (jsonParseCompletionTime - startTime) + + "|update time:" + (actualUpdateCompletionTime - jsonParseCompletionTime) + + "|"; + logger.info(EELFLoggerDelegate.applicationLogger,timingString); + + return operationResult; + } +} diff --git a/jar/src/main/java/org/onap/music/rest/RestMusicDataAPI.java b/jar/src/main/java/org/onap/music/rest/RestMusicDataAPI.java new file mode 100755 index 00000000..47d1eae7 --- /dev/null +++ b/jar/src/main/java/org/onap/music/rest/RestMusicDataAPI.java @@ -0,0 +1,1289 @@ +/* + * ============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.rest; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriInfo; + +import org.mindrot.jbcrypt.BCrypt; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.datastore.jsonobjects.JsonDelete; +import org.onap.music.datastore.jsonobjects.JsonInsert; +import org.onap.music.datastore.jsonobjects.JsonKeySpace; +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.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.MusicServiceException; +import org.onap.music.main.CachingUtil; +import org.onap.music.main.MusicCore; +import org.onap.music.main.MusicCore.Condition; +import org.onap.music.main.MusicUtil; +import org.onap.music.main.ResultType; +import org.onap.music.main.ReturnType; +import org.onap.music.response.jsonobjects.JsonResponse; + +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 io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; + +/* Version 2 Class */ +//@Path("/v{version: [0-9]+}/keyspaces") +@Path("/v2/keyspaces") +@Api(value = "Data Api") +public class RestMusicDataAPI { + /* + * Header values for Versioning X-minorVersion *** - Used to request or communicate a MINOR + * version back from the client to the server, and from the server back to the client - This + * will be the MINOR version requested by the client, or the MINOR version of the last MAJOR + * version (if not specified by the client on the request) - Contains a single position value + * (e.g. if the full version is 1.24.5, X-minorVersion = "24") - Is optional for the client on + * request; however, this header should be provided if the client needs to take advantage of + * MINOR incremented version functionality - Is mandatory for the server on response + * + *** X-patchVersion *** - Used only to communicate a PATCH version in a response for + * troubleshooting purposes only, and will not be provided by the client on request - This will + * be the latest PATCH version of the MINOR requested by the client, or the latest PATCH version + * of the MAJOR (if not specified by the client on the request) - Contains a single position + * value (e.g. if the full version is 1.24.5, X-patchVersion = "5") - Is mandatory for the + * server on response (CURRENTLY NOT USED) + * + *** X-latestVersion *** - Used only to communicate an API's latest version - Is mandatory for the + * server on response, and shall include the entire version of the API (e.g. if the full version + * is 1.24.5, X-latestVersion = "1.24.5") - Used in the response to inform clients that they are + * not using the latest version of the API (CURRENTLY NOT USED) + * + */ + + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicDataAPI.class); + private static final String XMINORVERSION = "X-minorVersion"; + private static final String XPATCHVERSION = "X-patchVersion"; + private static final String NS = "ns"; + private static final String USERID = "userId"; + private static final String PASSWORD = "password"; + private static final String VERSION = "v2"; + + 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; + } + } + + + /** + * Create Keyspace REST + * + * @param kspObject + * @param keyspaceName + * @return + * @throws Exception + */ + @POST + @Path("/{name}") + @ApiOperation(value = "Create Keyspace", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + //public Map<String, Object> createKeySpace( + public Response createKeySpace( + @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 = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns, + @ApiParam(value = "userId",required = true) @HeaderParam(USERID) String userId, + @ApiParam(value = "Password",required = true) @HeaderParam(PASSWORD) String password, + JsonKeySpace kspObject, + @ApiParam(value = "Keyspace Name",required = true) @PathParam("name") String keyspaceName) { + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + + Map<String, Object> authMap = CachingUtil.verifyOnboarding(ns, userId, password); + if (!authMap.isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR); + response.status(Status.UNAUTHORIZED); + return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build(); + } + if(kspObject == null || kspObject.getReplicationInfo() == null) { + authMap.put(ResultType.EXCEPTION.getResult(), ResultType.BODYMISSING.getResult()); + response.status(Status.BAD_REQUEST); + return response.entity(authMap).build(); + } + + try { + authMap = MusicCore.autheticateUser(ns, userId, password, keyspaceName, aid, + "createKeySpace"); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); + response.status(Status.BAD_REQUEST); + return response.entity(new JsonResponse(ResultType.FAILURE).setError("Unable to authenticate.").toMap()).build(); + } + String newAid = null; + if (!authMap.isEmpty()) { + if (authMap.containsKey("aid")) { + newAid = (String) authMap.get("aid"); + } else { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR); + response.status(Status.UNAUTHORIZED); + return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build(); + } + } + + String consistency = MusicUtil.EVENTUAL;// for now this needs only + // eventual consistency + + PreparedQueryObject queryObject = new PreparedQueryObject(); + 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); + + } + 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); + logger.info(EELFLoggerDelegate.applicationLogger, "result = " + result); + } catch ( MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("err:" + ex.getMessage()).toMap()).build(); + } + + try { + queryObject = new PreparedQueryObject(); + queryObject.appendQueryString("CREATE ROLE IF NOT EXISTS '" + userId + + "' WITH PASSWORD = '" + password + "' AND LOGIN = true;"); + MusicCore.nonKeyRelatedPut(queryObject, consistency); + queryObject = new PreparedQueryObject(); + queryObject.appendQueryString("GRANT ALL PERMISSIONS on KEYSPACE " + keyspaceName + + " to '" + userId + "'"); + queryObject.appendQueryString(";"); + MusicCore.nonKeyRelatedPut(queryObject, consistency); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); + } + + try { + boolean isAAF = Boolean.valueOf(CachingUtil.isAAFApplication(ns)); + 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 (?,?,?,?,?,?,?)"); + queryObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), newAid)); + queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), keyspaceName)); + queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), ns)); + queryObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "True")); + queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), hashedpwd)); + queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); + queryObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF)); + CachingUtil.updateMusicCache(keyspaceName, ns); + CachingUtil.updateMusicValidateCache(ns, userId, hashedpwd); + MusicCore.eventualPut(queryObject); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); + return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); + } + + return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Created").toMap()).build(); + } + + /** + * + * @param kspObject + * @param keyspaceName + * @return + * @throws Exception + */ + @DELETE + @Path("/{name}") + @ApiOperation(value = "Delete Keyspace", response = String.class) + @Produces(MediaType.APPLICATION_JSON) + //public Map<String, Object> dropKeySpace( + public Response dropKeySpace( + @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 = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns, + @ApiParam(value = "userId",required = true) @HeaderParam(USERID) String userId, + @ApiParam(value = "Password",required = true) @HeaderParam(PASSWORD) String password, + @ApiParam(value = "Keyspace Name",required = true) @PathParam("name") String keyspaceName) throws Exception { + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + + Map<String, Object> authMap = MusicCore.autheticateUser(ns, userId, password,keyspaceName, aid, "dropKeySpace"); + if (authMap.containsKey("aid")) + authMap.remove("aid"); + if (!authMap.isEmpty()) { + return response.status(Status.UNAUTHORIZED).entity(authMap).build(); + } + + String consistency = MusicUtil.EVENTUAL;// for now this needs only + // eventual + // consistency + String appName = CachingUtil.getAppName(keyspaceName); + String uuid = CachingUtil.getUuidFromMusicCache(keyspaceName); + PreparedQueryObject pQuery = new PreparedQueryObject(); + pQuery.appendQueryString( + "select count(*) as count from admin.keyspace_master where application_name=? allow filtering;"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); + Row row = MusicCore.get(pQuery).one(); + long count = row.getLong(0); + + if (count == 0) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Keyspace not found. Please make sure keyspace exists.").toMap()).build(); + // Admin Functions: + } else if (count == 1) { + pQuery = new PreparedQueryObject(); + pQuery.appendQueryString( + "UPDATE admin.keyspace_master SET keyspace_name=? where uuid = ?;"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), + MusicUtil.DEFAULTKEYSPACENAME)); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); + MusicCore.nonKeyRelatedPut(pQuery, consistency); + } else { + pQuery = new PreparedQueryObject(); + pQuery.appendQueryString("delete from admin.keyspace_master where uuid = ?"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); + MusicCore.nonKeyRelatedPut(pQuery, consistency); + } + + 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(); + } + return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Deleted").toMap()).build(); + } + + /** + * + * @param tableObj + * @param version + * @param keyspace + * @param tablename + * @param headers + * @return + * @throws Exception + */ + @POST + @Path("/{keyspace}/tables/{tablename}") + @ApiOperation(value = "Create Table", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + //public Map<String, Object> createTable( + 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 = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns, + @ApiParam(value = "userId",required = true) @HeaderParam(USERID) String userId, + @ApiParam(value = "Password",required = true) @HeaderParam(PASSWORD) String password, + JsonTable tableObj, + @ApiParam(value = "Keyspace Name",required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Table Name",required = true) @PathParam("tablename") String tablename) throws Exception { + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + Map<String, Object> authMap = MusicCore.autheticateUser(ns, userId, password, keyspace, + aid, "createTable"); + if (authMap.containsKey("aid")) + authMap.remove("aid"); + if (!authMap.isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR); + return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build(); + } + String consistency = MusicUtil.EVENTUAL; + // for now this needs only eventual consistency + PreparedQueryObject queryObject = new PreparedQueryObject(); + // first read the information about the table fields + Map<String, String> fields = tableObj.getFields(); + StringBuilder fieldsString = new StringBuilder("(vector_ts text,"); + int counter = 0; + String primaryKey; + for (Map.Entry<String, String> entry : fields.entrySet()) { + + if (entry.getKey().equals("PRIMARY KEY")) { + if(! entry.getValue().contains("(")) + primaryKey = entry.getValue(); + else { + primaryKey = entry.getValue().substring(entry.getValue().indexOf('(') + 1); + primaryKey = primaryKey.substring(0, primaryKey.indexOf(')')); + } + fieldsString.append("" + entry.getKey() + " (" + primaryKey + ")"); + } else + fieldsString.append("" + entry.getKey() + " " + entry.getValue() + ""); + if (counter == fields.size() - 1) + fieldsString.append(")"); + else + fieldsString.append(","); + counter = counter + 1; + } + // 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; + } + } + + queryObject.appendQueryString( + "CREATE TABLE " + keyspace + "." + tablename + " " + fieldsString); + + if (propertiesMap != null) + queryObject.appendQueryString(" WITH " + propertiesString); + + queryObject.appendQueryString(";"); + ResultType result = ResultType.FAILURE; + + try { + result = MusicCore.nonKeyRelatedPut(queryObject, consistency); + } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.MUSICSERVICEERROR); + response.status(Status.BAD_REQUEST); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); + } + if ( result.equals(ResultType.FAILURE) ) { + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Error Creating Table " + tablename).toMap()).build(); + } + return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("TableName " + tablename + " Created under keyspace " + keyspace).toMap()).build(); + } + + /** + * + * @param keyspace + * @param tablename + * @param fieldName + * @param info + * @throws Exception + */ + @POST + @Path("/{keyspace}/tables/{tablename}/index/{field}") + @ApiOperation(value = "Create Index", response = String.class) + @Produces(MediaType.APPLICATION_JSON) + 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 = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns, + @ApiParam(value = "userId",required = true) @HeaderParam(USERID) String userId, + @ApiParam(value = "Password",required = true) @HeaderParam(PASSWORD) String password, + @ApiParam(value = "Keyspace Name",required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Table Name",required = true) @PathParam("tablename") String tablename, + @ApiParam(value = "Field Name",required = true) @PathParam("field") String fieldName, + @Context UriInfo info) throws Exception { + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + + Map<String, Object> authMap = MusicCore.autheticateUser(ns, userId, password, keyspace,aid, "createIndex"); + if (authMap.containsKey("aid")) + authMap.remove("aid"); + if (!authMap.isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR); + response.status(Status.UNAUTHORIZED); + return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build(); + } + MultivaluedMap<String, String> rowParams = info.getQueryParameters(); + String indexName = ""; + if (rowParams.getFirst("index_name") != null) + indexName = rowParams.getFirst("index_name"); + PreparedQueryObject query = new PreparedQueryObject(); + query.appendQueryString("Create index " + indexName + " if not exists on " + keyspace + "." + + tablename + " (" + fieldName + ");"); + + ResultType result = ResultType.FAILURE; + try { + result = MusicCore.nonKeyRelatedPut(query, "eventual"); + } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + response.status(Status.BAD_REQUEST); + return response.entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); + } + if ( result.equals(ResultType.SUCCESS) ) { + return response.entity(new JsonResponse(result).setMessage("Index Created on " + keyspace+"."+tablename+"."+fieldName).toMap()).build(); + } else { + return response.entity(new JsonResponse(result).setError("Unknown Error in create index.").toMap()).build(); + } + } + + /** + * + * @param insObj + * @param keyspace + * @param tablename + * @return + * @throws Exception + */ + @POST + @Path("/{keyspace}/tables/{tablename}/rows") + @ApiOperation(value = "Insert Into Table", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response insertIntoTable( + @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 = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns, + @ApiParam(value = "userId",required = true) @HeaderParam(USERID) String userId, + @ApiParam(value = "Password",required = true) @HeaderParam(PASSWORD) String password, + JsonInsert insObj, + @ApiParam(value = "Keyspace Name", + required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Table Name", + required = true) @PathParam("tablename") String tablename) { + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + + Map<String, Object> authMap = null; + + try { + authMap = MusicCore.autheticateUser(ns, userId, password, keyspace, + aid, "insertIntoTable"); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR); + return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); + } + if (authMap.containsKey("aid")) + authMap.remove("aid"); + if (!authMap.isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR); + return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build(); + } + + Map<String, Object> valuesMap = insObj.getValues(); + PreparedQueryObject queryObject = new PreparedQueryObject(); + TableMetadata tableInfo = null; + try { + tableInfo = MusicCore.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.getMessage(), 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); + 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); + 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.getMessage()); + } + valueString.append("?"); + queryObject.addValue(formattedValue); + + if (counter == valuesMap.size() - 1) { + fieldsString.append(")"); + valueString.append(")"); + } else { + fieldsString.append(","); + valueString.append(","); + } + counter = counter + 1; + } + + 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(); + } + + 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"); + try { + if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) { + result = MusicCore.eventualPut(queryObject); + } else 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" + + " 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(); + } + result = MusicCore.criticalPut(keyspace, tablename, primaryKey, queryObject, lockId,null); + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + result = MusicCore.atomicPut(keyspace, tablename, primaryKey, queryObject, null); + + } + else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) { + result = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, primaryKey, queryObject, null); + + } + } catch (Exception ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); + } + + if (result==null) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build(); + } + return response.status(Status.OK).entity(new JsonResponse(result.getResult()).setMessage("Insert Successful").toMap()).build(); + } + + /** + * + * @param insObj + * @param keyspace + * @param tablename + * @param info + * @return + * @throws Exception + */ + @PUT + @Path("/{keyspace}/tables/{tablename}/rows") + @ApiOperation(value = "Update Table", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response updateTable( + @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 = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam(NS) String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam(USERID) String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam(PASSWORD) String password, + JsonUpdate updateObj, + @ApiParam(value = "Keyspace Name", + required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Table Name", + required = true) @PathParam("tablename") String tablename, + @Context UriInfo info) { + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + + Map<String, Object> authMap; + try { + authMap = MusicCore.autheticateUser(ns, userId, password, keyspace, + aid, "updateTable"); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); + return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); + } + if (authMap.containsKey("aid")) + authMap.remove("aid"); + if (!authMap.isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); + return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build(); + } + long startTime = System.currentTimeMillis(); + String operationId = UUID.randomUUID().toString();// just for infoging + // purposes. + String consistency = updateObj.getConsistencyInfo().get("type"); + 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 = MusicCore.returnColumnMetadata(keyspace, tablename); + } catch (MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); + } + if (tableInfo == null) { + logger.error(EELFLoggerDelegate.errorLogger,"", 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, "Invalid column name : "+entry.getKey()); + 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.getMessage()); + } + 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; + 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(); + } + } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); + 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 MusicCore.Condition(updateObj.getConditions(), selectQuery); + } + + ReturnType operationResult = null; + long jsonParseCompletionTime = System.currentTimeMillis(); + + 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.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); + 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.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); + } + } + long actualUpdateCompletionTime = System.currentTimeMillis(); + + long endTime = System.currentTimeMillis(); + String timingString = "Time taken in ms for Music " + consistency + " update-" + operationId + + ":" + "|total operation time:" + (endTime - startTime) + + "|json parsing time:" + (jsonParseCompletionTime - startTime) + + "|update time:" + (actualUpdateCompletionTime - jsonParseCompletionTime) + + "|"; + + if (operationResult != null && operationResult.getTimingInfo() != null) { + String lockManagementTime = operationResult.getTimingInfo(); + timingString = timingString + lockManagementTime; + } + logger.info(EELFLoggerDelegate.applicationLogger, timingString); + + if (operationResult==null) { + logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build(); + } + if ( operationResult.getResult() == ResultType.SUCCESS ) { + return response.status(Status.OK).entity(new JsonResponse(operationResult.getResult()).setMessage(operationResult.getMessage()).toMap()).build(); + } else { + logger.error(EELFLoggerDelegate.errorLogger,operationResult.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(operationResult.getResult()).setError(operationResult.getMessage()).toMap()).build(); + } + + } + + /** + * + * @param delObj + * @param keyspace + * @param tablename + * @param info + * @return + * @throws Exception + */ + @DELETE + @Path("/{keyspace}/tables/{tablename}/rows") + @ApiOperation(value = "Delete From table", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response deleteFromTable( + @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 = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam(NS) String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam(USERID) String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam(PASSWORD) String password, + JsonDelete delObj, + @ApiParam(value = "Keyspace Name", + required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Table Name", + required = true) @PathParam("tablename") String tablename, + @Context UriInfo info) { + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + + Map<String, Object> authMap = null; + try { + authMap = MusicCore.autheticateUser(ns, userId, password, keyspace, + aid, "deleteFromTable"); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); + return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); + } + if (authMap.containsKey("aid")) + authMap.remove("aid"); + if (!authMap.isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); + return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build(); + } + if(delObj == null) { + logger.error(EELFLoggerDelegate.errorLogger,"", 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(); + } + PreparedQueryObject queryObject = new PreparedQueryObject(); + StringBuilder columnString = new StringBuilder(); + + int counter = 0; + ArrayList<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.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); + 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 MusicCore.Condition(delObj.getConditions(), selectQuery); + } + + String consistency = delObj.getConsistencyInfo().get("type"); + + ReturnType operationResult = null; + try { + if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) + operationResult = MusicCore.eventualPut(queryObject); + else 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" + + " 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(MusicUtil.ATOMIC)) { + operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue, + queryObject, conditionInfo); + } + else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) { + operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, rowId.primarKeyValue, + queryObject, conditionInfo); + } + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + .setError("Unable to perform Delete operation. Exception from music").toMap()).build(); + } + if (operationResult==null) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build(); + } + if (operationResult.getResult().equals(ResultType.SUCCESS)) { + return response.status(Status.OK).entity(new JsonResponse(operationResult.getResult()).setMessage(operationResult.getMessage()).toMap()).build(); + } else { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(operationResult.getMessage()).toMap()).build(); + } + } + + /** + * + * @param tabObj + * @param keyspace + * @param tablename + * @throws Exception + */ + @DELETE + @Path("/{keyspace}/tables/{tablename}") + @ApiOperation(value = "Drop Table", response = String.class) + @Produces(MediaType.APPLICATION_JSON) + public Response dropTable( + @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 = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam(NS) String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam(USERID) String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam(PASSWORD) String password, + @ApiParam(value = "Keyspace Name", + required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Table Name", + required = true) @PathParam("tablename") String tablename) throws Exception { + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + + Map<String, Object> authMap = + MusicCore.autheticateUser(ns, userId, password, keyspace, aid, "dropTable"); + if (authMap.containsKey("aid")) + authMap.remove("aid"); + if (!authMap.isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); + return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build(); + } + String consistency = "eventual";// for now this needs only eventual + // consistency + PreparedQueryObject query = new PreparedQueryObject(); + query.appendQueryString("DROP TABLE " + keyspace + "." + tablename + ";"); + try { + return response.status(Status.OK).entity(new JsonResponse(MusicCore.nonKeyRelatedPut(query, consistency)).toMap()).build(); + } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); + } + + } + + /** + * + * @param selObj + * @param keyspace + * @param tablename + * @param info + * @return + */ + @PUT + @Path("/{keyspace}/tables/{tablename}/rows/criticalget") + @ApiOperation(value = "Select Critical", response = Map.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response selectCritical( + @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 = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam(NS) String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam(USERID) String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam(PASSWORD) String password, + 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 { + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + + Map<String, Object> authMap = MusicCore.autheticateUser(ns, userId, password, keyspace,aid, "selectCritical"); + if (authMap.containsKey("aid")) + authMap.remove("aid"); + if (!authMap.isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger,"Error while authentication... ", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); + return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build(); + } + 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.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); + } + queryObject.appendQueryString( + "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowId.rowIdString + ";"); + + ResultSet results = null; + + String consistency = selObj.getConsistencyInfo().get("type"); + + 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); + } + + else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) { + results = MusicCore.atomicGetWithDeleteLock(keyspace, tablename, rowId.primarKeyValue, queryObject); + } + + return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicCore.marshallResults(results)).toMap()).build(); + } + + /** + * + * @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) + @Produces(MediaType.APPLICATION_JSON) + public Response select( + @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 = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam(NS) String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam(USERID) String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam(PASSWORD) String password, + @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 { + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + + Map<String, Object> authMap = + MusicCore.autheticateUser(ns, userId, password, keyspace, aid, "select"); + if (authMap.containsKey("aid")) + authMap.remove("aid"); + if (!authMap.isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); + return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build(); + } + 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(VERSION, minorVersion, patchVersion, aid, ns, + userId, password, keyspace, tablename, info, limit); + } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); + } + } + + try { + ResultSet results = MusicCore.get(queryObject); + return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicCore.marshallResults(results)).toMap()).build(); + } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.UNKNOWNERROR ,ErrorSeverity.ERROR, ErrorTypes.MUSICSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); + } + + } + + /** + * + * @param keyspace + * @param tablename + * @param info + * @param limit + * @return + * @throws MusicServiceException + */ + public PreparedQueryObject selectSpecificQuery(String version, String minorVersion, + String patchVersion, String aid, String ns, String userId, String password, + String keyspace, String tablename, UriInfo info, int limit) + throws MusicServiceException { + + PreparedQueryObject queryObject = new PreparedQueryObject(); + StringBuilder rowIdString = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), + queryObject).rowIdString; + + queryObject.appendQueryString( + "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowIdString); + + if (limit != -1) { + queryObject.appendQueryString(" LIMIT " + limit); + } + + queryObject.appendQueryString(";"); + 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 = MusicCore.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.getMessage()); + } + 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/jar/src/main/java/org/onap/music/rest/RestMusicHealthCheckAPI.java b/jar/src/main/java/org/onap/music/rest/RestMusicHealthCheckAPI.java new file mode 100644 index 00000000..752a538b --- /dev/null +++ b/jar/src/main/java/org/onap/music/rest/RestMusicHealthCheckAPI.java @@ -0,0 +1,113 @@ +/* + * ============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.rest; + +import java.util.HashMap; +/** + * @author inam + * + */ +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.Consumes; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.core.Response.Status; + + +import org.onap.music.response.jsonobjects.JsonResponse; +import org.onap.music.eelf.healthcheck.MusicHealthCheck; +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; + + + + +@Path("/v{version: [0-9]+}/service") +@Api(value="Healthcheck Api") +public class RestMusicHealthCheckAPI { + + + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicUtil.class); + + + @GET + @Path("/cs") + @ApiOperation(value = "Get Health Status", response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + public Response cassandraStatus(@Context HttpServletResponse response) { + logger.info(EELFLoggerDelegate.applicationLogger,"Replying to request for MUSIC Health Check status for Cassandra"); + + Map<String, Object> resultMap = new HashMap<>(); + + MusicHealthCheck cassHealthCheck = new MusicHealthCheck(); + String status = cassHealthCheck.getCassandraStatus(); + if(status.equals("ACTIVE")) { + resultMap.put("ACTIVE", "Cassandra Running and Listening to requests"); + return Response.status(Status.OK).entity(resultMap).build(); + }else { + resultMap.put("INACTIVE", "Cassandra Service is not responding"); + return Response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + + + + } + + @GET + @Path("/zk") + @ApiOperation(value = "Get Health Status", response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + public Response ZKStatus(@Context HttpServletResponse response) { + logger.info(EELFLoggerDelegate.applicationLogger,"Replying to request for MUSIC Health Check status for Zookeeper"); + Map<String, Object> resultMap = new HashMap<>(); + MusicHealthCheck ZKHealthCheck = new MusicHealthCheck(); + String status = ZKHealthCheck.getZookeeperStatus(); + if(status.equals("ACTIVE")) { + resultMap.put("ACTIVE", "Zookeeper is Active and Running"); + return Response.status(Status.OK).entity(resultMap).build(); + }else { + resultMap.put("INACTIVE", "Zookeeper is not responding"); + return Response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + } + + + + + + + +} diff --git a/jar/src/main/java/org/onap/music/rest/RestMusicLocksAPI.java b/jar/src/main/java/org/onap/music/rest/RestMusicLocksAPI.java new file mode 100644 index 00000000..22112ddf --- /dev/null +++ b/jar/src/main/java/org/onap/music/rest/RestMusicLocksAPI.java @@ -0,0 +1,423 @@ +/* + * ============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.rest; + +import java.util.Map; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.core.Response.Status; +import org.onap.music.datastore.jsonobjects.JsonLeasedLock; +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.lockingservice.MusicLockState; +import org.onap.music.main.MusicCore; +import org.onap.music.main.MusicUtil; +import org.onap.music.main.ResultType; +import org.onap.music.main.ReturnType; +import org.onap.music.response.jsonobjects.JsonResponse; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; + + +@Path("/v2/locks/") +@Api(value="Lock Api") +public class RestMusicLocksAPI { + + private EELFLoggerDelegate logger =EELFLoggerDelegate.getLogger(RestMusicLocksAPI.class); + private static final String XMINORVERSION = "X-minorVersion"; + private static final String XPATCHVERSION = "X-patchVersion"; + private static final String VERSION = "v2"; + + /** + * Puts the requesting process in the q for this lock. The corresponding + * node will be created in zookeeper if it did not already exist + * + * @param lockName + * @return + * @throws Exception + */ + @POST + @Path("/create/{lockname}") + @ApiOperation(value = "Create Lock", + notes = "Puts the requesting process in the q for this lock." + + " The corresponding node will be created in zookeeper if it did not already exist." + + " Lock Name is the \"key\" of the form keyspaceName.tableName.rowId", + response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + 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 = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam("ns") String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam("userId") String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam("password") String password) throws Exception{ + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + Map<String, Object> resultMap = MusicCore.validateLock(lockName); + if (resultMap.containsKey("Exception")) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + String keyspaceName = (String) resultMap.get("keyspace"); + resultMap.remove("keyspace"); + resultMap = MusicCore.autheticateUser(ns, userId, password, keyspaceName, aid, + "createLockReference"); + if (resultMap.containsKey("aid")) + resultMap.remove("aid"); + if (!resultMap.isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR); + return response.status(Status.UNAUTHORIZED).entity(resultMap).build(); + } + ResultType status = ResultType.SUCCESS; + String lockId = MusicCore.createLockReference(lockName); + + if (lockId == null) { + status = ResultType.FAILURE; + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.LOCKINGERROR ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(status).setError("Lock Id is null").toMap()).build(); + } + return response.status(Status.OK).entity(new JsonResponse(status).setLock(lockId).toMap()).build(); + } + + /** + * + * Checks if the node is in the top of the queue and hence acquires the lock + * + * @param lockId + * @return + * @throws Exception + */ + @GET + @Path("/acquire/{lockreference}") + @ApiOperation(value = "Aquire Lock", + notes = "Checks if the node is in the top of the queue and hence acquires the lock", + response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + public Response accquireLock( + @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 = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam("ns") String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam("userId") String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam("password") String password) throws Exception{ + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + Map<String, Object> resultMap = MusicCore.validateLock(lockId); + if (resultMap.containsKey("Exception")) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + String keyspaceName = (String) resultMap.get("keyspace"); + resultMap.remove("keyspace"); + resultMap = MusicCore.autheticateUser(ns, userId, password, keyspaceName, aid, + "accquireLock"); + if (resultMap.containsKey("aid")) + resultMap.remove("aid"); + if (!resultMap.isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + try { + String lockName = lockId.substring(lockId.indexOf('$')+1, lockId.lastIndexOf('$')); + ReturnType lockStatus = MusicCore.acquireLock(lockName,lockId); + if ( lockStatus.getResult().equals(ResultType.SUCCESS)) { + response.status(Status.OK); + } else { + response.status(Status.BAD_REQUEST); + } + return response.entity(new JsonResponse(lockStatus.getResult()).setLock(lockId).setMessage(lockStatus.getMessage()).toMap()).build(); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,AppMessages.INVALIDLOCK + lockId, ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Unable to aquire lock").toMap()).build(); + } + } + + + + + @POST + @Path("/acquire-with-lease/{lockreference}") + @ApiOperation(value = "Aquire Lock with Lease", 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 = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam("ns") String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam("userId") String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam("password") String password) throws Exception{ + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + Map<String, Object> resultMap = MusicCore.validateLock(lockId); + if (resultMap.containsKey("Exception")) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + String keyspaceName = (String) resultMap.get("keyspace"); + resultMap.remove("keyspace"); + resultMap = MusicCore.autheticateUser(ns, userId, password, keyspaceName, aid, + "accquireLockWithLease"); + + if (resultMap.containsKey("aid")) + resultMap.remove("aid"); + if (!resultMap.isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + String lockName = lockId.substring(lockId.indexOf('$')+1, lockId.lastIndexOf('$')); + ReturnType lockLeaseStatus = MusicCore.acquireLockWithLease(lockName, lockId, lockObj.getLeasePeriod()); + if ( lockLeaseStatus.getResult().equals(ResultType.SUCCESS)) { + response.status(Status.OK); + } else { + response.status(Status.BAD_REQUEST); + } + return response.entity(new JsonResponse(lockLeaseStatus.getResult()).setLock(lockName) + .setMessage(lockLeaseStatus.getMessage()) + .setLockLease(String.valueOf(lockObj.getLeasePeriod())).toMap()).build(); + } + + + @GET + @Path("/enquire/{lockname}") + @ApiOperation(value = "Get Lock Holder", + notes = "Gets the current Lock Holder", + response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + 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 = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam("ns") String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam("userId") String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam("password") String password) throws Exception{ + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + Map<String, Object> resultMap = MusicCore.validateLock(lockName); + if (resultMap.containsKey("Exception")) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + String keyspaceName = (String) resultMap.get("keyspace"); + resultMap.remove("keyspace"); + resultMap = MusicCore.autheticateUser(ns, userId, password, keyspaceName, aid, + "currentLockHolder"); + if (resultMap.containsKey("aid")) + resultMap.remove("aid"); + if (!resultMap.isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + String who = MusicCore.whoseTurnIsIt(lockName); + ResultType status = ResultType.SUCCESS; + String error = ""; + if ( who == null ) { + status = ResultType.FAILURE; + error = "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).entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).toMap()).build(); + } + return response.status(Status.OK).entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).toMap()).build(); + } + + @GET + @Path("/{lockname}") + @ApiOperation(value = "Lock State", + notes = "Returns current Lock State and Holder.", + response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + 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 = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam("ns") String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam("userId") String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam("password") String password) throws Exception{ + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + Map<String, Object> resultMap = MusicCore.validateLock(lockName); + if (resultMap.containsKey("Exception")) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + String keyspaceName = (String) resultMap.get("keyspace"); + resultMap.remove("keyspace"); + resultMap = MusicCore.autheticateUser(ns, userId, password, keyspaceName, aid, + "currentLockState"); + + if (resultMap.containsKey("aid")) + resultMap.remove("aid"); + if (!resultMap.isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + + MusicLockState mls = MusicCore.getMusicLockState(lockName); + Map<String,Object> returnMap = null; + JsonResponse jsonResponse = new JsonResponse(ResultType.FAILURE).setLock(lockName); + if(mls == null) { + jsonResponse.setError(""); + jsonResponse.setMessage("No lock object created yet.."); + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(jsonResponse.toMap()).build(); + } else { + jsonResponse.setStatus(ResultType.SUCCESS); + jsonResponse.setLockStatus(mls.getLockStatus()); + jsonResponse.setLockHolder(mls.getLockHolder()); + return response.status(Status.OK).entity(jsonResponse.toMap()).build(); + } + } + + /** + * + * deletes the process from the zk queue + * + * @param lockId + * @throws Exception + */ + @DELETE + @Path("/release/{lockreference}") + @ApiOperation(value = "Release Lock", + notes = "deletes the process from the zk queue", + response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + 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 = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam("ns") String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam("userId") String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam("password") String password) throws Exception{ + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + Map<String, Object> resultMap = MusicCore.validateLock(lockId); + if (resultMap.containsKey("Exception")) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + String keyspaceName = (String) resultMap.get("keyspace"); + resultMap.remove("keyspace"); + resultMap = MusicCore.autheticateUser(ns, userId, password, keyspaceName, aid, + "unLock"); + if (resultMap.containsKey("aid")) + resultMap.remove("aid"); + if (!resultMap.isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + boolean voluntaryRelease = true; + MusicLockState mls = MusicCore.releaseLock(lockId,voluntaryRelease); + if(mls.getErrorMessage() != null) { + resultMap.put(ResultType.EXCEPTION.getResult(), mls.getErrorMessage()); + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + Map<String,Object> returnMap = null; + if (mls.getLockStatus() == MusicLockState.LockStatus.UNLOCKED) { + returnMap = new JsonResponse(ResultType.SUCCESS).setLock(lockId) + .setLockStatus(mls.getLockStatus()).toMap(); + response.status(Status.OK); + } + if (mls.getLockStatus() == MusicLockState.LockStatus.LOCKED) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.LOCKINGERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + returnMap = new JsonResponse(ResultType.FAILURE).setLock(lockId) + .setLockStatus(mls.getLockStatus()).toMap(); + response.status(Status.BAD_REQUEST); + } + return response.entity(returnMap).build(); + } + + /** + * + * @param lockName + * @throws Exception + */ + @DELETE + @Path("/delete/{lockname}") + @ApiOperation(value = "Delete Lock", response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + 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 = "Application namespace", + required = true) @HeaderParam("ns") String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam("userId") String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam("password") String password) throws Exception{ + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + Map<String, Object> resultMap = MusicCore.validateLock(lockName); + if (resultMap.containsKey("Exception")) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + String keyspaceName = (String) resultMap.get("keyspace"); + resultMap.remove("keyspace"); + resultMap = MusicCore.autheticateUser(ns, userId, password, keyspaceName, aid, + "deleteLock"); + if (resultMap.containsKey("aid")) + resultMap.remove("aid"); + if (!resultMap.isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + try{ + MusicCore.deleteLock(lockName); + }catch (Exception e) { + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); + } + return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).toMap()).build(); + } + +} diff --git a/jar/src/main/java/org/onap/music/rest/RestMusicQAPI.java b/jar/src/main/java/org/onap/music/rest/RestMusicQAPI.java new file mode 100755 index 00000000..e08adaf7 --- /dev/null +++ b/jar/src/main/java/org/onap/music/rest/RestMusicQAPI.java @@ -0,0 +1,251 @@ +/* + * ============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.rest; + + + +import java.util.HashMap; +import java.util.Map; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import org.onap.music.datastore.jsonobjects.JsonDelete; +import org.onap.music.datastore.jsonobjects.JsonInsert; +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.main.MusicCore; + +import org.onap.music.datastore.PreparedQueryObject; +import com.datastax.driver.core.ResultSet; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; + +//@Path("/v{version: [0-9]+}/priorityq/") +@Path("/priorityq/") +@Api(value="Q Api") +public class RestMusicQAPI { + + private EELFLoggerDelegate logger =EELFLoggerDelegate.getLogger(RestMusicDataAPI.class); + + + /** + * + * @param tableObj + * @param keyspace + * @param tablename + * @throws Exception + */ + + @POST + @Path("/keyspaces/{keyspace}/{qname}") + @ApiOperation(value = "", response = Void.class) + @Consumes(MediaType.APPLICATION_JSON) + public Response createQ( + @ApiParam(value="Major Version",required=true) @PathParam("version") String version, + @ApiParam(value="Minor Version",required=false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value="Patch Version",required=false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value="AID",required=true) @HeaderParam("aid") String aid, + @ApiParam(value="Application namespace",required=true) @HeaderParam("ns") String ns, + @ApiParam(value="userId",required=true) @HeaderParam("userId") String userId, + @ApiParam(value="Password",required=true) @HeaderParam("password") String password, JsonTable tableObj, + @ApiParam(value="Key Space",required=true) @PathParam("keyspace") String keyspace, + @ApiParam(value="Table Name",required=true) @PathParam("tablename") String tablename) throws Exception{ + return new RestMusicDataAPI().createTable(version,minorVersion,patchVersion,aid, ns, userId, password, tableObj, keyspace, tablename); + } + + /** + * + * @param insObj + * @param keyspace + * @param tablename + * @throws Exception + */ + @POST + @Path("/keyspaces/{keyspace}/{qname}/rows") + @ApiOperation(value = "", response = Void.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response insertIntoQ( + @ApiParam(value="Major Version",required=true) @PathParam("version") String version, + @ApiParam(value="Minor Version",required=false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value="Patch Version",required=false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value="AID",required=true) @HeaderParam("aid") String aid, + @ApiParam(value="Application namespace",required=true) @HeaderParam("ns") String ns, @ApiParam(value="userId",required=true) @HeaderParam("userId") String userId, + @ApiParam(value="Password",required=true) @HeaderParam("password") String password, JsonInsert insObj, + @ApiParam(value="Key Space",required=true) @PathParam("keyspace") String keyspace, + @ApiParam(value="Table Name",required=true) @PathParam("tablename") String tablename) throws Exception{ + return new RestMusicDataAPI().insertIntoTable(version,minorVersion,patchVersion,aid, ns, userId, password, insObj, keyspace, tablename); + } + + /** + * + * @param updateObj + * @param keyspace + * @param tablename + * @param info + * @return + * @throws Exception + */ + @PUT + @Path("/keyspaces/{keyspace}/{qname}/rows") + @ApiOperation(value = "", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response updateQ( + @ApiParam(value="Major Version",required=true) @PathParam("version") String version, + @ApiParam(value="Minor Version",required=false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value="Patch Version",required=false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value="AID",required=true) @HeaderParam("aid") String aid, + @ApiParam(value="Application namespace",required=true) @HeaderParam("ns") String ns, @ApiParam(value="userId",required=true) @HeaderParam("userId") String userId, + @ApiParam(value="Password",required=true) @HeaderParam("password") String password, JsonUpdate updateObj, + @ApiParam(value="Key Space",required=true) @PathParam("keyspace") String keyspace, + @ApiParam(value="Table Name",required=true) @PathParam("tablename") String tablename, + @Context UriInfo info) throws Exception{ + return new RestMusicDataAPI().updateTable(version,minorVersion,patchVersion,aid, ns, userId, password, updateObj, keyspace, tablename, info); + } + + /** + * + * @param delObj + * @param keyspace + * @param tablename + * @param info + * @return + * @throws Exception + */ + @DELETE + @Path("/keyspaces/{keyspace}/{qname}/rows") + @ApiOperation(value = "", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response deleteFromQ( + @ApiParam(value="Major Version",required=true) @PathParam("version") String version, + @ApiParam(value="Minor Version",required=false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value="Patch Version",required=false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value="AID",required=true) @HeaderParam("aid") String aid, + @ApiParam(value="Application namespace",required=true) @HeaderParam("ns") String ns, + @ApiParam(value="userId",required=true) @HeaderParam("userId") String userId, + @ApiParam(value="Password",required=true) @HeaderParam("password") String password, JsonDelete delObj, + @ApiParam(value="Key Space",required=true) @PathParam("keyspace") String keyspace, + @ApiParam(value="Table Name",required=true) @PathParam("tablename") String tablename, + @Context UriInfo info) throws Exception{ + return new RestMusicDataAPI().deleteFromTable(version,minorVersion,patchVersion,aid, ns, userId, password, delObj, keyspace, tablename, info); + } + + /** + * + * @param keyspace + * @param tablename + * @param info + * @return + * @throws Exception + */ + @GET + @Path("/keyspaces/{keyspace}/{qname}/peek") + @ApiOperation(value = "", response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + public Map<String, HashMap<String, Object>> peek( + @ApiParam(value="Major Version",required=true) @PathParam("version") String version, + @ApiParam(value="Minor Version",required=false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value="Patch Version",required=false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value="AID",required=true) @HeaderParam("aid") String aid, + @ApiParam(value="Application namespace",required=true) @HeaderParam("ns") String ns, + @ApiParam(value="userId",required=true) @HeaderParam("userId") String userId, + @ApiParam(value="Password",required=true) @HeaderParam("password") String password, + @ApiParam(value="Key Space",required=true) @PathParam("keyspace") String keyspace, + @ApiParam(value="Table Name",required=true) @PathParam("tablename") String tablename, + @Context UriInfo info) throws Exception{ + int limit =1; //peek must return just the top row + PreparedQueryObject query = new RestMusicDataAPI().selectSpecificQuery(version,minorVersion,patchVersion,aid, ns, userId, password,keyspace,tablename,info,limit); + ResultSet results = MusicCore.get(query); + return MusicCore.marshallResults(results); + + } + + /** + * + * + * @param keyspace + * @param tablename + * @param info + * @return + * @throws Exception + */ + @GET + @Path("/keyspaces/{keyspace}/{qname}/filter") + @ApiOperation(value = "", response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + public Map<String, HashMap<String, Object>> filter( + @ApiParam(value="Major Version",required=true) @PathParam("version") String version, + @ApiParam(value="Minor Version",required=false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value="Patch Version",required=false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value="AID",required=true) @HeaderParam("aid") String aid, + @ApiParam(value="Application namespace",required=true) @HeaderParam("ns") String ns, + @ApiParam(value="userId",required=true) @HeaderParam("userId") String userId, + @ApiParam(value="Password",required=true) @HeaderParam("password") String password, + @ApiParam(value="Key Space",required=true) @PathParam("keyspace") String keyspace, + @ApiParam(value="Table Name",required=true) @PathParam("tablename") String tablename, + @Context UriInfo info) throws Exception{ + int limit =-1; + PreparedQueryObject query = new RestMusicDataAPI().selectSpecificQuery(version,minorVersion,patchVersion,aid, ns, userId, password,keyspace,tablename,info,limit); + ResultSet results = MusicCore.get(query); + return MusicCore.marshallResults(results); + } + + /** + * + * @param tabObj + * @param keyspace + * @param tablename + * @throws Exception + */ + @DELETE + @ApiOperation(value = "", response = Void.class) + @Path("/keyspaces/{keyspace}/{qname}") + public Response dropQ( + @ApiParam(value="Major Version",required=true) @PathParam("version") String version, + @ApiParam(value="Minor Version",required=false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value="Patch Version",required=false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value="AID",required=true) @HeaderParam("aid") String aid, + @ApiParam(value="Application namespace",required=true) @HeaderParam("ns") String ns, + @ApiParam(value="userId",required=true) @HeaderParam("userId") String userId, + @ApiParam(value="Password",required=true) @HeaderParam("password") String password, JsonTable tabObj, + @ApiParam(value="Key Space",required=true) @PathParam("keyspace") String keyspace, + @ApiParam(value="Table Name",required=true) @PathParam("tablename") String tablename) throws Exception{ + return new RestMusicDataAPI().dropTable(version,minorVersion,patchVersion,aid, ns, userId, password, keyspace, tablename); + } +} diff --git a/jar/src/main/java/org/onap/music/rest/RestMusicTestAPI.java b/jar/src/main/java/org/onap/music/rest/RestMusicTestAPI.java new file mode 100644 index 00000000..287fa176 --- /dev/null +++ b/jar/src/main/java/org/onap/music/rest/RestMusicTestAPI.java @@ -0,0 +1,67 @@ +/* + * ============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.rest; + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; + +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.main.MusicUtil; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + + +@Path("/v{version: [0-9]+}/test") +@Api(value="Test Api") +public class RestMusicTestAPI { + + @SuppressWarnings("unused") + private EELFLoggerDelegate logger =EELFLoggerDelegate.getLogger(RestMusicTestAPI.class); + + /** + * Returns a test JSON. This will confirm that REST is working. + * @return + */ + @GET + @ApiOperation(value = "Get Test", response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + public Map<String, HashMap<String, String>> simpleTests( + @Context HttpServletResponse response) { + response.addHeader("X-latestVersion",MusicUtil.getVersion()); + Map<String, HashMap<String, String>> testMap = new HashMap<>(); + for(int i=0; i < 3; i++){ + HashMap<String, String> innerMap = new HashMap<>(); + innerMap.put(i+"", i+1+""); + innerMap.put(i+1+"", i+2+""); + testMap.put(i+"", innerMap); + } + return testMap; + } +} diff --git a/jar/src/main/java/org/onap/music/rest/RestMusicVersionAPI.java b/jar/src/main/java/org/onap/music/rest/RestMusicVersionAPI.java new file mode 100644 index 00000000..a5f2ac49 --- /dev/null +++ b/jar/src/main/java/org/onap/music/rest/RestMusicVersionAPI.java @@ -0,0 +1,63 @@ +/* + * ============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.rest; + +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; + +import org.onap.music.response.jsonobjects.JsonResponse; +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; + + +@Path("/v{version: [0-9]+}/version") +@Api(value="Version Api") +public class RestMusicVersionAPI { + + private EELFLoggerDelegate logger =EELFLoggerDelegate.getLogger(RestMusicVersionAPI.class); + + /** + * Get the version of MUSIC + * @return + */ + @GET + @ApiOperation(value = "Get Version", response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + public Map<String,Object> version(@Context HttpServletResponse response) { + 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(); + } +}
\ No newline at end of file diff --git a/jar/src/main/resources/LICENSE.txt b/jar/src/main/resources/LICENSE.txt new file mode 100644 index 00000000..cc6cdea5 --- /dev/null +++ b/jar/src/main/resources/LICENSE.txt @@ -0,0 +1,24 @@ + +The following license applies to all files in this and sub-directories. Licenses +are included in individual source files where appropriate, and if it differs +from this text, it supersedes this. Any file that does not have license text +defaults to being covered by this text; not all files support the addition of +licenses. +# +# ------------------------------------------------------------------------- +# 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. +# +# ------------------------------------------------------------------------- +#
\ No newline at end of file diff --git a/jar/src/main/resources/Resources.properties b/jar/src/main/resources/Resources.properties new file mode 100644 index 00000000..72269cb8 --- /dev/null +++ b/jar/src/main/resources/Resources.properties @@ -0,0 +1,50 @@ +#============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============================================= +#==================================================================== +#Resource key=Error Code|Message text|Resolution text |Description text +LOADING_DEFAULT_LOG_CONFIGURATION=\ + EELF0001I|\ + Loading default logging configuration from system resource file "{0}"|\ + No external logging configurations were defined or found, So verify the default logging configuration from system resource file (../logback.xml). |\ + Loading default logging configuration from system resource file +LOADING_LOG_CONFIGURATION=EELF0002I|\ + Loading logging configuration from file "{0}"|\ + Verify the correct logging configuration file is loaded. |\ + Loading logging configuration for specific file +LOGGING_ALREADY_INITIALIZED=\ + EELF0003W|\ + Logging has already been initialized, check the container logging definitions to ensure they represent your desired logging configuration.|\ + Verify the container logging definitions to ensure they represent your desired logging configuration. |\ + Logging has already been initialized, check the container logging definitions to ensure they represent your desired logging configuration. +NO_LOG_CONFIGURATION=\ + EELF0004E|\ + No log configuration could be found or defaulted!|\ + No external and default logging configuration file. |\ + No log configuration could be found or defaulted! +SEARCHING_LOG_CONFIGURATION=\ + EELF0005I|\ + Searching path "{0}" for log configuration file "{1}"|\ + Verify the correct Path({user.home};etc;../etc) and filename (eelf.logging.file).|\ + Searching path for specific log configuration file. +UNSUPPORTED_LOGGING_FRAMEWORK=\ + EELF0006E|\ + An unsupported logging framework is bound to SLF4J. |\ + Verify your logging frameworks.|\ + An unsupported logging framework is bound to SLF4J. + diff --git a/jar/src/main/resources/cache.ccf b/jar/src/main/resources/cache.ccf new file mode 100644 index 00000000..acc6831c --- /dev/null +++ b/jar/src/main/resources/cache.ccf @@ -0,0 +1,56 @@ +# DEFAULT CACHE REGION +jcs.default= +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.cacheattributes.UseMemoryShrinker=false +jcs.default.cacheattributes.MaxMemoryIdleTime=3600 +jcs.default.cacheattributes.ShrinkerInterval=60 +jcs.default.elementattributes=org.apache.commons.jcs.engine.ElementAttributes +jcs.default.elementattributes.IsEternal=false +jcs.default.elementattributes.MaxLife=21600 +jcs.default.elementattributes.IdleTime=1800 +jcs.default.elementattributes.IsSpool=true +jcs.default.elementattributes.IsRemote=true +jcs.default.elementattributes.IsLateral=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 + + + + diff --git a/jar/src/main/resources/logback.xml b/jar/src/main/resources/logback.xml new file mode 100644 index 00000000..fe7f54ae --- /dev/null +++ b/jar/src/main/resources/logback.xml @@ -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============================================= + ==================================================================== +--> +<configuration scan="true" scanPeriod="3 seconds"> + <!--<jmxConfigurator /> --> + <!-- directory path for all other type logs --> + <property name="logDir" value="/opt/app/music/logs" /> + + <!-- directory path for debugging type logs --> + <property name="debugDir" value="debug-logs" /> + + <!-- specify the component name --> + <!-- <property name="componentName" value="EELF"></property> --> + <property name="componentName" value="MUSIC"></property> + + <!-- log file names --> + <property name="generalLogName" value="music" /> + <property name="securityLogName" value="security" /> + <property name="errorLogName" value="error" /> + <property name="metricsLogName" value="metrics" /> + <property name="auditLogName" value="audit" /> + <property name="debugLogName" value="debug" /> + <property name="defaultPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n" /> + <property name="applicationLoggerPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %msg%n" /> + <property name="auditLoggerPattern" value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{VirtualServerName}|%X{ServiceName}|%X{PartnerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}|%X{Unused}|%X{ProcessKey}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}| %msg%n" /> + <property name="metricsLoggerPattern" value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{VirtualServerName}|%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}|%X{Unused}|%X{ProcessKey}|%X{TargetVirtualEntity}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}| %msg%n" /> + <property name="errorLoggerPattern" value= "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %msg%n " /> + <property name="debugLoggerPattern" value="%date{ISO8601,UTC}|%X{RequestId}| %msg%n" ></property> + <property name="logDirectory" value="${logDir}/${componentName}" /> + <property name="debugLogDirectory" value="${debugDir}/${componentName}" /> + <!-- Example evaluator filter applied against console appender --> + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <!-- <encoder> + <pattern>${defaultPattern}</pattern> + </encoder> --> + <layout class=""> + <pattern> + %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n + </pattern> + </layout> + </appender> + + <!-- ============================================================================ --> + <!-- EELF Appenders --> + <!-- ============================================================================ --> + <appender name="EELF" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${generalLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${generalLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>${applicationLoggerPattern}</pattern> + </encoder> + </appender> + + <appender name="asyncEELF" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <includeCallerData>true</includeCallerData> + <appender-ref ref="EELF" /> + </appender> + + <!-- EELF Security Appender. This appender is used to record security events + to the security log file. Security events are separate from other loggers + in EELF so that security log records can be captured and managed in a secure + way separate from the other logs. This appender is set to never discard any + events. --> + <appender name="EELFSecurity" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${securityLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${securityLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n </pattern> + </encoder> + </appender> + + <appender name="asyncEELFSecurity" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <discardingThreshold>0</discardingThreshold> + <appender-ref ref="EELFSecurity" /> + </appender> + + + + + <!-- EELF Audit Appender. This appender is used to record audit engine + related logging events. The audit logger and appender are specializations + of the EELF application root logger and appender. This can be used to segregate + Policy engine events from other components, or it can be eliminated to record + these events as part of the application root log. --> + + <appender name="EELFAudit" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${auditLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${auditLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>${auditLoggerPattern}</pattern> + </encoder> + </appender> + <appender name="asyncEELFAudit" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFAudit" /> + </appender> + +<appender name="EELFMetrics" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${metricsLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${metricsLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <!-- <pattern>"%d{HH:mm:ss.SSS} [%thread] %-5level %logger{1024} - + %msg%n"</pattern> --> + <pattern>${metricsLoggerPattern}</pattern> + </encoder> + </appender> + + + <appender name="asyncEELFMetrics" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFMetrics"/> + </appender> + + <appender name="EELFError" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${errorLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${errorLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>${errorLoggerPattern}</pattern> + </encoder> + </appender> + + <appender name="asyncEELFError" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFError"/> + </appender> + + <appender name="EELFDebug" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${debugLogDirectory}/${debugLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${debugLogDirectory}/${debugLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>${debugLoggerPattern}</pattern> + </encoder> + </appender> + + <appender name="asyncEELFDebug" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFDebug" /> + <includeCallerData>true</includeCallerData> + </appender> + + + <!-- ============================================================================ --> + <!-- EELF loggers --> + <!-- ============================================================================ --> + <logger name="com.att.eelf" level="info" additivity="false"> + <appender-ref ref="asyncEELF" /> + + </logger> + <logger name="com.att.eelf.security" level="info" additivity="false"> + <appender-ref ref="asyncEELFSecurity" /> + + </logger> + + + <logger name="com.att.eelf.audit" level="info" additivity="false"> + <appender-ref ref="asyncEELFAudit" /> + + </logger> + + <logger name="com.att.eelf.metrics" level="info" additivity="false"> + <appender-ref ref="asyncEELFMetrics" /> + + </logger> + + + <logger name="com.att.eelf.error" level="error" additivity="false"> + <appender-ref ref="asyncEELFError" /> + + </logger> + + <logger name="com.att.eelf.debug" level="debug" additivity="false"> + <appender-ref ref="asyncEELFDebug" /> + + </logger> + + + + + <root level="INFO"> + <appender-ref ref="asyncEELF" /> + <appender-ref ref="STDOUT" /> + </root> + +</configuration> diff --git a/jar/src/main/resources/project.properties b/jar/src/main/resources/project.properties new file mode 100644 index 00000000..199afa33 --- /dev/null +++ b/jar/src/main/resources/project.properties @@ -0,0 +1,4 @@ +version=${project.version} +artifactId=${project.artifactId} +music.properties=/opt/app/music/etc/music.properties + diff --git a/jar/src/test/java/LICENSE.txt b/jar/src/test/java/LICENSE.txt new file mode 100644 index 00000000..cc6cdea5 --- /dev/null +++ b/jar/src/test/java/LICENSE.txt @@ -0,0 +1,24 @@ + +The following license applies to all files in this and sub-directories. Licenses +are included in individual source files where appropriate, and if it differs +from this text, it supersedes this. Any file that does not have license text +defaults to being covered by this text; not all files support the addition of +licenses. +# +# ------------------------------------------------------------------------- +# 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. +# +# ------------------------------------------------------------------------- +#
\ No newline at end of file diff --git a/jar/src/test/java/org/onap/music/unittests/CassandraCQL.java b/jar/src/test/java/org/onap/music/unittests/CassandraCQL.java new file mode 100644 index 00000000..a4c250c2 --- /dev/null +++ b/jar/src/test/java/org/onap/music/unittests/CassandraCQL.java @@ -0,0 +1,256 @@ +/* + * ============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; + +/** + * @author srupane + * + */ + +import java.io.IOException; +import java.math.BigInteger; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import com.datastax.driver.core.Cluster; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.exceptions.NoHostAvailableException; +import org.apache.cassandra.exceptions.ConfigurationException; +import org.apache.thrift.transport.TTransportException; +import org.cassandraunit.utils.EmbeddedCassandraServerHelper; +import org.onap.music.datastore.MusicDataStore; +import org.onap.music.datastore.PreparedQueryObject; + +public class CassandraCQL { + + public static final String createKeySpace = + "CREATE KEYSPACE IF NOT EXISTS testCassa WITH replication = " + +"{'class':'SimpleStrategy','replication_factor':1} AND durable_writes = true;"; + + public static final String dropKeyspace = "DROP KEYSPACE IF EXISTS testCassa"; + + public static final String createTableEmployees = + "CREATE TABLE IF NOT EXISTS testCassa.employees " + + "(vector_ts text,empId uuid,empName text,empSalary varint,address Map<text,text>,PRIMARY KEY (empName)) " + + "WITH comment='Financial Info of employees' " + + "AND compression={'sstable_compression':'DeflateCompressor','chunk_length_kb':64} " + + "AND compaction={'class':'SizeTieredCompactionStrategy','min_threshold':6};"; + + public static final String insertIntoTablePrepared1 = + "INSERT INTO testCassa.employees (vector_ts,empId,empName,empSalary) VALUES (?,?,?,?); "; + + public static final String insertIntoTablePrepared2 = + "INSERT INTO testCassa.employees (vector_ts,empId,empName,empSalary,address) VALUES (?,?,?,?,?);"; + + public static final String selectALL = "SELECT * FROM testCassa.employees;"; + + public static final String selectSpecific = + "SELECT * FROM testCassa.employees WHERE empName= ?;"; + + public static final String updatePreparedQuery = + "UPDATE testCassa.employees SET vector_ts=?,address= ? WHERE empName= ?;"; + + public static final String deleteFromTable = " "; + + public static final String deleteFromTablePrepared = " "; + + // Set Values for Prepared Query + + public static List<Object> setPreparedInsertValues1() { + + List<Object> preppreparedInsertValues1 = new ArrayList<>(); + String vectorTs = + String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis()); + UUID empId = UUID.fromString("abc66ccc-d857-4e90-b1e5-df98a3d40cd6"); + BigInteger empSalary = BigInteger.valueOf(23443); + String empName = "Mr Test one"; + preppreparedInsertValues1.add(vectorTs); + preppreparedInsertValues1.add(empId); + preppreparedInsertValues1.add(empName); + preppreparedInsertValues1.add(empSalary); + return preppreparedInsertValues1; + } + + public static List<Object> setPreparedInsertValues2() { + + List<Object> preparedInsertValues2 = new ArrayList<>(); + String vectorTs = + String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis()); + UUID empId = UUID.fromString("abc434cc-d657-4e90-b4e5-df4223d40cd6"); + BigInteger empSalary = BigInteger.valueOf(45655); + String empName = "Mr Test two"; + Map<String, String> address = new HashMap<>(); + preparedInsertValues2.add(vectorTs); + preparedInsertValues2.add(empId); + preparedInsertValues2.add(empName); + preparedInsertValues2.add(empSalary); + address.put("Street", "1 some way"); + address.put("City", "Some town"); + preparedInsertValues2.add(address); + return preparedInsertValues2; + } + + public static List<Object> setPreparedUpdateValues() { + + List<Object> preparedUpdateValues = new ArrayList<>(); + String vectorTs = + String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis()); + Map<String, String> address = new HashMap<>(); + preparedUpdateValues.add(vectorTs); + String empName = "Mr Test one"; + address.put("Street", "101 Some Way"); + address.put("City", "New York"); + preparedUpdateValues.add(address); + preparedUpdateValues.add(empName); + return preparedUpdateValues; + } + + // Generate Different Prepared Query Objects + /** + * Query Object for Get. + * + * @return + */ + public static PreparedQueryObject setPreparedGetQuery() { + + PreparedQueryObject queryObject = new PreparedQueryObject(); + String empName1 = "Mr Test one"; + queryObject.appendQueryString(selectSpecific); + queryObject.addValue(empName1); + return queryObject; + } + + /** + * Query Object 1 for Insert. + * + * @return {@link PreparedQueryObject} + */ + public static PreparedQueryObject setPreparedInsertQueryObject1() { + + PreparedQueryObject queryobject = new PreparedQueryObject(); + queryobject.appendQueryString(insertIntoTablePrepared1); + List<Object> values = setPreparedInsertValues1(); + if (!values.isEmpty() || values != null) { + for (Object o : values) { + queryobject.addValue(o); + } + } + return queryobject; + + } + + /** + * Query Object 2 for Insert. + * + * @return {@link PreparedQueryObject} + */ + public static PreparedQueryObject setPreparedInsertQueryObject2() { + + PreparedQueryObject queryobject = new PreparedQueryObject(); + queryobject.appendQueryString(insertIntoTablePrepared2); + List<Object> values = setPreparedInsertValues2(); + if (!values.isEmpty() || values != null) { + for (Object o : values) { + queryobject.addValue(o); + } + } + return queryobject; + + } + + /** + * Query Object for Update. + * + * @return {@link PreparedQueryObject} + */ + public static PreparedQueryObject setPreparedUpdateQueryObject() { + + PreparedQueryObject queryobject = new PreparedQueryObject(); + queryobject.appendQueryString(updatePreparedQuery); + List<Object> values = setPreparedUpdateValues(); + if (!values.isEmpty() || values != null) { + for (Object o : values) { + queryobject.addValue(o); + } + } + return queryobject; + + } + + private static ArrayList<String> getAllPossibleLocalIps() { + ArrayList<String> allPossibleIps = new ArrayList<String>(); + try { + Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); + while (en.hasMoreElements()) { + NetworkInterface ni = (NetworkInterface) en.nextElement(); + Enumeration<InetAddress> ee = ni.getInetAddresses(); + while (ee.hasMoreElements()) { + InetAddress ia = (InetAddress) ee.nextElement(); + allPossibleIps.add(ia.getHostAddress()); + } + } + } catch (SocketException e) { + System.out.println(e.getMessage()); + } + return allPossibleIps; + } + + public static MusicDataStore connectToEmbeddedCassandra() { + Iterator<String> it = getAllPossibleLocalIps().iterator(); + String address = "localhost"; + + Cluster cluster = null; + Session session = null; + while (it.hasNext()) { + try { + + try { + EmbeddedCassandraServerHelper.startEmbeddedCassandra(80000); + } catch (ConfigurationException | TTransportException | IOException e) { + + System.out.println(e.getMessage()); + } + + cluster = new Cluster.Builder().addContactPoint(address).withPort(9142).build(); + cluster.getConfiguration().getSocketOptions().setReadTimeoutMillis(20000); + session = cluster.connect(); + + break; + } catch (NoHostAvailableException e) { + address = it.next(); + System.out.println(e.getMessage()); + + } + } + return new MusicDataStore(cluster, session); + + } + +} diff --git a/jar/src/test/java/org/onap/music/unittests/JsonResponseTest.java b/jar/src/test/java/org/onap/music/unittests/JsonResponseTest.java new file mode 100644 index 00000000..9da10638 --- /dev/null +++ b/jar/src/test/java/org/onap/music/unittests/JsonResponseTest.java @@ -0,0 +1,83 @@ +/* + * ============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; + +import static org.junit.Assert.*; +import java.util.Map; +import org.junit.Test; +import org.onap.music.main.ResultType; +import org.onap.music.response.jsonobjects.JsonResponse; + +public class JsonResponseTest { + + JsonResponse result = null; + + @Test + public void testJsonResponseBooleanStringString() { + result = new JsonResponse(ResultType.SUCCESS).setError("error").setMusicVersion("version"); + assertEquals("error",result.getError()); + } + + @Test + public void testStatus() { + result = new JsonResponse(ResultType.SUCCESS); + result.setStatus(ResultType.SUCCESS); + assertEquals(ResultType.SUCCESS, result.getStatus()); + result = new JsonResponse(ResultType.FAILURE).setError("error").setMusicVersion("version"); + assertEquals(ResultType.FAILURE, result.getStatus()); + } + + @Test + public void testError() { + result = new JsonResponse(ResultType.FAILURE); + result.setError("error"); + assertTrue(result.getError().equals("error")); + result.setError(""); + assertFalse(result.getError().equals("error")); + } + + @Test + public void testVersion() { + result = new JsonResponse(ResultType.SUCCESS); + result.setMusicVersion("version"); + assertTrue(result.getMusicVersion().equals("version")); + result.setMusicVersion(""); + assertFalse(result.getMusicVersion().equals("version")); + } + + @Test + public void testToMap() { + result = new JsonResponse(ResultType.SUCCESS).setError("error").setMusicVersion("1.0"); + Map<String,Object> myMap = result.toMap(); + assertTrue(myMap.containsKey("status")); + assertEquals(ResultType.SUCCESS, myMap.get("status")); + assertEquals("error", myMap.get("error")); + assertEquals("1.0", myMap.get("version")); + + result = new JsonResponse(ResultType.FAILURE); + myMap = result.toMap(); + assertTrue(myMap.containsKey("status")); + assertEquals(ResultType.FAILURE, myMap.get("status")); + } + +} diff --git a/jar/src/test/java/org/onap/music/unittests/MusicDataStoreTest.java b/jar/src/test/java/org/onap/music/unittests/MusicDataStoreTest.java new file mode 100644 index 00000000..16d2af02 --- /dev/null +++ b/jar/src/test/java/org/onap/music/unittests/MusicDataStoreTest.java @@ -0,0 +1,162 @@ +/* + * ============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; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; +import org.mockito.Mock; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; + +import org.onap.music.datastore.MusicDataStore; +import org.onap.music.datastore.PreparedQueryObject; + +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.TableMetadata; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class MusicDataStoreTest { + + static MusicDataStore dataStore; + static PreparedQueryObject testObject; + + @BeforeClass + public static void init() { + dataStore = CassandraCQL.connectToEmbeddedCassandra(); + + } + + @AfterClass + public static void close() throws MusicServiceException, MusicQueryException { + + testObject = new PreparedQueryObject(); + testObject.appendQueryString(CassandraCQL.dropKeyspace); + dataStore.executePut(testObject, "eventual"); + dataStore.close(); + + } + + @Test + public void Test1_SetUp() throws MusicServiceException, MusicQueryException { + boolean result = false; + testObject = new PreparedQueryObject(); + testObject.appendQueryString(CassandraCQL.createKeySpace); + result = dataStore.executePut(testObject, "eventual");; + testObject = new PreparedQueryObject(); + testObject.appendQueryString(CassandraCQL.createTableEmployees); + result = dataStore.executePut(testObject, "eventual"); + assertEquals(true, result); + + } + + @Test + public void Test2_ExecutePut_eventual_insert() throws MusicServiceException, MusicQueryException { + testObject = CassandraCQL.setPreparedInsertQueryObject1(); + boolean result = dataStore.executePut(testObject, "eventual"); + assertEquals(true, result); + } + + @Test + public void Test3_ExecutePut_critical_insert() throws MusicServiceException, MusicQueryException { + testObject = CassandraCQL.setPreparedInsertQueryObject2(); + boolean result = dataStore.executePut(testObject, "Critical"); + assertEquals(true, result); + } + + @Test + public void Test4_ExecutePut_eventual_update() throws MusicServiceException, MusicQueryException { + testObject = CassandraCQL.setPreparedUpdateQueryObject(); + boolean result = false; + result = dataStore.executePut(testObject, "eventual"); + assertEquals(true, result); + } + + @Test + public void Test5_ExecuteEventualGet() throws MusicServiceException, MusicQueryException { + testObject = new PreparedQueryObject(); + testObject.appendQueryString(CassandraCQL.selectALL); + boolean result = false; + int count = 0; + ResultSet output = null; + output = dataStore.executeEventualGet(testObject); + System.out.println(output); + ; + for (Row row : output) { + count++; + System.out.println(row.toString()); + } + if (count == 2) { + result = true; + } + assertEquals(true, result); + } + + @Test + public void Test6_ExecuteCriticalGet() throws MusicServiceException, MusicQueryException { + testObject = CassandraCQL.setPreparedGetQuery(); + boolean result = false; + int count = 0; + ResultSet output = null; + output = dataStore.executeCriticalGet(testObject); + System.out.println(output); + ; + for (Row row : output) { + count++; + System.out.println(row.toString()); + } + if (count == 1) { + result = true; + } + assertEquals(true, result); + } + + @Test(expected = NullPointerException.class) + public void Test7_exception() { + PreparedQueryObject queryObject = null; + try { + dataStore.executePut(queryObject, "critical"); + } catch (MusicQueryException | MusicServiceException e) { + System.out.println(e.getMessage()); + } + } + + @Test + public void Test8_columnDataType() { + DataType data = dataStore.returnColumnDataType("testCassa", "employees", "empName"); + String datatype = data.toString(); + assertEquals("text",datatype); + } + + @Test + public void Test8_columnMetdaData() { + TableMetadata data = dataStore.returnColumnMetadata("testCassa", "employees"); + assertNotNull(data); + } +} diff --git a/jar/src/test/java/org/onap/music/unittests/MusicUtilTest.java b/jar/src/test/java/org/onap/music/unittests/MusicUtilTest.java new file mode 100644 index 00000000..b117c330 --- /dev/null +++ b/jar/src/test/java/org/onap/music/unittests/MusicUtilTest.java @@ -0,0 +1,207 @@ +/* + * ============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; + +import static org.junit.Assert.*; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import org.apache.cassandra.exceptions.PreparedQueryNotFoundException; +import org.junit.Test; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.main.MusicUtil; +import com.datastax.driver.core.DataType; +import javassist.CodeConverter.ArrayAccessReplacementMethodNames; + +public class MusicUtilTest { + + @Test + public void testGetCassName() { + MusicUtil.setCassName("Cassandra"); + assertTrue(MusicUtil.getCassName().equals("Cassandra")); + } + + @Test + public void testGetCassPwd() { + MusicUtil.setCassPwd("Cassandra"); + assertTrue(MusicUtil.getCassPwd().equals("Cassandra")); + } + + @Test + public void testGetAafEndpointUrl() { + MusicUtil.setAafEndpointUrl("url"); + assertEquals(MusicUtil.getAafEndpointUrl(),"url"); + } + + @Test + public void testGetMyId() { + MusicUtil.setMyId(1); + assertEquals(MusicUtil.getMyId(),1); + } + + @Test + public void testGetAllIds() { + List<String> ids = new ArrayList<String>(); + ids.add("1"); + ids.add("2"); + ids.add("3"); + MusicUtil.setAllIds(ids); + assertEquals(MusicUtil.getAllIds().get(0),"1"); + } + +// @Test +// public void testGetPublicIp() { +// MusicUtil.setPublicIp("10.0.0.1"); +// assertEquals(MusicUtil.getPublicIp(),"10.0.0.1"); +// } + + @Test + public void testGetAllPublicIps() { + List<String> ips = new ArrayList<String>(); + ips.add("10.0.0.1"); + ips.add("10.0.0.2"); + ips.add("10.0.0.3"); + MusicUtil.setAllPublicIps(ips); + assertEquals(MusicUtil.getAllPublicIps().get(1),"10.0.0.2"); + } + + @Test + public void testGetPropkeys() { + assertEquals(MusicUtil.getPropkeys()[2],"music.ip"); + } + + @Test + public void testGetMusicRestIp() { + MusicUtil.setMusicRestIp("localhost"); + assertEquals(MusicUtil.getMusicRestIp(),"localhost"); + } + + @Test + public void testGetMusicPropertiesFilePath() { + MusicUtil.setMusicPropertiesFilePath("filepath"); + assertEquals(MusicUtil.getMusicPropertiesFilePath(),"filepath"); + } + + @Test + public void testGetDefaultLockLeasePeriod() { + MusicUtil.setDefaultLockLeasePeriod(5000); + assertEquals(MusicUtil.getDefaultLockLeasePeriod(),5000); + } + + @Test + public void testIsDebug() { + MusicUtil.setDebug(true); + assertTrue(MusicUtil.isDebug()); + } + + @Test + public void testGetVersion() { + MusicUtil.setVersion("1.0.0"); + 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 testGetMyCassaHost() { + MusicUtil.setMyCassaHost("10.0.0.2"); + assertEquals(MusicUtil.getMyCassaHost(),"10.0.0.2"); + } + + @Test + public void testGetDefaultMusicIp() { + MusicUtil.setDefaultMusicIp("10.0.0.2"); + assertEquals(MusicUtil.getDefaultMusicIp(),"10.0.0.2"); + } + +// @Test +// public void testGetTestType() { +// fail("Not yet implemented"); // TODO +// } + + @Test + public void testIsValidQueryObject() { + PreparedQueryObject myQueryObject = new PreparedQueryObject(); + myQueryObject.appendQueryString("select * from apple where type = ?"); + myQueryObject.addValue("macintosh"); + assertTrue(MusicUtil.isValidQueryObject(true,myQueryObject)); + + myQueryObject.appendQueryString("select * from apple"); + assertTrue(MusicUtil.isValidQueryObject(false,myQueryObject)); + + myQueryObject.appendQueryString("select * from apple where type = ?"); + assertFalse(MusicUtil.isValidQueryObject(true,myQueryObject)); + + myQueryObject = new PreparedQueryObject(); + myQueryObject.appendQueryString(""); + System.out.println("#######" + myQueryObject.getQuery().isEmpty()); + assertFalse(MusicUtil.isValidQueryObject(false,myQueryObject)); + + + } + + @Test + public void testConvertToCQLDataType() throws Exception { + Map<String,Object> myMap = new HashMap<String,Object>(); + myMap.put("name","tom"); + assertEquals(MusicUtil.convertToCQLDataType(DataType.varchar(),"Happy People"),"'Happy People'"); + assertEquals(MusicUtil.convertToCQLDataType(DataType.uuid(),UUID.fromString("29dc2afa-c2c0-47ae-afae-e72a645308ab")),"29dc2afa-c2c0-47ae-afae-e72a645308ab"); + assertEquals(MusicUtil.convertToCQLDataType(DataType.blob(),"Hi"),"Hi"); + assertEquals(MusicUtil.convertToCQLDataType(DataType.map(DataType.varchar(),DataType.varchar()),myMap),"{'name':'tom'}"); + } + + @Test + public void testConvertToActualDataType() throws Exception { + assertEquals(MusicUtil.convertToActualDataType(DataType.varchar(),"Happy People"),"Happy People"); + assertEquals(MusicUtil.convertToActualDataType(DataType.uuid(),"29dc2afa-c2c0-47ae-afae-e72a645308ab"),UUID.fromString("29dc2afa-c2c0-47ae-afae-e72a645308ab")); + assertEquals(MusicUtil.convertToActualDataType(DataType.varint(),"1234"),BigInteger.valueOf(Long.parseLong("1234"))); + assertEquals(MusicUtil.convertToActualDataType(DataType.bigint(),"123"),Long.parseLong("123")); + assertEquals(MusicUtil.convertToActualDataType(DataType.cint(),"123"),Integer.parseInt("123")); + 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")); + Map<String,Object> myMap = new HashMap<String,Object>(); + myMap.put("name","tom"); + assertEquals(MusicUtil.convertToActualDataType(DataType.map(DataType.varchar(),DataType.varchar()),myMap),myMap); + + } + + @Test + public void testJsonMaptoSqlString() throws Exception { + Map<String,Object> myMap = new HashMap<>(); + myMap.put("name","tom"); + myMap.put("value",5); + String result = MusicUtil.jsonMaptoSqlString(myMap,","); + assertTrue(result.contains("name")); + assertTrue(result.contains("value")); + } + +} diff --git a/jar/src/test/java/org/onap/music/unittests/ResultTypeTest.java b/jar/src/test/java/org/onap/music/unittests/ResultTypeTest.java new file mode 100644 index 00000000..012629e0 --- /dev/null +++ b/jar/src/test/java/org/onap/music/unittests/ResultTypeTest.java @@ -0,0 +1,43 @@ +/* + * ============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; + +import static org.junit.Assert.*; +import org.junit.Test; +import org.onap.music.main.ResultType; + +public class ResultTypeTest { + + @Test + public void testResultType() { + assertEquals("SUCCESS",ResultType.SUCCESS.name()); + assertEquals("FAILURE",ResultType.FAILURE.name()); + } + + @Test + public void testGetResult() { + assertEquals("Success",ResultType.SUCCESS.getResult()); + assertEquals("Failure",ResultType.FAILURE.getResult()); + } + +} diff --git a/jar/src/test/java/org/onap/music/unittests/ReturnTypeTest.java b/jar/src/test/java/org/onap/music/unittests/ReturnTypeTest.java new file mode 100644 index 00000000..c22b0155 --- /dev/null +++ b/jar/src/test/java/org/onap/music/unittests/ReturnTypeTest.java @@ -0,0 +1,83 @@ +/* + * ============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; + +import static org.junit.Assert.*; +import java.util.Map; +import org.apache.tools.ant.filters.TokenFilter.ContainsString; +import org.hamcrest.core.AnyOf; +import org.junit.Test; +import org.onap.music.main.ResultType; +import org.onap.music.main.ReturnType; + +public class ReturnTypeTest { + + @Test + public void testReturnType() { + ReturnType result = new ReturnType(ResultType.SUCCESS,"message"); + assertEquals(result.getMessage(),"message"); + assertEquals(result.getResult(),ResultType.SUCCESS); + } + + @Test + public void testTimingInfo() { + ReturnType result = new ReturnType(ResultType.SUCCESS,"message"); + result.setTimingInfo("123"); + assertEquals(result.getTimingInfo(),"123"); + } + + @Test + public void testGetResult() { + ReturnType result = new ReturnType(ResultType.FAILURE,"message"); + assertEquals(result.getResult(),ResultType.FAILURE); + } + + @Test + public void testGetMessage() { + ReturnType result = new ReturnType(ResultType.SUCCESS,"message"); + result.setMessage("NewMessage"); + assertEquals(result.getMessage(),"NewMessage"); + } + + @Test + public void testToJson() { + ReturnType result = new ReturnType(ResultType.SUCCESS,"message"); + String myJson = result.toJson(); + assertTrue(myJson.contains("message")); + } + + @Test + public void testToString() { + ReturnType result = new ReturnType(ResultType.SUCCESS,"message"); + String test = result.toString(); + assertTrue(test.contains("message")); + } + + @Test + public void testToMap() { + ReturnType result = new ReturnType(ResultType.SUCCESS,"message"); + Map<String, Object> myMap = result.toMap(); + assertTrue(myMap.containsKey("message")); + } + +} diff --git a/jar/src/test/java/org/onap/music/unittests/TestLockStore.java b/jar/src/test/java/org/onap/music/unittests/TestLockStore.java new file mode 100644 index 00000000..4dbc7b4f --- /dev/null +++ b/jar/src/test/java/org/onap/music/unittests/TestLockStore.java @@ -0,0 +1,53 @@ +/* + * ============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; + +import org.apache.log4j.Logger; +import org.onap.music.lockingservice.MusicLockingService; + +public class TestLockStore { + final static Logger logger = Logger.getLogger(TestLockStore.class); + + public static void main(String[] args) throws Exception { + String lockName = "/achristmkllas"; + MusicLockingService ml = new MusicLockingService(); + ml.deleteLock(lockName); + + + logger.info("lockname:" + lockName); + + String lockId1 = ml.createLockId(lockName); + logger.info("lockId1 " + lockId1); + logger.info(ml.isMyTurn(lockId1)); + + String lockId2 = ml.createLockId(lockName); + logger.info("lockId2 " + lockId2); + logger.info("check " + ml.isMyTurn("$bank$x-94608776321630264-0000000000")); + logger.info(ml.isMyTurn(lockId2)); + + // zkClient.unlock(lockId1); + // logger.info(ml.lock(lockId2)); + // zkClient.unlock(lockId2); + } + + +} diff --git a/jar/src/test/java/org/onap/music/unittests/TestMusicCore.java b/jar/src/test/java/org/onap/music/unittests/TestMusicCore.java new file mode 100644 index 00000000..e798aaf1 --- /dev/null +++ b/jar/src/test/java/org/onap/music/unittests/TestMusicCore.java @@ -0,0 +1,489 @@ +/* + * ============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; + +import static org.junit.Assert.*; +import static org.onap.music.main.MusicCore.mDstoreHandle; +import static org.onap.music.main.MusicCore.mLockHandle; + +import org.apache.zookeeper.KeeperException.NoNodeException; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.music.exceptions.MusicLockingException; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.lockingservice.MusicLockState; +import org.onap.music.lockingservice.MusicLockingService; +import org.onap.music.lockingservice.MusicLockState.LockStatus; +import org.onap.music.main.MusicCore; +import org.onap.music.main.MusicUtil; +import org.onap.music.main.ResultType; +import org.onap.music.main.ReturnType; +import org.onap.music.main.MusicCore.Condition; +import org.onap.music.datastore.MusicDataStore; +import org.onap.music.datastore.PreparedQueryObject; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Session; + +@RunWith(MockitoJUnitRunner.class) +public class TestMusicCore { + + @Mock + private Condition condition; + + @Mock + private ResultSet rs; + + @Mock + private PreparedQueryObject preparedQueryObject; + + @Mock + private Session session; + + @Before + public void setUp() { + mLockHandle = Mockito.mock(MusicLockingService.class); + + } + + @Test + public void testCreateLockReferenceforvalidlock() { + Mockito.when(mLockHandle.createLockId("/" + "test")).thenReturn("lock"); + String lockId = MusicCore.createLockReference("test"); + assertEquals("lock", lockId); + Mockito.verify(mLockHandle).createLockId("/" + "test"); + } + + @Test + public void testIsTableOrKeySpaceLock() { + Boolean result = MusicCore.isTableOrKeySpaceLock("ks1.tn1"); + assertTrue(result); + } + + @Test + public void testIsTableOrKeySpaceLockwithPrimarykey() { + Boolean result = MusicCore.isTableOrKeySpaceLock("ks1.tn1.pk1"); + assertFalse(result); + } + + @Test + public void testGetMusicLockState() throws MusicLockingException { + MusicLockState musicLockState = new MusicLockState(LockStatus.UNLOCKED, "id1"); + Mockito.when(mLockHandle.getLockState("ks1.tb1.pk1")).thenReturn(musicLockState); + MusicLockState mls = MusicCore.getMusicLockState("ks1.tb1.pk1"); + assertEquals(musicLockState, mls); + Mockito.verify(mLockHandle).getLockState("ks1.tb1.pk1"); + } + + @Test + public void testAcquireLockifisMyTurnTrue() throws MusicLockingException { + Mockito.when(mLockHandle.isMyTurn("id1")).thenReturn(true); + ReturnType lock = MusicCore.acquireLock("ks1.tn1", "id1"); + assertEquals(lock.getResult(), ResultType.SUCCESS); + Mockito.verify(mLockHandle).isMyTurn("id1"); + } + + @Test + public void testAcquireLockifisMyTurnFalse() throws MusicLockingException { + Mockito.when(mLockHandle.isMyTurn("id1")).thenReturn(false); + ReturnType lock = MusicCore.acquireLock("ks1.ts1", "id1"); + assertEquals(lock.getResult(), ResultType.FAILURE); + Mockito.verify(mLockHandle).isMyTurn("id1"); + } + + @Test + public void testAcquireLockifisMyTurnTrueandIsTableOrKeySpaceLockTrue() throws MusicLockingException { + Mockito.when(mLockHandle.isMyTurn("id1")).thenReturn(true); + ReturnType lock = MusicCore.acquireLock("ks1.tn1", "id1"); + assertEquals(lock.getResult(), ResultType.SUCCESS); + Mockito.verify(mLockHandle).isMyTurn("id1"); + } + + @Test + public void testAcquireLockifisMyTurnTrueandIsTableOrKeySpaceLockFalseandHaveLock() throws MusicLockingException { + MusicLockState musicLockState = new MusicLockState(LockStatus.LOCKED, "id1"); + Mockito.when(mLockHandle.isMyTurn("id1")).thenReturn(true); + Mockito.when(mLockHandle.getLockState("ks1.tn1.pk1")).thenReturn(musicLockState); + ReturnType lock = MusicCore.acquireLock("ks1.tn1.pk1", "id1"); + assertEquals(lock.getResult(), ResultType.SUCCESS); + Mockito.verify(mLockHandle).isMyTurn("id1"); + Mockito.verify(mLockHandle).getLockState("ks1.tn1.pk1"); + } + + @Test + public void testAcquireLockifisMyTurnTrueandIsTableOrKeySpaceLockFalseandDontHaveLock() throws MusicLockingException { + MusicLockState musicLockState = new MusicLockState(LockStatus.LOCKED, "id2"); + Mockito.when(mLockHandle.isMyTurn("id1")).thenReturn(true); + Mockito.when(mLockHandle.getLockState("ks1.tn1.pk1")).thenReturn(musicLockState); + ReturnType lock = MusicCore.acquireLock("ks1.tn1.pk1", "id1"); + assertEquals(lock.getResult(), ResultType.SUCCESS); + Mockito.verify(mLockHandle).isMyTurn("id1"); + Mockito.verify(mLockHandle).getLockState("ks1.tn1.pk1"); + } + + @Test + public void testAcquireLockifLockRefDoesntExist() throws MusicLockingException { + Mockito.when(mLockHandle.lockIdExists("bs1")).thenReturn(false); + ReturnType lock = MusicCore.acquireLock("ks1.ts1", "bs1"); + assertEquals(lock.getResult(), ResultType.FAILURE); + assertEquals(lock.getMessage(), "Lockid doesn't exist"); + Mockito.verify(mLockHandle).lockIdExists("bs1"); + } + + @Test + public void testAcquireLockWithLeasewithLease() throws MusicLockingException { + MusicLockState musicLockState = new MusicLockState(LockStatus.LOCKED, "id1"); + musicLockState.setLeasePeriod(0); + ReturnType expectedResult = new ReturnType(ResultType.SUCCESS, "Succes"); + Mockito.when(mLockHandle.getLockState("ks1.tn1.pk1")).thenReturn(musicLockState); + Mockito.when(mLockHandle.isMyTurn("id1")).thenReturn(true); + ReturnType actualResult = MusicCore.acquireLockWithLease("ks1.tn1.pk1", "id1", 6000); + assertEquals(expectedResult.getResult(), actualResult.getResult()); + Mockito.verify(mLockHandle).isMyTurn("id1"); + Mockito.verify(mLockHandle, Mockito.atLeastOnce()).getLockState("ks1.tn1.pk1"); + } + + @Test + public void testAcquireLockWithLeasewithException() throws MusicLockingException { + ReturnType expectedResult = new ReturnType(ResultType.FAILURE, "failure"); + Mockito.when(mLockHandle.getLockState("ks1.tn1.pk1")).thenThrow(new MusicLockingException()); + Mockito.when(mLockHandle.isMyTurn("id1")).thenReturn(true); + ReturnType actualResult = MusicCore.acquireLockWithLease("ks1.tn1.pk1", "id1", 6000); + assertEquals(expectedResult.getResult(), actualResult.getResult()); + Mockito.verify(mLockHandle, Mockito.atLeastOnce()).getLockState("ks1.tn1.pk1"); + } + + @Test + public void testAcquireLockWithLeasewithLockStatusLOCKED() throws MusicLockingException { + MusicLockState musicLockState = new MusicLockState(LockStatus.LOCKED, "id1"); + ReturnType expectedResult = new ReturnType(ResultType.SUCCESS, "Succes"); + Mockito.when(mLockHandle.getLockState("ks1.tn1.pk1")).thenReturn(musicLockState); + Mockito.when(mLockHandle.isMyTurn("id1")).thenReturn(true); + ReturnType actualResult = MusicCore.acquireLockWithLease("ks1.tn1.pk1", "id1", 6000); + assertEquals(expectedResult.getResult(), actualResult.getResult()); + Mockito.verify(mLockHandle).isMyTurn("id1"); + Mockito.verify(mLockHandle, Mockito.atLeastOnce()).getLockState("ks1.tn1.pk1"); + } + + @Test + public void testAcquireLockWithLeasewithLockStatusUNLOCKED() throws MusicLockingException { + MusicLockState musicLockState = new MusicLockState(LockStatus.UNLOCKED, "id1"); + ReturnType expectedResult = new ReturnType(ResultType.SUCCESS, "Succes"); + Mockito.when(mLockHandle.getLockState("ks1.tn1.pk1")).thenReturn(musicLockState); + Mockito.when(mLockHandle.isMyTurn("id1")).thenReturn(true); + ReturnType actualResult = MusicCore.acquireLockWithLease("ks1.tn1.pk1", "id1", 6000); + assertEquals(expectedResult.getResult(), actualResult.getResult()); + Mockito.verify(mLockHandle).isMyTurn("id1"); + Mockito.verify(mLockHandle, Mockito.atLeastOnce()).getLockState("ks1.tn1.pk1"); + + } + + @Test + public void testAcquireLockWithLeaseIfNotMyTurn() throws MusicLockingException { + MusicLockState musicLockState = new MusicLockState(LockStatus.UNLOCKED, "id1"); + ReturnType expectedResult = new ReturnType(ResultType.FAILURE, "Failure"); + Mockito.when(mLockHandle.getLockState("ks1.tn1.pk1")).thenReturn(musicLockState); + Mockito.when(mLockHandle.isMyTurn("id1")).thenReturn(false); + ReturnType actualResult = MusicCore.acquireLockWithLease("ks1.tn1.pk1", "id1", 6000); + assertEquals(expectedResult.getResult(), actualResult.getResult()); + Mockito.verify(mLockHandle).isMyTurn("id1"); + Mockito.verify(mLockHandle).getLockState("ks1.tn1.pk1"); + } + + @Test + public void testQuorumGet() throws MusicServiceException, MusicQueryException { + preparedQueryObject = Mockito.mock(PreparedQueryObject.class); + mDstoreHandle = Mockito.mock(MusicDataStore.class); + rs = Mockito.mock(ResultSet.class); + session = Mockito.mock(Session.class); + Mockito.when(mDstoreHandle.getSession()).thenReturn(session); + Mockito.when(mDstoreHandle.executeCriticalGet(preparedQueryObject)).thenReturn(rs); + ResultSet rs1 = MusicCore.quorumGet(preparedQueryObject); + assertNotNull(rs1); + } + + @Test + public void testGetLockNameFromId() { + String lockname = MusicCore.getLockNameFromId("lockName$id"); + assertEquals("lockName", lockname); + } + + @Test + public void testDestroyLockRef() throws NoNodeException { + Mockito.doNothing().when(mLockHandle).unlockAndDeleteId("id1"); + MusicCore.destroyLockRef("id1"); + Mockito.verify(mLockHandle, Mockito.atLeastOnce()).unlockAndDeleteId("id1"); + } + + @Test + public void testreleaseLockwithvoluntaryReleaseTrue() throws NoNodeException { + MusicLockState musicLockState = new MusicLockState(LockStatus.UNLOCKED, "id2"); + Mockito.doNothing().when(mLockHandle).unlockAndDeleteId("id1"); + MusicLockState musicLockState1 = MusicCore.releaseLock("id1", true); + assertEquals(musicLockState.getLockStatus(), musicLockState1.getLockStatus()); + Mockito.verify(mLockHandle, Mockito.atLeastOnce()).unlockAndDeleteId("id1"); + } + + @Test + public void testreleaseLockwithvoluntaryReleaseFalse() throws NoNodeException { + MusicLockState musicLockState = new MusicLockState(LockStatus.UNLOCKED, "id2"); + Mockito.doNothing().when(mLockHandle).unlockAndDeleteId("id1"); + MusicLockState musicLockState1 = MusicCore.releaseLock("id1", false); + assertEquals(musicLockState.getLockStatus(), musicLockState1.getLockStatus()); + Mockito.verify(mLockHandle, Mockito.atLeastOnce()).unlockAndDeleteId("id1"); + } + + @Test + public void testDeleteLock() throws MusicLockingException { + Mockito.doNothing().when(mLockHandle).deleteLock("/" + "id1"); + MusicCore.deleteLock("id1"); + Mockito.verify(mLockHandle).deleteLock("/" + "id1"); + } + + /* + * @Test public void testNonKeyRelatedPut() throws Exception { mDstoreHandle = + * Mockito.mock(MusicDataStore.class); Mockito.when(mDstoreHandle.executePut("qu1", + * "consistency")).thenReturn(true); Boolean result = MusicCore.nonKeyRelatedPut("qu1", + * "consistency"); assertTrue(result); Mockito.verify(mDstoreHandle).executePut("qu1", + * "consistency"); } + */ + + @Test + public void testEventualPutPreparedQuery() throws MusicServiceException, MusicQueryException { + mDstoreHandle = Mockito.mock(MusicDataStore.class); + preparedQueryObject = Mockito.mock(PreparedQueryObject.class); + ReturnType expectedResult = new ReturnType(ResultType.SUCCESS, "Succes"); + session = Mockito.mock(Session.class); + Mockito.when(mDstoreHandle.getSession()).thenReturn(session); + Mockito.when(mDstoreHandle.executePut(preparedQueryObject, "eventual")).thenReturn(true); + ReturnType actualResult = MusicCore.eventualPut(preparedQueryObject); + assertEquals(expectedResult.getResult(), actualResult.getResult()); + Mockito.verify(mDstoreHandle).executePut(preparedQueryObject, "eventual"); + } + + @Test + public void testEventualPutPreparedQuerywithResultFalse() + throws MusicServiceException, MusicQueryException { + mDstoreHandle = Mockito.mock(MusicDataStore.class); + preparedQueryObject = Mockito.mock(PreparedQueryObject.class); + ReturnType expectedResult = new ReturnType(ResultType.FAILURE, "Failure"); + session = Mockito.mock(Session.class); + Mockito.when(mDstoreHandle.getSession()).thenReturn(session); + Mockito.when(mDstoreHandle.executePut(preparedQueryObject, "eventual")).thenReturn(false); + ReturnType actualResult = MusicCore.eventualPut(preparedQueryObject); + assertEquals(expectedResult.getResult(), actualResult.getResult()); + Mockito.verify(mDstoreHandle).executePut(preparedQueryObject, "eventual"); + //Mockito.verify(mDstoreHandle).executePut(preparedQueryObject, MusicUtil.EVENTUAL); + } + + @Test + public void testCriticalPutPreparedQuerywithValidLockId() + throws Exception { + mDstoreHandle = Mockito.mock(MusicDataStore.class); + preparedQueryObject = Mockito.mock(PreparedQueryObject.class); + MusicLockState musicLockState = new MusicLockState(LockStatus.UNLOCKED, "id1"); + Mockito.when(condition.testCondition()).thenReturn(true); + session = Mockito.mock(Session.class); + Mockito.when(mDstoreHandle.getSession()).thenReturn(session); + ReturnType expectedResult = new ReturnType(ResultType.SUCCESS, "Succes"); + Mockito.when(mLockHandle.getLockState("ks1" + "." + "tn1" + "." + "pk1")) + .thenReturn(musicLockState); + Mockito.when(mDstoreHandle.executePut(preparedQueryObject, "critical")).thenReturn(true); + ReturnType returnType = MusicCore.criticalPut("ks1", "tn1", "pk1", preparedQueryObject, + "id1", condition); + assertEquals(expectedResult.getResult(), returnType.getResult()); + Mockito.verify(condition).testCondition(); + Mockito.verify(mLockHandle).getLockState("ks1" + "." + "tn1" + "." + "pk1"); + Mockito.verify(mDstoreHandle).executePut(preparedQueryObject, "critical"); + } + + @Test + public void testCriticalPutPreparedQuerywithInvalidLockId() throws MusicLockingException { + mDstoreHandle = Mockito.mock(MusicDataStore.class); + preparedQueryObject = Mockito.mock(PreparedQueryObject.class); + MusicLockState musicLockState = new MusicLockState(LockStatus.UNLOCKED, "id2"); + ReturnType expectedResult = new ReturnType(ResultType.FAILURE, "Failure"); + Mockito.when(mLockHandle.getLockState("ks1" + "." + "tn1" + "." + "pk1")) + .thenReturn(musicLockState); + ReturnType returnType = MusicCore.criticalPut("ks1", "tn1", "pk1", preparedQueryObject, + "id1", condition); + assertEquals(expectedResult.getResult(), returnType.getResult()); + Mockito.verify(mLockHandle).getLockState("ks1" + "." + "tn1" + "." + "pk1"); + } + + @Test + public void testCriticalPutPreparedQuerywithvalidLockIdandTestConditionFalse() throws Exception { + mDstoreHandle = Mockito.mock(MusicDataStore.class); + preparedQueryObject = Mockito.mock(PreparedQueryObject.class); + MusicLockState musicLockState = new MusicLockState(LockStatus.UNLOCKED, "id1"); + Mockito.when(condition.testCondition()).thenReturn(false); + ReturnType expectedResult = new ReturnType(ResultType.FAILURE, "Failure"); + Mockito.when(mLockHandle.getLockState("ks1" + "." + "tn1" + "." + "pk1")) + .thenReturn(musicLockState); + ReturnType returnType = MusicCore.criticalPut("ks1", "tn1", "pk1", preparedQueryObject, + "id1", condition); + assertEquals(expectedResult.getResult(), returnType.getResult()); + Mockito.verify(condition).testCondition(); + Mockito.verify(mLockHandle).getLockState("ks1" + "." + "tn1" + "." + "pk1"); + } + + @Test + public void testNonKeyRelatedPutPreparedQuery() throws Exception { + mDstoreHandle = Mockito.mock(MusicDataStore.class); + preparedQueryObject = Mockito.mock(PreparedQueryObject.class); + session = Mockito.mock(Session.class); + Mockito.when(mDstoreHandle.getSession()).thenReturn(session); + Mockito.when(mDstoreHandle.executePut(preparedQueryObject, "consistency")).thenReturn(true); + ResultType result = MusicCore.nonKeyRelatedPut(preparedQueryObject, "consistency"); + assertEquals(ResultType.SUCCESS, result); + Mockito.verify(mDstoreHandle).executePut(preparedQueryObject, "consistency"); + } + + @Test + public void testAtomicPutPreparedQuery() throws Exception { + mDstoreHandle = Mockito.mock(MusicDataStore.class); + preparedQueryObject = Mockito.mock(PreparedQueryObject.class); + Mockito.when(mLockHandle.createLockId("/" + "ks1.tn1.pk1")).thenReturn("id1"); + MusicLockState musicLockState = new MusicLockState(LockStatus.LOCKED, "id1"); + ReturnType expectedResult = new ReturnType(ResultType.SUCCESS, "Succes"); + session = Mockito.mock(Session.class); + Mockito.when(mDstoreHandle.getSession()).thenReturn(session); + Mockito.when(mLockHandle.getLockState("ks1.tn1.pk1")).thenReturn(musicLockState); + Mockito.when(mLockHandle.isMyTurn("id1")).thenReturn(true); + Mockito.when(condition.testCondition()).thenReturn(true); + Mockito.when(mLockHandle.getLockState("ks1" + "." + "tn1" + "." + "pk1")) + .thenReturn(musicLockState); + Mockito.when(mDstoreHandle.executePut(preparedQueryObject, "critical")).thenReturn(true); + ReturnType returnType = + MusicCore.atomicPut("ks1", "tn1", "pk1", preparedQueryObject, condition); + assertEquals(expectedResult.getResult(), returnType.getResult()); + Mockito.verify(mLockHandle).createLockId("/" + "ks1.tn1.pk1"); + Mockito.verify(mLockHandle, Mockito.atLeastOnce()).getLockState("ks1.tn1.pk1"); + Mockito.verify(mLockHandle).isMyTurn("id1"); + Mockito.verify(condition).testCondition(); + Mockito.verify(mLockHandle, Mockito.atLeastOnce()) + .getLockState("ks1" + "." + "tn1" + "." + "pk1"); + Mockito.verify(mDstoreHandle).executePut(preparedQueryObject, "critical"); + } + + @Test + public void testAtomicPutPreparedQuerywithAcquireLockWithLeaseFalse() throws MusicLockingException { + mDstoreHandle = Mockito.mock(MusicDataStore.class); + preparedQueryObject = Mockito.mock(PreparedQueryObject.class); + Mockito.when(mLockHandle.createLockId("/" + "ks1.tn1.pk1")).thenReturn("id1"); + ReturnType expectedResult = new ReturnType(ResultType.FAILURE, "Failure"); + Mockito.when(mLockHandle.isMyTurn("id1")).thenReturn(false); + ReturnType returnType = + MusicCore.atomicPut("ks1", "tn1", "pk1", preparedQueryObject, condition); + assertEquals(expectedResult.getResult(), returnType.getResult()); + Mockito.verify(mLockHandle).isMyTurn("id1"); + Mockito.verify(mLockHandle).createLockId("/" + "ks1.tn1.pk1"); + } + + @Test + public void testAtomicGetPreparedQuery() throws MusicServiceException, MusicQueryException, MusicLockingException { + mDstoreHandle = Mockito.mock(MusicDataStore.class); + preparedQueryObject = Mockito.mock(PreparedQueryObject.class); + rs = Mockito.mock(ResultSet.class); + session = Mockito.mock(Session.class); + Mockito.when(mDstoreHandle.getSession()).thenReturn(session); + Mockito.when(mLockHandle.createLockId("/" + "ks1.tn1.pk1")).thenReturn("id1"); + MusicLockState musicLockState = new MusicLockState(LockStatus.LOCKED, "id1"); + Mockito.when(mLockHandle.getLockState("ks1.tn1.pk1")).thenReturn(musicLockState); + Mockito.when(mLockHandle.isMyTurn("id1")).thenReturn(true); + Mockito.when(mLockHandle.getLockState("ks1" + "." + "tn1" + "." + "pk1")) + .thenReturn(musicLockState); + Mockito.when(mDstoreHandle.executeCriticalGet(preparedQueryObject)).thenReturn(rs); + ResultSet rs1 = MusicCore.atomicGet("ks1", "tn1", "pk1", preparedQueryObject); + assertNotNull(rs1); + Mockito.verify(mLockHandle).createLockId("/" + "ks1.tn1.pk1"); + Mockito.verify(mLockHandle, Mockito.atLeastOnce()).getLockState("ks1.tn1.pk1"); + Mockito.verify(mLockHandle).isMyTurn("id1"); + Mockito.verify(mLockHandle, Mockito.atLeastOnce()) + .getLockState("ks1" + "." + "tn1" + "." + "pk1"); + Mockito.verify(mDstoreHandle).executeCriticalGet(preparedQueryObject); + } + + @Test + public void testAtomicGetPreparedQuerywithAcquireLockWithLeaseFalse() + throws MusicServiceException, MusicLockingException { + mDstoreHandle = Mockito.mock(MusicDataStore.class); + preparedQueryObject = Mockito.mock(PreparedQueryObject.class); + rs = Mockito.mock(ResultSet.class); + Mockito.when(mLockHandle.createLockId("/" + "ks1.tn1.pk1")).thenReturn("id1"); + Mockito.when(mLockHandle.isMyTurn("id1")).thenReturn(false); + ResultSet rs1 = MusicCore.atomicGet("ks1", "tn1", "pk1", preparedQueryObject); + assertNull(rs1); + Mockito.verify(mLockHandle).createLockId("/" + "ks1.tn1.pk1"); + Mockito.verify(mLockHandle).isMyTurn("id1"); + } + + @Test + public void testGetPreparedQuery() throws MusicServiceException, MusicQueryException { + mDstoreHandle = Mockito.mock(MusicDataStore.class); + rs = Mockito.mock(ResultSet.class); + preparedQueryObject = Mockito.mock(PreparedQueryObject.class); + session = Mockito.mock(Session.class); + Mockito.when(mDstoreHandle.getSession()).thenReturn(session); + Mockito.when(mDstoreHandle.executeEventualGet(preparedQueryObject)).thenReturn(rs); + ResultSet rs1 = MusicCore.get(preparedQueryObject); + assertNotNull(rs1); + Mockito.verify(mDstoreHandle).executeEventualGet(preparedQueryObject); + + } + + @Test + public void testcriticalGetPreparedQuery() throws MusicServiceException, MusicQueryException, MusicLockingException { + mDstoreHandle = Mockito.mock(MusicDataStore.class); + preparedQueryObject = Mockito.mock(PreparedQueryObject.class); + MusicLockState musicLockState = new MusicLockState(LockStatus.UNLOCKED, "id1"); + rs = Mockito.mock(ResultSet.class); + session = Mockito.mock(Session.class); + Mockito.when(mDstoreHandle.getSession()).thenReturn(session); + Mockito.when(mLockHandle.getLockState("ks1" + "." + "tn1" + "." + "pk1")) + .thenReturn(musicLockState); + Mockito.when(mDstoreHandle.executeCriticalGet(preparedQueryObject)).thenReturn(rs); + ResultSet rs1 = MusicCore.criticalGet("ks1", "tn1", "pk1", preparedQueryObject, "id1"); + assertNotNull(rs1); + Mockito.verify(mLockHandle, Mockito.atLeastOnce()) + .getLockState("ks1" + "." + "tn1" + "." + "pk1"); + Mockito.verify(mDstoreHandle).executeCriticalGet(preparedQueryObject); + } + + @Test + public void testcriticalGetPreparedQuerywithInvalidLockId() throws MusicServiceException, MusicLockingException { + mDstoreHandle = Mockito.mock(MusicDataStore.class); + preparedQueryObject = Mockito.mock(PreparedQueryObject.class); + MusicLockState musicLockState = new MusicLockState(LockStatus.UNLOCKED, "id2"); + Mockito.when(mLockHandle.getLockState("ks1" + "." + "tn1" + "." + "pk1")) + .thenReturn(musicLockState); + ResultSet rs1 = MusicCore.criticalGet("ks1", "tn1", "pk1", preparedQueryObject, "id1"); + assertNull(rs1); + Mockito.verify(mLockHandle, Mockito.atLeastOnce()) + .getLockState("ks1" + "." + "tn1" + "." + "pk1"); + } + +} diff --git a/jar/src/test/java/org/onap/music/unittests/TestMusicCoreIntegration.java b/jar/src/test/java/org/onap/music/unittests/TestMusicCoreIntegration.java new file mode 100644 index 00000000..d327d0f0 --- /dev/null +++ b/jar/src/test/java/org/onap/music/unittests/TestMusicCoreIntegration.java @@ -0,0 +1,176 @@ +/* + * ============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; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import java.io.File; +import java.util.List; +import org.apache.curator.test.TestingServer; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.lockingservice.MusicLockState; +import org.onap.music.lockingservice.MusicLockingService; +import org.onap.music.lockingservice.MusicLockState.LockStatus; +import org.onap.music.main.MusicCore; +import org.onap.music.main.MusicUtil; +import org.onap.music.main.ResultType; +import org.onap.music.main.ReturnType; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestMusicCoreIntegration { + + static TestingServer zkServer; + static PreparedQueryObject testObject; + static String lockId = null; + static String lockName = "ks1.tb1.pk1"; + + @BeforeClass + public static void init() throws Exception { + try { + MusicCore.mDstoreHandle = CassandraCQL.connectToEmbeddedCassandra(); + zkServer = new TestingServer(2181, new File("/tmp/zk")); + MusicCore.mLockHandle = new MusicLockingService(); + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println("####Port:" + zkServer.getPort()); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + System.out.println("After class"); + testObject = new PreparedQueryObject(); + testObject.appendQueryString(CassandraCQL.dropKeyspace); + MusicCore.eventualPut(testObject); + MusicCore.deleteLock(lockName); + MusicCore.mDstoreHandle.close(); + MusicCore.mLockHandle.getzkLockHandle().close(); + MusicCore.mLockHandle.close(); + zkServer.stop(); + + } + + @Test + public void Test1_SetUp() throws MusicServiceException, MusicQueryException { + MusicCore.mLockHandle = new MusicLockingService(); + ResultType result = ResultType.FAILURE; + testObject = new PreparedQueryObject(); + testObject.appendQueryString(CassandraCQL.createKeySpace); + MusicCore.eventualPut(testObject); + testObject = new PreparedQueryObject(); + testObject.appendQueryString(CassandraCQL.createTableEmployees); + result = MusicCore.nonKeyRelatedPut(testObject, MusicUtil.EVENTUAL); + assertEquals(ResultType.SUCCESS, result); + } + + @Test + public void Test2_atomicPut() throws Exception { + testObject = new PreparedQueryObject(); + testObject = CassandraCQL.setPreparedInsertQueryObject1(); + ReturnType returnType = MusicCore.atomicPut("testCassa", "employees", "Mr Test one", + testObject, null); + assertEquals(ResultType.SUCCESS, returnType.getResult()); + } + + @Test + public void Test3_atomicPutWithDeleteLock() throws Exception { + testObject = new PreparedQueryObject(); + testObject = CassandraCQL.setPreparedInsertQueryObject2(); + ReturnType returnType = MusicCore.atomicPutWithDeleteLock("testCassa", "employees", + "Mr Test two", testObject, null); + assertEquals(ResultType.SUCCESS, returnType.getResult()); + } + + @Test + public void Test4_atomicGetWithDeleteLock() throws Exception { + testObject = new PreparedQueryObject(); + testObject = CassandraCQL.setPreparedGetQuery(); + ResultSet resultSet = MusicCore.atomicGetWithDeleteLock("testCassa", "employees", + "Mr Test one", testObject); + List<Row> rows = resultSet.all(); + assertEquals(1, rows.size()); + } + + @Test + public void Test5_atomicGet() throws Exception { + testObject = new PreparedQueryObject(); + testObject = CassandraCQL.setPreparedGetQuery(); + ResultSet resultSet = + MusicCore.atomicGet("testCassa", "employees", "Mr Test two", testObject); + List<Row> rows = resultSet.all(); + assertEquals(1, rows.size()); + } + + @Test + public void Test6_createLockReference() throws Exception { + lockId = MusicCore.createLockReference(lockName); + assertNotNull(lockId); + } + + @Test + public void Test7_acquireLockwithLease() throws Exception { + ReturnType lockLeaseStatus = MusicCore.acquireLockWithLease(lockName, lockId, 1000); + assertEquals(ResultType.SUCCESS, lockLeaseStatus.getResult()); + } + + @Test + public void Test8_acquireLock() throws Exception { + ReturnType lockStatus = MusicCore.acquireLock(lockName, lockId); + assertEquals(ResultType.SUCCESS, lockStatus.getResult()); + } + + @Test + public void Test9_release() throws Exception { + MusicLockState musicLockState = new MusicLockState(LockStatus.LOCKED, "id1"); + MusicLockState musicLockState1 = new MusicLockState(LockStatus.UNLOCKED, "id1"); + MusicCore.whoseTurnIsIt(lockName); + MusicLockState mls = MusicCore.getMusicLockState(lockName); + boolean voluntaryRelease = true; + MusicLockState mls1 = MusicCore.releaseLock(lockId, voluntaryRelease); + assertEquals(musicLockState.getLockStatus(), mls.getLockStatus()); + assertEquals(musicLockState1.getLockStatus(), mls1.getLockStatus()); + } + + @Test + public void Test10_create() { + MusicCore.pureZkCreate("/nodeName"); + } + + @Test + public void Test11_write() { + MusicCore.pureZkWrite("nodeName", "I'm Test".getBytes()); + } + + @Test + public void Test12_read() { + byte[] data = MusicCore.pureZkRead("nodeName"); + String data1 = new String(data); + assertEquals("I'm Test", data1); + } + +} diff --git a/jar/src/test/java/org/onap/music/unittests/TestRestMusicData.java b/jar/src/test/java/org/onap/music/unittests/TestRestMusicData.java new file mode 100644 index 00000000..febf6c76 --- /dev/null +++ b/jar/src/test/java/org/onap/music/unittests/TestRestMusicData.java @@ -0,0 +1,718 @@ +/* + * ============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; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import java.io.File; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import org.apache.curator.test.TestingServer; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; +import org.mindrot.jbcrypt.BCrypt; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.datastore.jsonobjects.JsonDelete; +import org.onap.music.datastore.jsonobjects.JsonInsert; +import org.onap.music.datastore.jsonobjects.JsonKeySpace; +import org.onap.music.datastore.jsonobjects.JsonOnboard; +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.lockingservice.MusicLockingService; +import org.onap.music.main.MusicCore; +import org.onap.music.main.MusicUtil; +import org.onap.music.main.ResultType; +import org.onap.music.rest.RestMusicAdminAPI; +import org.onap.music.rest.RestMusicDataAPI; +import org.onap.music.rest.RestMusicLocksAPI; +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.sun.jersey.core.util.MultivaluedMapImpl; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RunWith(MockitoJUnitRunner.class) +public class TestRestMusicData { + + RestMusicDataAPI data = new RestMusicDataAPI(); + RestMusicAdminAPI admin = new RestMusicAdminAPI(); + RestMusicLocksAPI lock = new RestMusicLocksAPI(); + static PreparedQueryObject testObject; + static TestingServer zkServer; + + @Mock + HttpServletResponse http; + + @Mock + UriInfo info; + + static String appName = "TestApp"; + static String userId = "TestUser"; + static String password = "TestPassword"; + static boolean isAAF = false; + static UUID uuid = UUID.fromString("abc66ccc-d857-4e90-b1e5-df98a3d40ce6"); + static String keyspaceName = "testCassa"; + static String tableName = "employees"; + static String xLatestVersion = "X-latestVersion"; + static String onboardUUID = null; + static String lockId = null; + static String lockName = "testCassa.employees.sample3"; + + @BeforeClass + public static void init() throws Exception { + try { + MusicCore.mDstoreHandle = CassandraCQL.connectToEmbeddedCassandra(); + zkServer = new TestingServer(2181, new File("/tmp/zk")); + MusicCore.mLockHandle = new MusicLockingService(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + System.out.println("After class"); + testObject = new PreparedQueryObject(); + testObject.appendQueryString("DROP KEYSPACE IF EXISTS " + keyspaceName); + MusicCore.eventualPut(testObject); + testObject = new PreparedQueryObject(); + testObject.appendQueryString("DROP KEYSPACE IF EXISTS admin"); + MusicCore.eventualPut(testObject); + MusicCore.mDstoreHandle.close(); + MusicCore.mLockHandle.getzkLockHandle().close(); + MusicCore.mLockHandle.close(); + zkServer.stop(); + } + + @Test + public void Test1_createKeyspace() throws Exception { + testObject = new PreparedQueryObject(); + testObject.appendQueryString("CREATE KEYSPACE admin WITH REPLICATION = " + + "{'class' : 'SimpleStrategy' , " + + "'replication_factor': 1} AND DURABLE_WRITES = true"); + MusicCore.eventualPut(testObject); + testObject = new PreparedQueryObject(); + testObject.appendQueryString( + "CREATE TABLE admin.keyspace_master (" + " uuid uuid, keyspace_name text," + + " application_name text, is_api boolean," + + " password text, username text," + + " is_aaf boolean, PRIMARY KEY (uuid)\n" + ");"); + MusicCore.eventualPut(testObject); + + testObject = new PreparedQueryObject(); + testObject.appendQueryString( + "INSERT INTO admin.keyspace_master (uuid, keyspace_name, application_name, is_api, " + + "password, username, is_aaf) VALUES (?,?,?,?,?,?,?)"); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), + MusicUtil.DEFAULTKEYSPACENAME)); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "True")); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), BCrypt.hashpw(password, BCrypt.gensalt()))); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF)); + MusicCore.eventualPut(testObject); + + testObject = new PreparedQueryObject(); + testObject.appendQueryString( + "INSERT INTO admin.keyspace_master (uuid, keyspace_name, application_name, is_api, " + + "password, username, is_aaf) VALUES (?,?,?,?,?,?,?)"); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), + UUID.fromString("bbc66ccc-d857-4e90-b1e5-df98a3d40de6"))); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), + MusicUtil.DEFAULTKEYSPACENAME)); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), "TestApp1")); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "True")); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), BCrypt.hashpw(password, BCrypt.gensalt()))); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), "TestUser1")); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF)); + MusicCore.eventualPut(testObject); + + testObject = new PreparedQueryObject(); + testObject.appendQueryString( + "select uuid from admin.keyspace_master where application_name = ? allow filtering"); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); + ResultSet rs = MusicCore.get(testObject); + List<Row> rows = rs.all(); + if (rows.size() > 0) { + System.out.println("#######UUID is:" + rows.get(0).getUUID("uuid")); + } + } + + @Test + public void Test2_createKeyspace() throws Exception { + JsonKeySpace jsonKeyspace = new JsonKeySpace(); + Map<String, String> consistencyInfo = new HashMap<>(); + Map<String, Object> replicationInfo = new HashMap<>(); + consistencyInfo.put("type", "eventual"); + replicationInfo.put("class", "SimpleStrategy"); + replicationInfo.put("replication_factor", 1); + jsonKeyspace.setConsistencyInfo(consistencyInfo); + jsonKeyspace.setDurabilityOfWrites("true"); + jsonKeyspace.setKeyspaceName(keyspaceName); + jsonKeyspace.setReplicationInfo(replicationInfo); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Response response = data.createKeySpace("1", "1", "1", null, appName, userId, + password, jsonKeyspace, keyspaceName); + System.out.println("#######status is " + response.getStatus()); + System.out.println("Entity" + response.getEntity()); + assertEquals(200,response.getStatus()); + } + + @Test + public void Test2_createKeyspace0() throws Exception { + JsonKeySpace jsonKeyspace = new JsonKeySpace(); + Map<String, String> consistencyInfo = new HashMap<>(); + Map<String, Object> replicationInfo = new HashMap<>(); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Response response = data.createKeySpace("1", "1", "1", null, appName, userId, + password, jsonKeyspace, keyspaceName); + System.out.println("#######status is " + response.getStatus()); + System.out.println("Entity" + response.getEntity()); + assertEquals(400,response.getStatus()); + } +//MusicCore.autheticateUser + @Test + public void Test2_createKeyspace01() throws Exception { + JsonKeySpace jsonKeyspace = new JsonKeySpace(); + Map<String, String> consistencyInfo = new HashMap<>(); + Map<String, Object> replicationInfo = new HashMap<>(); + String appName1 = "test"; + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Response response = data.createKeySpace("1", "1", "1", null, appName1, userId, + password, jsonKeyspace, keyspaceName); + System.out.println("#######status is " + response.getStatus()); + System.out.println("Entity" + response.getEntity()); + assertEquals(401,response.getStatus()); + } + + @Test + public void Test3_createKeyspace1() throws Exception { + JsonKeySpace jsonKeyspace = new JsonKeySpace(); + Map<String, String> consistencyInfo = new HashMap<>(); + Map<String, Object> replicationInfo = new HashMap<>(); + consistencyInfo.put("type", "eventual"); + replicationInfo.put("class", "SimpleStrategy"); + replicationInfo.put("replication_factor", 1); + jsonKeyspace.setConsistencyInfo(consistencyInfo); + jsonKeyspace.setDurabilityOfWrites("true"); + jsonKeyspace.setKeyspaceName("TestApp1"); + jsonKeyspace.setReplicationInfo(replicationInfo); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Response response = data.createKeySpace("1", "1", "1", null, "TestApp1", + "TestUser1", password, jsonKeyspace, keyspaceName); + System.out.println("#######status is " + response.getStatus()); + System.out.println("Entity" + response.getEntity()); + assertEquals(400,response.getStatus()); + } + + @Test + public void Test3_createTable() throws Exception { + JsonTable jsonTable = new JsonTable(); + Map<String, String> consistencyInfo = new HashMap<>(); + Map<String, String> fields = new HashMap<>(); + fields.put("uuid", "text"); + fields.put("emp_name", "text"); + fields.put("emp_salary", "varint"); + fields.put("PRIMARY KEY", "(emp_name)"); + consistencyInfo.put("type", "eventual"); + jsonTable.setConsistencyInfo(consistencyInfo); + jsonTable.setKeyspaceName(keyspaceName); + jsonTable.setPrimaryKey("emp_name"); + jsonTable.setTableName(tableName); + jsonTable.setFields(fields); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Response response = data.createTable("1", "1", "1", + "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, userId, password, + jsonTable, keyspaceName, tableName); + System.out.println("#######status is " + response.getStatus()); + System.out.println("Entity" + response.getEntity()); + assertEquals(200, response.getStatus()); + } + + // Improper Auth + @Test + public void Test3_createTable1() throws Exception { + JsonTable jsonTable = new JsonTable(); + Map<String, String> consistencyInfo = new HashMap<>(); + Map<String, String> fields = new HashMap<>(); + fields.put("uuid", "text"); + fields.put("emp_name", "text"); + fields.put("emp_salary", "varint"); + fields.put("PRIMARY KEY", "(emp_name)"); + consistencyInfo.put("type", "eventual"); + jsonTable.setConsistencyInfo(consistencyInfo); + jsonTable.setKeyspaceName(keyspaceName); + jsonTable.setPrimaryKey("emp_name"); + jsonTable.setTableName(tableName); + jsonTable.setFields(fields); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Response response = data.createTable("1", "1", "1", + "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, userId, "wrong", + jsonTable, keyspaceName, tableName); + System.out.println("#######status is " + response.getStatus()); + System.out.println("Entity" + response.getEntity()); + assertEquals(401, response.getStatus()); + } + + // Improper keyspace + @Test + public void Test3_createTable2() throws Exception { + JsonTable jsonTable = new JsonTable(); + Map<String, String> consistencyInfo = new HashMap<>(); + Map<String, String> fields = new HashMap<>(); + fields.put("uuid", "text"); + fields.put("emp_name", "text"); + fields.put("emp_salary", "varint"); + fields.put("PRIMARY KEY", "(emp_name)"); + consistencyInfo.put("type", "eventual"); + jsonTable.setConsistencyInfo(consistencyInfo); + jsonTable.setKeyspaceName(keyspaceName); + jsonTable.setPrimaryKey("emp_name"); + jsonTable.setTableName(tableName); + jsonTable.setFields(fields); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Response response = data.createTable("1", "1", "1", + "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, userId, password, + jsonTable, "wrong", tableName); + System.out.println("#######status is " + response.getStatus()); + System.out.println("Entity" + response.getEntity()); + assertEquals(401, response.getStatus()); + } + + + + @Test + public void Test4_insertIntoTable() throws Exception { + JsonInsert jsonInsert = new JsonInsert(); + Map<String, String> consistencyInfo = new HashMap<>(); + Map<String, Object> values = new HashMap<>(); + values.put("uuid", "cfd66ccc-d857-4e90-b1e5-df98a3d40cd6"); + values.put("emp_name", "testName"); + values.put("emp_salary", 500); + consistencyInfo.put("type", "eventual"); + jsonInsert.setConsistencyInfo(consistencyInfo); + jsonInsert.setKeyspaceName(keyspaceName); + jsonInsert.setTableName(tableName); + jsonInsert.setValues(values); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Response response = data.insertIntoTable("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", + appName, userId, password, jsonInsert, keyspaceName, tableName); + assertEquals(200, response.getStatus()); + } + + @Test + public void Test4_insertIntoTable2() throws Exception { + JsonInsert jsonInsert = new JsonInsert(); + Map<String, String> consistencyInfo = new HashMap<>(); + Map<String, Object> values = new HashMap<>(); + values.put("uuid", "cfd66ccc-d857-4e90-b1e5-df98a3d40cd6"); + values.put("emp_name", "test1"); + values.put("emp_salary", 1500); + consistencyInfo.put("type", "eventual"); + jsonInsert.setConsistencyInfo(consistencyInfo); + jsonInsert.setKeyspaceName(keyspaceName); + jsonInsert.setTableName(tableName); + jsonInsert.setValues(values); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Response response = data.insertIntoTable("1", "1", "1", + "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, userId, password, + jsonInsert, keyspaceName, tableName); + assertEquals(200, response.getStatus()); + } + + // Auth Error + @Test + public void Test4_insertIntoTable3() throws Exception { + JsonInsert jsonInsert = new JsonInsert(); + Map<String, String> consistencyInfo = new HashMap<>(); + Map<String, Object> values = new HashMap<>(); + values.put("uuid", "cfd66ccc-d857-4e90-b1e5-df98a3d40cd6"); + values.put("emp_name", "test1"); + values.put("emp_salary", 1500); + consistencyInfo.put("type", "eventual"); + jsonInsert.setConsistencyInfo(consistencyInfo); + jsonInsert.setKeyspaceName(keyspaceName); + jsonInsert.setTableName(tableName); + jsonInsert.setValues(values); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Response response = data.insertIntoTable("1", "1", "1", + "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, userId, "wrong", + jsonInsert, keyspaceName, tableName); + assertEquals(401, response.getStatus()); + } + + // Table wrong + @Test + public void Test4_insertIntoTable4() throws Exception { + JsonInsert jsonInsert = new JsonInsert(); + Map<String, String> consistencyInfo = new HashMap<>(); + Map<String, Object> values = new HashMap<>(); + values.put("uuid", "cfd66ccc-d857-4e90-b1e5-df98a3d40cd6"); + values.put("emp_name", "test1"); + values.put("emp_salary", 1500); + consistencyInfo.put("type", "eventual"); + jsonInsert.setConsistencyInfo(consistencyInfo); + jsonInsert.setKeyspaceName(keyspaceName); + jsonInsert.setTableName(tableName); + jsonInsert.setValues(values); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Response response = data.insertIntoTable("1", "1", "1", + "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, userId, password, + jsonInsert, keyspaceName, "wrong"); + assertEquals(400, response.getStatus()); + } + + + + @Test + public void Test5_updateTable() throws Exception { + JsonUpdate jsonUpdate = new JsonUpdate(); + Map<String, String> consistencyInfo = new HashMap<>(); + MultivaluedMap<String, String> row = new MultivaluedMapImpl(); + Map<String, Object> values = new HashMap<>(); + row.add("emp_name", "testName"); + values.put("emp_salary", 2500); + consistencyInfo.put("type", "atomic"); + jsonUpdate.setConsistencyInfo(consistencyInfo); + jsonUpdate.setKeyspaceName(keyspaceName); + jsonUpdate.setTableName(tableName); + jsonUpdate.setValues(values); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Mockito.when(info.getQueryParameters()).thenReturn(row); + Response response = data.updateTable("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, + userId, password, jsonUpdate, keyspaceName, tableName, info); + assertEquals(200, response.getStatus()); + } + + @Test + public void Test6_select() throws Exception { + JsonSelect jsonSelect = new JsonSelect(); + Map<String, String> consistencyInfo = new HashMap<>(); + MultivaluedMap<String, String> row = new MultivaluedMapImpl(); + row.add("emp_name", "testName"); + consistencyInfo.put("type", "atomic"); + jsonSelect.setConsistencyInfo(consistencyInfo); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Mockito.when(info.getQueryParameters()).thenReturn(row); + Response response = data.select("1", "1", "1","abc66ccc-d857-4e90-b1e5-df98a3d40ce6", + appName, userId, password, keyspaceName, tableName, info); + HashMap<String,HashMap<String,Object>> map = (HashMap<String, HashMap<String, Object>>) response.getEntity(); + HashMap<String, Object> result = map.get("result"); + assertEquals("2500", ((HashMap<String,Object>) result.get("row 0")).get("emp_salary").toString()); + } + + @Test + public void Test6_selectCritical() throws Exception { + JsonInsert jsonInsert = new JsonInsert(); + Map<String, String> consistencyInfo = new HashMap<>(); + MultivaluedMap<String, String> row = new MultivaluedMapImpl(); + row.add("emp_name", "testName"); + consistencyInfo.put("type", "atomic"); + jsonInsert.setConsistencyInfo(consistencyInfo); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Mockito.when(info.getQueryParameters()).thenReturn(row); + Response response = data.selectCritical("1", "1", "1","abc66ccc-d857-4e90-b1e5-df98a3d40ce6", + appName, userId, password, jsonInsert, keyspaceName, tableName,info); + HashMap<String,HashMap<String,Object>> map = (HashMap<String, HashMap<String, Object>>) response.getEntity(); + HashMap<String, Object> result = map.get("result"); + assertEquals("2500", ((HashMap<String,Object>) result.get("row 0")).get("emp_salary").toString()); + } + + @Test + public void Test6_deleteFromTable() throws Exception { + JsonDelete jsonDelete = new JsonDelete(); + Map<String, String> consistencyInfo = new HashMap<>(); + MultivaluedMap<String, String> row = new MultivaluedMapImpl(); + row.add("emp_name", "test1"); + consistencyInfo.put("type", "atomic"); + jsonDelete.setConsistencyInfo(consistencyInfo); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Mockito.when(info.getQueryParameters()).thenReturn(row); + Response response = data.deleteFromTable("1", "1", "1", + "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, userId, password, + jsonDelete, keyspaceName, tableName, info); + assertEquals(200, response.getStatus()); + } + + // Values + @Test + public void Test6_deleteFromTable1() throws Exception { + JsonDelete jsonDelete = new JsonDelete(); + Map<String, String> consistencyInfo = new HashMap<>(); + MultivaluedMap<String, String> row = new MultivaluedMapImpl(); + consistencyInfo.put("type", "atomic"); + jsonDelete.setConsistencyInfo(consistencyInfo); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Mockito.when(info.getQueryParameters()).thenReturn(row); + Response response = data.deleteFromTable("1", "1", "1", + "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, userId, password, + jsonDelete, keyspaceName, tableName, info); + assertEquals(400, response.getStatus()); + } + + // delObj + @Test + public void Test6_deleteFromTable2() throws Exception { + JsonDelete jsonDelete = new JsonDelete(); + Map<String, String> consistencyInfo = new HashMap<>(); + MultivaluedMap<String, String> row = new MultivaluedMapImpl(); + row.add("emp_name", "test1"); + consistencyInfo.put("type", "atomic"); + jsonDelete.setConsistencyInfo(consistencyInfo); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Mockito.when(info.getQueryParameters()).thenReturn(row); + Response response = data.deleteFromTable("1", "1", "1", + "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, userId, password, + null, keyspaceName, tableName, info); + assertEquals(400, response.getStatus()); + } + + @Test + public void Test7_dropTable() throws Exception { + JsonTable jsonTable = new JsonTable(); + Map<String, String> consistencyInfo = new HashMap<>(); + consistencyInfo.put("type", "atomic"); + jsonTable.setConsistencyInfo(consistencyInfo); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Response response = data.dropTable("1", "1", "1", + "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, userId, password, + keyspaceName, tableName); + assertEquals(200, response.getStatus()); + } + + @Test + public void Test8_deleteKeyspace() throws Exception { + JsonKeySpace jsonKeyspace = new JsonKeySpace(); + Map<String, String> consistencyInfo = new HashMap<>(); + Map<String, Object> replicationInfo = new HashMap<>(); + consistencyInfo.put("type", "eventual"); + replicationInfo.put("class", "SimpleStrategy"); + replicationInfo.put("replication_factor", 1); + jsonKeyspace.setConsistencyInfo(consistencyInfo); + jsonKeyspace.setDurabilityOfWrites("true"); + jsonKeyspace.setKeyspaceName("TestApp1"); + jsonKeyspace.setReplicationInfo(replicationInfo); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Response response = data.dropKeySpace("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", + appName, userId, password, keyspaceName); + assertEquals(200, response.getStatus()); + } + + @Test + public void Test8_deleteKeyspace2() throws Exception { + JsonKeySpace jsonKeyspace = new JsonKeySpace(); + Map<String, String> consistencyInfo = new HashMap<>(); + Map<String, Object> replicationInfo = new HashMap<>(); + consistencyInfo.put("type", "eventual"); + replicationInfo.put("class", "SimpleStrategy"); + replicationInfo.put("replication_factor", 1); + jsonKeyspace.setConsistencyInfo(consistencyInfo); + jsonKeyspace.setDurabilityOfWrites("true"); + jsonKeyspace.setKeyspaceName("TestApp1"); + jsonKeyspace.setReplicationInfo(replicationInfo); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Response response = data.dropKeySpace("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", + appName, userId, "wrong", keyspaceName); + assertEquals(401, response.getStatus()); + } + + @Test + public void Test8_deleteKeyspace3() throws Exception { + JsonKeySpace jsonKeyspace = new JsonKeySpace(); + Map<String, String> consistencyInfo = new HashMap<>(); + Map<String, Object> replicationInfo = new HashMap<>(); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Response response = data.dropKeySpace("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", + appName, userId, password, keyspaceName); + assertEquals(400, response.getStatus()); + } + + + + @Test + public void Test6_onboard() throws Exception { + JsonOnboard jsonOnboard = new JsonOnboard(); + jsonOnboard.setAppname("TestApp2"); + jsonOnboard.setIsAAF("false"); + jsonOnboard.setUserId("TestUser2"); + jsonOnboard.setPassword("TestPassword2"); + Map<String, Object> resultMap = (Map<String, Object>) admin.onboardAppWithMusic(jsonOnboard).getEntity(); + resultMap.containsKey("success"); + onboardUUID = resultMap.get("Generated AID").toString(); + assertEquals("Your application TestApp2 has been onboarded with MUSIC.", resultMap.get("Success")); + } + // Missing appname + @Test + public void Test6_onboard1() throws Exception { + JsonOnboard jsonOnboard = new JsonOnboard(); + jsonOnboard.setIsAAF("false"); + jsonOnboard.setUserId("TestUser2"); + jsonOnboard.setPassword("TestPassword2"); + Map<String, Object> resultMap = (Map<String, Object>) admin.onboardAppWithMusic(jsonOnboard).getEntity(); + resultMap.containsKey("success"); + System.out.println("--->" + resultMap.toString()); + assertEquals("Unauthorized: Please check the request parameters. Some of the required values appName(ns), userId, password, isAAF are missing.", resultMap.get("Exception")); + } + + + @Test + public void Test7_onboardSearch() throws Exception { + JsonOnboard jsonOnboard = new JsonOnboard(); + jsonOnboard.setAppname("TestApp2"); + jsonOnboard.setIsAAF("false"); + jsonOnboard.setAid(onboardUUID); + Map<String, Object> resultMap = (Map<String, Object>) admin.getOnboardedInfoSearch(jsonOnboard).getEntity(); + resultMap.containsKey("success"); + assertEquals(MusicUtil.DEFAULTKEYSPACENAME, resultMap.get(onboardUUID)); + + } + + // Missing appname + @Test + public void Test7_onboardSearch1() throws Exception { + JsonOnboard jsonOnboard = new JsonOnboard(); + jsonOnboard.setIsAAF("false"); + jsonOnboard.setAid(onboardUUID); + Map<String, Object> resultMap = (Map<String, Object>) admin.getOnboardedInfoSearch(jsonOnboard).getEntity(); + System.out.println("--->" + resultMap.toString()); + resultMap.containsKey("success"); + assertEquals(MusicUtil.DEFAULTKEYSPACENAME, resultMap.get(onboardUUID)); + + } + + @Test + public void Test8_onboardUpdate() throws Exception { + JsonOnboard jsonOnboard = new JsonOnboard(); + jsonOnboard.setIsAAF("false"); + jsonOnboard.setUserId("TestUser3"); + jsonOnboard.setPassword("TestPassword3"); + jsonOnboard.setAid(onboardUUID); + Map<String, Object> resultMap = (Map<String, Object>) admin.updateOnboardApp(jsonOnboard).getEntity(); + System.out.println("--->" + resultMap.toString()); + resultMap.containsKey("success"); + assertEquals("Your application has been updated successfully", resultMap.get("Success")); + } + + // Aid null + @Test + public void Test8_onboardUpdate1() throws Exception { + JsonOnboard jsonOnboard = new JsonOnboard(); + jsonOnboard.setIsAAF("false"); + jsonOnboard.setUserId("TestUser3"); + jsonOnboard.setPassword("TestPassword3"); + Map<String, Object> resultMap = (Map<String, Object>) admin.updateOnboardApp(jsonOnboard).getEntity(); + System.out.println("--->" + resultMap.toString()); + resultMap.containsKey("success"); + assertEquals("Please make sure Aid is present", resultMap.get("Exception")); + } + + // Appname not null + @Test + public void Test8_onboardUpdate2() throws Exception { + JsonOnboard jsonOnboard = new JsonOnboard(); + jsonOnboard.setAppname("TestApp2"); + jsonOnboard.setIsAAF("false"); + jsonOnboard.setUserId("TestUser3"); + jsonOnboard.setPassword("TestPassword3"); + jsonOnboard.setAid(onboardUUID); + Map<String, Object> resultMap = (Map<String, Object>) admin.updateOnboardApp(jsonOnboard).getEntity(); + resultMap.containsKey("success"); + System.out.println("--->" + resultMap.toString()); + assertEquals("Application TestApp2 has already been onboarded. Please contact admin.", resultMap.get("Exception")); + } + + // All null + @Test + public void Test8_onboardUpdate3() throws Exception { + JsonOnboard jsonOnboard = new JsonOnboard(); + jsonOnboard.setAid(onboardUUID); + Map<String, Object> resultMap = (Map<String, Object>) admin.updateOnboardApp(jsonOnboard).getEntity(); + assertTrue(resultMap.containsKey("Exception") ); + } + + @Test + public void Test9_onboardDelete() throws Exception { + JsonOnboard jsonOnboard = new JsonOnboard(); + jsonOnboard.setAppname("TestApp2"); + jsonOnboard.setAid(onboardUUID); + Map<String, Object> resultMap = (Map<String, Object>) admin.deleteOnboardApp(jsonOnboard).getEntity(); + resultMap.containsKey("success"); + assertEquals("Your application has been deleted successfully", resultMap.get("Success")); + } + + @Test + public void Test9_onboardDelete1() throws Exception { + JsonOnboard jsonOnboard = new JsonOnboard(); + Map<String, Object> resultMap = (Map<String, Object>) admin.deleteOnboardApp(jsonOnboard).getEntity(); + assertTrue(resultMap.containsKey("Exception")); + } + + @Test + public void Test3_createLockReference() throws Exception { + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Map<String, Object> resultMap = (Map<String, Object>) lock.createLockReference(lockName,"1","1", null, appName, userId, password).getEntity(); + @SuppressWarnings("unchecked") + Map<String, Object> resultMap1 = (Map<String, Object>) resultMap.get("lock"); + lockId = (String) resultMap1.get("lock"); + assertEquals(ResultType.SUCCESS, resultMap.get("status")); + } + + @Test + public void Test4_accquireLock() throws Exception { + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Map<String, Object> resultMap = (Map<String, Object>) lock.accquireLock(lockId,"1","1", null, appName, userId, password).getEntity(); + assertEquals(ResultType.SUCCESS, resultMap.get("status")); + } + + @Test + public void Test5_currentLockHolder() throws Exception { + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Map<String, Object> resultMap = (Map<String, Object>) lock.currentLockHolder(lockName,"1","1", null, appName, userId, password).getEntity(); + assertEquals(ResultType.SUCCESS, resultMap.get("status")); + } + + @Test + public void Test7_unLock() throws Exception { + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Map<String, Object> resultMap = (Map<String, Object>) lock.unLock(lockId,"1","1", null, appName, userId, password).getEntity(); + assertEquals(ResultType.SUCCESS, resultMap.get("status")); + } + + @Test + public void Test8_delete() throws Exception { + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Map<String, Object> resultMap = (Map<String, Object>) lock.deleteLock(lockName,"1","1", null, appName, userId, password).getEntity(); + assertEquals(ResultType.SUCCESS, resultMap.get("status")); + } +}
\ No newline at end of file diff --git a/jar/src/test/java/org/onap/music/unittests/jsonobjects/AAFResponseTest.java b/jar/src/test/java/org/onap/music/unittests/jsonobjects/AAFResponseTest.java new file mode 100644 index 00000000..354668c7 --- /dev/null +++ b/jar/src/test/java/org/onap/music/unittests/jsonobjects/AAFResponseTest.java @@ -0,0 +1,54 @@ +/* + * ============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/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonDeleteTest.java b/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonDeleteTest.java new file mode 100644 index 00000000..885694bd --- /dev/null +++ b/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonDeleteTest.java @@ -0,0 +1,86 @@ +/* + * ============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 java.util.HashMap; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.onap.music.datastore.jsonobjects.JsonDelete; + +public class JsonDeleteTest { + + JsonDelete jd = null; + + @Before + public void init() { + jd = new JsonDelete(); + } + + + @Test + public void testGetConditions() { + Map<String,Object> mapSo = new HashMap<>(); + mapSo = new HashMap<>(); + mapSo.put("key1","one"); + mapSo.put("key2","two"); + jd.setConditions(mapSo); + assertEquals("one",jd.getConditions().get("key1")); + } + + @Test + public void testGetConsistencyInfo() { + Map<String,String> mapSs = new HashMap<>(); + mapSs = new HashMap<>(); + mapSs.put("key3","three"); + mapSs.put("key4","four"); + jd.setConsistencyInfo(mapSs); + assertEquals("three",jd.getConsistencyInfo().get("key3")); + } + + @Test + public void testGetColumns() { + ArrayList<String> ary = new ArrayList<>(); + ary = new ArrayList<>(); + ary.add("e1"); + ary.add("e2"); + ary.add("e3"); + jd.setColumns(ary); + assertEquals("e1",jd.getColumns().get(0)); + } + + @Test + public void testGetTtl() { + jd.setTtl("2000"); + assertEquals("2000",jd.getTtl()); + } + + @Test + public void testGetTimestamp() { + jd.setTimestamp("20:00"); + assertEquals("20:00",jd.getTimestamp()); + + } + +} diff --git a/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonInsertTest.java b/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonInsertTest.java new file mode 100644 index 00000000..69403cc7 --- /dev/null +++ b/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonInsertTest.java @@ -0,0 +1,86 @@ +/* + * ============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.HashMap; +import java.util.Map; +import org.junit.Test; +import org.onap.music.datastore.jsonobjects.JsonInsert; + +public class JsonInsertTest { + + JsonInsert ji = new JsonInsert(); + + @Test + public void testGetKeyspaceName() { + ji.setKeyspaceName("keyspace"); + assertEquals("keyspace",ji.getKeyspaceName()); + } + + @Test + public void testGetTableName() { + ji.setTableName("table"); + assertEquals("table",ji.getTableName()); + } + + @Test + public void testGetConsistencyInfo() { + Map<String,String> cons = new HashMap<>(); + cons.put("test","true"); + ji.setConsistencyInfo(cons); + assertEquals("true",ji.getConsistencyInfo().get("test")); + } + + @Test + public void testGetTtl() { + ji.setTtl("ttl"); + assertEquals("ttl",ji.getTtl()); + } + + @Test + public void testGetTimestamp() { + ji.setTimestamp("10:30"); + assertEquals("10:30",ji.getTimestamp()); + } + + @Test + public void testGetValues() { + Map<String,Object> cons = new HashMap<>(); + cons.put("val1","one"); + cons.put("val2","two"); + ji.setValues(cons); + assertEquals("one",ji.getValues().get("val1")); + } + + @Test + public void testGetRow_specification() { + Map<String,Object> cons = new HashMap<>(); + cons.put("val1","one"); + cons.put("val2","two"); + ji.setRow_specification(cons); + assertEquals("two",ji.getRow_specification().get("val2")); + } + + +} diff --git a/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonKeySpaceTest.java b/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonKeySpaceTest.java new file mode 100644 index 00000000..882d5d5e --- /dev/null +++ b/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonKeySpaceTest.java @@ -0,0 +1,72 @@ +/* + * ============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.HashMap; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.onap.music.datastore.jsonobjects.JsonKeySpace; + +public class JsonKeySpaceTest { + + JsonKeySpace jk = null; + + + @Before + public void init() { + jk = new JsonKeySpace(); + } + + + + @Test + public void testGetConsistencyInfo() { + Map<String, String> mapSs = new HashMap<>(); + mapSs.put("k1", "one"); + jk.setConsistencyInfo(mapSs); + assertEquals("one",jk.getConsistencyInfo().get("k1")); + } + + @Test + public void testGetReplicationInfo() { + Map<String,Object> mapSo = new HashMap<>(); + mapSo.put("k1", "one"); + jk.setReplicationInfo(mapSo); + assertEquals("one",jk.getReplicationInfo().get("k1")); + + } + + @Test + public void testGetDurabilityOfWrites() { + jk.setDurabilityOfWrites("1"); + assertEquals("1",jk.getDurabilityOfWrites()); + } + + @Test + public void testGetKeyspaceName() { + jk.setKeyspaceName("Keyspace"); + assertEquals("Keyspace",jk.getKeyspaceName()); + } + +} diff --git a/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonLeasedLockTest.java b/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonLeasedLockTest.java new file mode 100644 index 00000000..63f901c6 --- /dev/null +++ b/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonLeasedLockTest.java @@ -0,0 +1,53 @@ +/* + * ============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.JsonLeasedLock; + +public class JsonLeasedLockTest { + + JsonLeasedLock jl = null; + + @Before + public void init() { + jl = new JsonLeasedLock(); + } + + + @Test + public void testGetLeasePeriod() { + long lease = 20000; + jl.setLeasePeriod(lease); + assertEquals(lease,jl.getLeasePeriod()); + } + + @Test + public void testGetNotifyUrl() { + String url = "http://somewhere.com"; + jl.setNotifyUrl(url); + assertEquals(url,jl.getNotifyUrl()); + } + +} diff --git a/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonOnboardTest.java b/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonOnboardTest.java new file mode 100644 index 00000000..82f1748a --- /dev/null +++ b/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonOnboardTest.java @@ -0,0 +1,78 @@ +/* + * ============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/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonSelectTest.java b/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonSelectTest.java new file mode 100644 index 00000000..0243232f --- /dev/null +++ b/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonSelectTest.java @@ -0,0 +1,41 @@ +/* + * ============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.HashMap; +import java.util.Map; +import org.junit.Test; +import org.onap.music.datastore.jsonobjects.JsonSelect; + +public class JsonSelectTest { + + @Test + public void testGetConsistencyInfo() { + JsonSelect js = new JsonSelect(); + Map<String, String> mapSs = new HashMap<>(); + mapSs.put("k1", "one"); + js.setConsistencyInfo(mapSs); + assertEquals("one",js.getConsistencyInfo().get("k1")); + } + +} diff --git a/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonTableTest.java b/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonTableTest.java new file mode 100644 index 00000000..e4c800fc --- /dev/null +++ b/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonTableTest.java @@ -0,0 +1,99 @@ +/* + * ============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.HashMap; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.onap.music.datastore.jsonobjects.JsonTable; + +public class JsonTableTest { + + JsonTable jt = null; + + @Before + public void init() { + jt = new JsonTable(); + } + + @Test + public void testGetConsistencyInfo() { + Map<String, String> mapSs = new HashMap<>(); + mapSs.put("k1", "one"); + jt.setConsistencyInfo(mapSs); + assertEquals("one",jt.getConsistencyInfo().get("k1")); + } + + @Test + public void testGetProperties() { + Map<String, Object> properties = new HashMap<>(); + properties.put("k1", "one"); + jt.setProperties(properties); + } + + @Test + public void testGetFields() { + Map<String, String> fields = new HashMap<>(); + fields.put("k1", "one"); + jt.setFields(fields); + assertEquals("one",jt.getFields().get("k1")); + } + + @Test + public void testGetKeyspaceName() { + String keyspace = "keyspace"; + jt.setKeyspaceName(keyspace); + assertEquals(keyspace,jt.getKeyspaceName()); + } + + @Test + public void testGetTableName() { + String table = "table"; + jt.setTableName(table); + assertEquals(table,jt.getTableName()); + } + + @Test + public void testGetSortingKey() { + String sortKey = "sortkey"; + jt.setSortingKey(sortKey); + assertEquals(sortKey,jt.getSortingKey()); + } + + @Test + public void testGetClusteringOrder() { + String clusteringOrder = "clusteringOrder"; + jt.setClusteringOrder(clusteringOrder); + assertEquals(clusteringOrder,jt.getClusteringOrder()); + } + + @Test + public void testGetPrimaryKey() { + String primaryKey = "primaryKey"; + jt.setPrimaryKey(primaryKey); + assertEquals(primaryKey,jt.getPrimaryKey()); + } + +} diff --git a/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonUpdateTest.java b/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonUpdateTest.java new file mode 100644 index 00000000..54db0540 --- /dev/null +++ b/jar/src/test/java/org/onap/music/unittests/jsonobjects/JsonUpdateTest.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2018 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.HashMap; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.onap.music.datastore.jsonobjects.JsonUpdate; + +public class JsonUpdateTest { + + JsonUpdate ju = null; + + @Before + public void init() { + ju = new JsonUpdate(); + } + + + @Test + public void testGetConditions() { + Map<String,Object> mapSo = new HashMap<>(); + mapSo.put("key1","one"); + mapSo.put("key2","two"); + ju.setConditions(mapSo); + assertEquals("one",ju.getConditions().get("key1")); + } + + @Test + public void testGetRow_specification() { + Map<String,Object> mapSo = new HashMap<>(); + mapSo.put("key1","one"); + mapSo.put("key2","two"); + ju.setRow_specification(mapSo); + assertEquals("one",ju.getRow_specification().get("key1")); + } + + @Test + public void testGetKeyspaceName() { + String keyspace = "keyspace"; + ju.setKeyspaceName(keyspace); + assertEquals(keyspace,ju.getKeyspaceName()); + } + + @Test + public void testGetTableName() { + String table = "table"; + ju.setTableName(table); + assertEquals(table,ju.getTableName()); + } + + @Test + public void testGetConsistencyInfo() { + Map<String, String> mapSs = new HashMap<>(); + mapSs.put("k1", "one"); + ju.setConsistencyInfo(mapSs); + assertEquals("one",ju.getConsistencyInfo().get("k1")); + } + + @Test + public void testGetTtl() { + ju.setTtl("2000"); + assertEquals("2000",ju.getTtl()); + } + + @Test + public void testGetTimestamp() { + ju.setTimestamp("20:00"); + assertEquals("20:00",ju.getTimestamp()); + + } + + @Test + public void testGetValues() { + Map<String,Object> cons = new HashMap<>(); + cons.put("val1","one"); + cons.put("val2","two"); + ju.setValues(cons); + assertEquals("one",ju.getValues().get("val1")); + } + +} diff --git a/jar/version.properties b/jar/version.properties new file mode 100644 index 00000000..d80599bb --- /dev/null +++ b/jar/version.properties @@ -0,0 +1,13 @@ +# Versioning variables +# Note that these variables cannot be structured (e.g. : version.release or version.snapshot etc... ) +# because they are used in Jenkins, whose plug-in doesn't support + +major=2 +minor=5 +patch=11 + +base_version=${major}.${minor}.${patch} + +# Release must be completed with git revision # in Jenkins +release_version=${base_version} +snapshot_version=${base_version}-SNAPSHOT @@ -25,7 +25,7 @@ <groupId>org.onap.music</groupId> <artifactId>MUSIC</artifactId> <packaging>war</packaging> - <version>2.5.3</version> + <version>2.5.11</version> <description> This is the MUSIC REST interface, packaged as a war file. </description> diff --git a/src/main/java/org/onap/music/conductor/conditionals/JsonConditional.java b/src/main/java/org/onap/music/conductor/conditionals/JsonConditional.java new file mode 100644 index 00000000..0e971eb6 --- /dev/null +++ b/src/main/java/org/onap/music/conductor/conditionals/JsonConditional.java @@ -0,0 +1,89 @@ +/* + * ============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.conductor.conditionals; + +import java.io.Serializable; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import io.swagger.annotations.ApiModel; + +@ApiModel(value = "JsonConditional", description = "Json model for insert or update into table based on some conditions") +@JsonIgnoreProperties(ignoreUnknown = true) +public class JsonConditional implements Serializable { + + private String primaryKey; + private String primaryKeyValue; + private String casscadeColumnName; + private Map<String,Object> tableValues; + private Map<String,Object> casscadeColumnData; + private Map<String,Map<String,String>> conditions; + + public Map<String, Object> getTableValues() { + return tableValues; + } + public void setTableValues(Map<String, Object> tableValues) { + this.tableValues = tableValues; + } + + public String getPrimaryKey() { + return primaryKey; + } + public String getPrimaryKeyValue() { + return primaryKeyValue; + } + public String getCasscadeColumnName() { + return casscadeColumnName; + } + + public Map<String, Object> getCasscadeColumnData() { + return casscadeColumnData; + } + + + + public void setPrimaryKey(String primaryKey) { + this.primaryKey = primaryKey; + } + public void setPrimaryKeyValue(String primaryKeyValue) { + this.primaryKeyValue = primaryKeyValue; + } + public Map<String, Map<String, String>> getConditions() { + return conditions; + } + public void setConditions(Map<String, Map<String, String>> conditions) { + this.conditions = conditions; + } + public void setCasscadeColumnName(String casscadeColumnName) { + this.casscadeColumnName = casscadeColumnName; + } + + public void setCasscadeColumnData(Map<String, Object> casscadeColumnData) { + this.casscadeColumnData = casscadeColumnData; + } + + + + + +} diff --git a/src/main/java/org/onap/music/conductor/conditionals/MusicContional.java b/src/main/java/org/onap/music/conductor/conditionals/MusicContional.java new file mode 100644 index 00000000..93e34721 --- /dev/null +++ b/src/main/java/org/onap/music/conductor/conditionals/MusicContional.java @@ -0,0 +1,357 @@ +/* + * ============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.conductor.conditionals; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.Map; + +import javax.ws.rs.core.Response.Status; + +import org.codehaus.jettison.json.JSONObject; +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.lockingservice.MusicLockState; +import org.onap.music.main.MusicCore; +import org.onap.music.main.MusicUtil; +import org.onap.music.main.ResultType; +import org.onap.music.main.ReturnType; +import org.onap.music.response.jsonobjects.JsonResponse; +import org.onap.music.rest.RestMusicDataAPI; + +import com.datastax.driver.core.ColumnDefinitions; +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.TableMetadata; + +public class MusicContional { + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicDataAPI.class); + + public static ReturnType conditionalInsert(String keyspace, String tablename, String casscadeColumnName, + Map<String, Object> casscadeColumnData, String primaryKey, Map<String, Object> valuesMap, + Map<String, String> status) throws Exception { + + Map<String, PreparedQueryObject> queryBank = new HashMap<>(); + TableMetadata tableInfo = null; + tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename); + DataType primaryIdType = tableInfo.getPrimaryKey().get(0).getType(); + String primaryId = tableInfo.getPrimaryKey().get(0).getName(); + DataType casscadeColumnType = tableInfo.getColumn(casscadeColumnName).getType(); + String vector = String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis()); + + PreparedQueryObject select = new PreparedQueryObject(); + select.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " where " + primaryId + " = ?"); + select.addValue(MusicUtil.convertToActualDataType(primaryIdType, primaryKey)); + queryBank.put(MusicUtil.SELECT, select); + + PreparedQueryObject update = new PreparedQueryObject(); + Map<String, String> updateColumnvalues = new HashMap<>(); //casscade column values + updateColumnvalues = getValues(true, casscadeColumnData, status); + Object formatedValues = MusicUtil.convertToActualDataType(casscadeColumnType, updateColumnvalues); + update.appendQueryString("UPDATE " + keyspace + "." + tablename + " SET " + casscadeColumnName + " =" + + casscadeColumnName + " + ? , vector_ts = ?" + " WHERE " + primaryId + " = ? "); + update.addValue(formatedValues); + update.addValue(MusicUtil.convertToActualDataType(DataType.text(), vector)); + update.addValue(MusicUtil.convertToActualDataType(primaryIdType, primaryKey)); + queryBank.put(MusicUtil.UPDATE, update); + + Map<String, String> insertColumnvalues = new HashMap<>(); + insertColumnvalues = getValues(false, casscadeColumnData, status); + formatedValues = MusicUtil.convertToActualDataType(casscadeColumnType, insertColumnvalues); + PreparedQueryObject insert = extractQuery(valuesMap, tableInfo, tablename, keyspace, primaryId, primaryKey,casscadeColumnName,formatedValues); + queryBank.put(MusicUtil.INSERT, insert); + + + String key = keyspace + "." + tablename + "." + primaryKey; + String lockId = MusicCore.createLockReference(key); + long leasePeriod = MusicUtil.getDefaultLockLeasePeriod(); + ReturnType lockAcqResult = MusicCore.acquireLockWithLease(key, lockId, leasePeriod); + + try { + if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) { + ReturnType criticalPutResult = conditionalInsertAtomic(lockId, keyspace, tablename, primaryKey, + queryBank); + MusicCore.destroyLockRef(lockId); + if (criticalPutResult.getMessage().contains("insert")) + criticalPutResult + .setMessage("Insert values: "); + else if (criticalPutResult.getMessage().contains("update")) + criticalPutResult + .setMessage("Update values: " + updateColumnvalues); + return criticalPutResult; + + } else { + MusicCore.destroyLockRef(lockId); + return lockAcqResult; + } + } catch (Exception e) { + MusicCore.destroyLockRef(lockId); + return new ReturnType(ResultType.FAILURE, e.getMessage()); + } + + } + + public static ReturnType conditionalInsertAtomic(String lockId, String keyspace, String tableName, + String primaryKey, Map<String, PreparedQueryObject> queryBank) { + + ResultSet results = null; + + try { + + MusicLockState mls = MusicCore.getLockingServiceHandle() + .getLockState(keyspace + "." + tableName + "." + primaryKey); + if (mls.getLockHolder().equals(lockId) == true) { + try { + results = MusicCore.getDSHandle().executeCriticalGet(queryBank.get(MusicUtil.SELECT)); + } catch (Exception e) { + return new ReturnType(ResultType.FAILURE, e.getMessage()); + } + if (results.all().isEmpty()) { + MusicCore.getDSHandle().executePut(queryBank.get(MusicUtil.INSERT), "critical"); + return new ReturnType(ResultType.SUCCESS, "insert"); + } else { + MusicCore.getDSHandle().executePut(queryBank.get(MusicUtil.UPDATE), "critical"); + return new ReturnType(ResultType.SUCCESS, "update"); + } + } else { + return new ReturnType(ResultType.FAILURE, + "Cannot perform operation since you are the not the lock holder"); + } + + } catch (Exception e) { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + String exceptionAsString = sw.toString(); + return new ReturnType(ResultType.FAILURE, + "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n" + + exceptionAsString); + } + + } + + public static ReturnType update(Map<String,PreparedQueryObject> queryBank, String keyspace, String tableName, String primaryKey,String primaryKeyValue,String planId,String cascadeColumnName,Map<String,String> cascadeColumnValues) { + + String key = keyspace + "." + tableName + "." + primaryKeyValue; + String lockId = MusicCore.createLockReference(key); + long leasePeriod = MusicUtil.getDefaultLockLeasePeriod(); + ReturnType lockAcqResult = MusicCore.acquireLockWithLease(key, lockId, leasePeriod); + + try { + + if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) { + return updateAtomic(lockId, keyspace, tableName, primaryKey,primaryKeyValue, queryBank,planId,cascadeColumnValues,cascadeColumnName); + + } else { + MusicCore.destroyLockRef(lockId); + return lockAcqResult; + } + + } catch (Exception e) { + MusicCore.destroyLockRef(lockId); + return new ReturnType(ResultType.FAILURE, e.getMessage()); + + } + } + + public static ReturnType updateAtomic(String lockId, String keyspace, String tableName, String primaryKey,String primaryKeyValue, + Map<String,PreparedQueryObject> queryBank,String planId,Map<String,String> cascadeColumnValues,String casscadeColumnName) { + try { + + MusicLockState mls = MusicCore.getLockingServiceHandle() + .getLockState(keyspace + "." + tableName + "." + primaryKeyValue); + if (mls.getLockHolder().equals(lockId) == true) { + Row row = MusicCore.getDSHandle().executeCriticalGet(queryBank.get(MusicUtil.SELECT)).one(); + + if(row != null) { + Map<String, String> updatedValues = cascadeColumnUpdateSpecific(row, cascadeColumnValues, casscadeColumnName, planId); + JSONObject json = new JSONObject(updatedValues); + PreparedQueryObject update = new PreparedQueryObject(); + String vector_ts = String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis()); + update.appendQueryString("UPDATE " + keyspace + "." + tableName + " SET " + casscadeColumnName + "['" + planId + + "'] = ?, vector_ts = ? WHERE " + primaryKey + " = ?"); + update.addValue(MusicUtil.convertToActualDataType(DataType.text(), json.toString())); + update.addValue(MusicUtil.convertToActualDataType(DataType.text(), vector_ts)); + update.addValue(MusicUtil.convertToActualDataType(DataType.text(), primaryKeyValue)); + try { + MusicCore.getDSHandle().executePut(update, "critical"); + } catch (Exception ex) { + return new ReturnType(ResultType.FAILURE, ex.getMessage()); + } + }else { + return new ReturnType(ResultType.FAILURE,"Cannot find data related to key: "+primaryKey); + } + + MusicCore.getDSHandle().executePut(queryBank.get(MusicUtil.UPSERT), "critical"); + return new ReturnType(ResultType.SUCCESS, "update success"); + + } else { + return new ReturnType(ResultType.FAILURE, + "Cannot perform operation since you are the not the lock holder"); + } + + } catch (Exception e) { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + String exceptionAsString = sw.toString(); + return new ReturnType(ResultType.FAILURE, + "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n" + + exceptionAsString); + } + + } + + @SuppressWarnings("unchecked") + public static Map<String, String> getValues(boolean isExists, Map<String, Object> casscadeColumnData, + Map<String, String> status) { + + Map<String, String> value = new HashMap<>(); + Map<String, String> returnMap = new HashMap<>(); + Object key = casscadeColumnData.get("key"); + String setStatus = ""; + value = (Map<String, String>) casscadeColumnData.get("value"); + + if (isExists) + setStatus = status.get("exists"); + else + setStatus = status.get("nonexists"); + + value.put("status", setStatus); + JSONObject valueJson = new JSONObject(value); + returnMap.put(key.toString(), valueJson.toString()); + return returnMap; + + } + + + public static PreparedQueryObject extractQuery(Map<String, Object> valuesMap, TableMetadata tableInfo, String tableName, + String keySpaceName,String primaryKeyName,String primaryKey,String casscadeColumn,Object casscadeColumnValues) throws Exception { + + PreparedQueryObject queryObject = new PreparedQueryObject(); + StringBuilder fieldsString = new StringBuilder("(vector_ts"+","); + StringBuilder valueString = new StringBuilder("(" + "?" + ","); + String vector = String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis()); + queryObject.addValue(vector); + if(casscadeColumn!=null && casscadeColumnValues!=null) { + fieldsString.append("" +casscadeColumn+" ," ); + valueString.append("?,"); + queryObject.addValue(casscadeColumnValues); + } + + int counter = 0; + 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); + + } + + Object formattedValue = null; + try { + formattedValue = MusicUtil.convertToActualDataType(colType, valueObj); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); + } + + valueString.append("?"); + queryObject.addValue(formattedValue); + + + if (counter == valuesMap.size() - 1) { + fieldsString.append(")"); + valueString.append(")"); + } else { + fieldsString.append(","); + valueString.append(","); + } + counter = counter + 1; + } + queryObject.appendQueryString("INSERT INTO " + keySpaceName + "." + tableName + " " + + fieldsString + " VALUES " + valueString); + return queryObject; + } + + public static Object getColValue(Row row, String colName, DataType colType) { + switch (colType.getName()) { + case VARCHAR: + return row.getString(colName); + case UUID: + return row.getUUID(colName); + case VARINT: + return row.getVarint(colName); + case BIGINT: + return row.getLong(colName); + case INT: + return row.getInt(colName); + case FLOAT: + return row.getFloat(colName); + case DOUBLE: + return row.getDouble(colName); + case BOOLEAN: + return row.getBool(colName); + case MAP: + return row.getMap(colName, String.class, String.class); + default: + return null; + } + } + + @SuppressWarnings("unchecked") + public static Map<String, String> cascadeColumnUpdateSpecific(Row row, Map<String, String> changeOfStatus, + String cascadeColumnName, String planId) { + + ColumnDefinitions colInfo = row.getColumnDefinitions(); + DataType colType = colInfo.getType(cascadeColumnName); + Map<String, String> values = new HashMap<>(); + Object columnValue = getColValue(row, cascadeColumnName, colType); + + Map<String, String> finalValues = new HashMap<>(); + values = (Map<String, String>) columnValue; + if (values.keySet().contains(planId)) { + String valueString = values.get(planId); + String tempValueString = valueString.replaceAll("\\{", "").replaceAll("\"", "").replaceAll("\\}", ""); + String[] elements = tempValueString.split(","); + for (String str : elements) { + String[] keyValue = str.split(":"); + if ((changeOfStatus.keySet().contains(keyValue[0].replaceAll("\\s", "")))) + keyValue[1] = changeOfStatus.get(keyValue[0].replaceAll("\\s", "")); + finalValues.put(keyValue[0], keyValue[1]); + } + } + return finalValues; + + } + +} diff --git a/src/main/java/org/onap/music/conductor/conditionals/RestMusicConditonalAPI.java b/src/main/java/org/onap/music/conductor/conditionals/RestMusicConditonalAPI.java new file mode 100644 index 00000000..c13dd621 --- /dev/null +++ b/src/main/java/org/onap/music/conductor/conditionals/RestMusicConditonalAPI.java @@ -0,0 +1,218 @@ +/* + * ============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.conductor.conditionals; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.ws.rs.Consumes; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.core.Response.Status; + +import org.codehaus.jettison.json.JSONObject; +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.main.MusicCore; +import org.onap.music.main.MusicUtil; +import org.onap.music.main.ResultType; +import org.onap.music.main.ReturnType; +import org.onap.music.response.jsonobjects.JsonResponse; +import org.onap.music.rest.RestMusicAdminAPI; + +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.TableMetadata; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiParam; + +@Path("/v2/conditional") +@Api(value = "Conditional Api", hidden = true) +public class RestMusicConditonalAPI { + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicAdminAPI.class); + private static final String XMINORVERSION = "X-minorVersion"; + private static final String XPATCHVERSION = "X-patchVersion"; + private static final String NS = "ns"; + private static final String USERID = "userId"; + private static final String PASSWORD = "password"; + private static final String VERSION = "v2"; + + @POST + @Path("/insert/keyspaces/{keyspace}/tables/{tablename}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response insertConditional( + @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 = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", required = true) @HeaderParam(NS) String ns, + @ApiParam(value = "userId", required = true) @HeaderParam(USERID) String userId, + @ApiParam(value = "Password", required = true) @HeaderParam(PASSWORD) String password, + @ApiParam(value = "Major Version", required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Major Version", required = true) @PathParam("tablename") String tablename, + JsonConditional jsonObj) throws Exception { + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + String primaryKey = jsonObj.getPrimaryKey(); + String primaryKeyValue = jsonObj.getPrimaryKeyValue(); + String casscadeColumnName = jsonObj.getCasscadeColumnName(); + Map<String, Object> tableValues = jsonObj.getTableValues(); + Map<String, Object> casscadeColumnData = jsonObj.getCasscadeColumnData(); + Map<String, Map<String, String>> conditions = jsonObj.getConditions(); + + if (primaryKey == null || primaryKeyValue == null || casscadeColumnName == null || tableValues.isEmpty() + || casscadeColumnData.isEmpty() || conditions.isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGINFO, ErrorSeverity.CRITICAL, + ErrorTypes.AUTHENTICATIONERROR); + return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE) + .setError(String.valueOf("One or more input values missing")).toMap()).build(); + + } + + Map<String, Object> authMap = null; + try { + authMap = MusicCore.autheticateUser(ns, userId, password, keyspace, aid, "insertIntoTable"); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGINFO, ErrorSeverity.CRITICAL, + ErrorTypes.AUTHENTICATIONERROR); + return response.status(Status.UNAUTHORIZED) + .entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); + } + if (authMap.containsKey("aid")) + authMap.remove("aid"); + if (!authMap.isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGINFO, ErrorSeverity.CRITICAL, + ErrorTypes.AUTHENTICATIONERROR); + return response.status(Status.UNAUTHORIZED).entity( + new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()) + .build(); + } + + Map<String, Object> valuesMap = new LinkedHashMap<>(); + for (Map.Entry<String, Object> entry : tableValues.entrySet()) { + valuesMap.put(entry.getKey(), entry.getValue()); + } + + Map<String, String> status = new HashMap<>(); + status.put("exists", conditions.get("exists").get("status").toString()); + status.put("nonexists", conditions.get("nonexists").get("status").toString()); + ReturnType out = null; + + out = MusicContional.conditionalInsert(keyspace, tablename, casscadeColumnName, casscadeColumnData, + primaryKeyValue, valuesMap, status); + return response.status(Status.OK).entity(new JsonResponse(out.getResult()).setMessage(out.getMessage()).toMap()) + .build(); + + } + + @SuppressWarnings("unchecked") + @PUT + @Path("/update/keyspaces/{keyspace}/tables/{tablename}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response updateConditional( + @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 = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", required = true) @HeaderParam(NS) String ns, + @ApiParam(value = "userId", required = true) @HeaderParam(USERID) String userId, + @ApiParam(value = "Password", required = true) @HeaderParam(PASSWORD) String password, + @ApiParam(value = "Major Version", required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Major Version", required = true) @PathParam("tablename") String tablename, + JsonConditional upObj) throws Exception { + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + + String primaryKey = upObj.getPrimaryKey(); + String primaryKeyValue = upObj.getPrimaryKeyValue(); + String casscadeColumnName = upObj.getCasscadeColumnName(); + Map<String, Object> casscadeColumnData = upObj.getCasscadeColumnData(); + Map<String, Object> tableValues = upObj.getTableValues(); + + if (primaryKey == null || primaryKeyValue == null || casscadeColumnName == null + || casscadeColumnData.isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGINFO, ErrorSeverity.CRITICAL, + ErrorTypes.AUTHENTICATIONERROR); + return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE) + .setError(String.valueOf("One or more input values missing")).toMap()).build(); + + } + + Map<String, Object> authMap = null; + try { + authMap = MusicCore.autheticateUser(ns, userId, password, keyspace, aid, "updateTable"); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGINFO, ErrorSeverity.CRITICAL, + ErrorTypes.AUTHENTICATIONERROR); + return response.status(Status.UNAUTHORIZED) + .entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); + } + if (authMap.containsKey("aid")) + authMap.remove("aid"); + if (!authMap.isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGINFO, ErrorSeverity.CRITICAL, + ErrorTypes.AUTHENTICATIONERROR); + return response.status(Status.UNAUTHORIZED).entity( + new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()) + .build(); + } + + String planId = casscadeColumnData.get("key").toString(); + Map<String,String> casscadeColumnValueMap = (Map<String, String>) casscadeColumnData.get("value"); + TableMetadata tableInfo = null; + tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename); + DataType primaryIdType = tableInfo.getPrimaryKey().get(0).getType(); + String primaryId = tableInfo.getPrimaryKey().get(0).getName(); + + PreparedQueryObject upsert = MusicContional.extractQuery(tableValues, tableInfo, tablename, keyspace, primaryKey, primaryKeyValue, null, null); + + PreparedQueryObject select = new PreparedQueryObject(); + select.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " where " + primaryId + " = ?"); + select.addValue(MusicUtil.convertToActualDataType(primaryIdType, primaryKeyValue)); + + Map<String,PreparedQueryObject> queryBank = new HashMap<>(); + //queryBank.put(MusicUtil.UPDATE, update); + queryBank.put(MusicUtil.UPSERT, upsert); + queryBank.put(MusicUtil.SELECT, select); + ReturnType result = MusicContional.update(queryBank, keyspace, tablename, primaryKey,primaryKeyValue,planId,casscadeColumnName,casscadeColumnValueMap); + if (result.getResult() == ResultType.SUCCESS) { + return response.status(Status.OK) + .entity(new JsonResponse(result.getResult()).setMessage(result.getMessage()).toMap()).build(); + + } + return response.status(Status.BAD_REQUEST) + .entity(new JsonResponse(result.getResult()).setMessage(result.getMessage()).toMap()).build(); + + } + +} diff --git a/src/main/java/org/onap/music/datastore/MusicDataStore.java b/src/main/java/org/onap/music/datastore/MusicDataStore.java index 278cf768..e9356f9d 100644 --- a/src/main/java/org/onap/music/datastore/MusicDataStore.java +++ b/src/main/java/org/onap/music/datastore/MusicDataStore.java @@ -253,6 +253,8 @@ public class MusicDataStore { return row.getBool(colName); case MAP: return row.getMap(colName, String.class, String.class); + case LIST: + return row.getList(colName, String.class); default: return null; } diff --git a/src/main/java/org/onap/music/lockingservice/MusicLockingService.java b/src/main/java/org/onap/music/lockingservice/MusicLockingService.java index ae026903..d0c33000 100644 --- a/src/main/java/org/onap/music/lockingservice/MusicLockingService.java +++ b/src/main/java/org/onap/music/lockingservice/MusicLockingService.java @@ -19,6 +19,8 @@ package org.onap.music.lockingservice; import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; import java.util.StringTokenizer; import java.util.concurrent.CountDownLatch; @@ -97,7 +99,12 @@ public class MusicLockingService implements Watcher { try{ data = zkLockHandle.getNodeData(lockName); }catch (Exception ex){ - logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(),AppMessages.UNKNOWNERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + StringWriter sw = new StringWriter(); + ex.printStackTrace(); + ex.printStackTrace(new PrintWriter(sw)); + String exceptionAsString = sw.toString(); + logger.error(EELFLoggerDelegate.errorLogger,exceptionAsString); + throw new MusicLockingException(exceptionAsString); } if(data !=null) return MusicLockState.deSerialize(data); diff --git a/src/main/java/org/onap/music/main/CachingUtil.java b/src/main/java/org/onap/music/main/CachingUtil.java index b59e81b3..26491302 100755 --- a/src/main/java/org/onap/music/main/CachingUtil.java +++ b/src/main/java/org/onap/music/main/CachingUtil.java @@ -101,8 +101,8 @@ public class CachingUtil implements Runnable { String keySpace = row.getString("application_name"); try { userAttempts.put(nameSpace, 0); - AAFResponse responseObj = triggerAAF(nameSpace, userId, password); - if (responseObj.getNs().size() > 0) { + boolean aafRresponse = triggerAAF(nameSpace, userId, password); + if (aafRresponse) { map = new HashMap<>(); map.put(userId, password); aafCache.put(nameSpace, map); @@ -163,20 +163,21 @@ public class CachingUtil implements Runnable { } } - AAFResponse responseObj = triggerAAF(nameSpace, userId, password); - if (responseObj.getNs().size() > 0) { - if (responseObj.getNs().get(0).getAdmin().contains(userId)) { + boolean aafRresponse = triggerAAF(nameSpace, userId, password); + if (aafRresponse) { + //TODO + //if (responseObj.getNs().get(0).getAdmin().contains(userId)) { //Map<String, String> map = new HashMap<>(); //map.put(userId, password); //aafCache.put(nameSpace, map); return true; - } + //} } logger.info(EELFLoggerDelegate.applicationLogger,"Invalid user. Cache not updated"); - return false; + return aafRresponse; } - private static AAFResponse triggerAAF(String nameSpace, String userId, String password) + private static boolean triggerAAF(String nameSpace, String userId, String password) throws Exception { if (MusicUtil.getAafEndpointUrl() == null) { logger.error(EELFLoggerDelegate.errorLogger,"",AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); @@ -194,7 +195,9 @@ public class CachingUtil implements Runnable { ClientResponse response = webResource.accept(MediaType.APPLICATION_JSON) .header("Authorization", "Basic " + base64Creds) .header("content-type", "application/json").get(ClientResponse.class); - if (response.getStatus() != 200) { + if(response.getStatus() == 200) + return true; + else if (response.getStatus() != 200) { if (userAttempts.get(nameSpace) == null) userAttempts.put(nameSpace, 0); if ((Integer) userAttempts.get(nameSpace) >= 2) { @@ -209,14 +212,14 @@ public class CachingUtil implements Runnable { // TODO Allow for 2-3 times and forbid any attempt to trigger AAF with invalid values // for specific time. } - response.getHeaders().put(HttpHeaders.CONTENT_TYPE, + /*response.getHeaders().put(HttpHeaders.CONTENT_TYPE, Arrays.asList(MediaType.APPLICATION_JSON)); // AAFResponse output = response.getEntity(AAFResponse.class); response.bufferEntity(); String x = response.getEntity(String.class); - AAFResponse responseObj = new ObjectMapper().readValue(x, AAFResponse.class); + AAFResponse responseObj = new ObjectMapper().readValue(x, AAFResponse.class);*/ - return responseObj; + return false; } public static void updateMusicCache(String keyspace, String nameSpace) { diff --git a/src/main/java/org/onap/music/main/MusicCore.java b/src/main/java/org/onap/music/main/MusicCore.java index dfc93ccc..cc147d57 100644 --- a/src/main/java/org/onap/music/main/MusicCore.java +++ b/src/main/java/org/onap/music/main/MusicCore.java @@ -22,6 +22,7 @@ package org.onap.music.main; +import java.io.PrintWriter; import java.io.StringWriter; import java.util.HashMap; import java.util.Map; @@ -664,6 +665,7 @@ public class MusicCore { "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n" + e.getMessage()); }catch(MusicLockingException ex){ + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage()); return new ReturnType(ResultType.FAILURE,ex.getMessage()); } diff --git a/src/main/java/org/onap/music/main/MusicUtil.java b/src/main/java/org/onap/music/main/MusicUtil.java index 5b442a79..20bb0a48 100755 --- a/src/main/java/org/onap/music/main/MusicUtil.java +++ b/src/main/java/org/onap/music/main/MusicUtil.java @@ -54,6 +54,10 @@ public class MusicUtil { private static final String XLATESTVERSION = "X-latestVersion"; private static final String XMINORVERSION = "X-minorVersion"; private static final String XPATCHVERSION = "X-patchVersion"; + public static final String SELECT = "select"; + public static final String INSERT = "insert"; + public static final String UPDATE = "update"; + public static final String UPSERT = "upsert"; private static final String LOCALHOST = "localhost"; private static final String PROPERTIES_FILE = "/opt/app/music/etc/music.properties"; @@ -343,7 +347,8 @@ public class MusicUtil { try { Scanner fileScanner = new Scanner(new File("")); testType = fileScanner.next();// ignore the my id line - String batchSize = fileScanner.next();// ignore the my public ip + @SuppressWarnings("unused") + String batchSize = fileScanner.next();// ignore the my public ip // line fileScanner.close(); } catch (FileNotFoundException e) { @@ -411,7 +416,8 @@ public class MusicUtil { value = "'" + valueString + "'"; break; case MAP: { - Map<String, Object> otMap = (Map<String, Object>) valueObj; + @SuppressWarnings("unchecked") + Map<String, Object> otMap = (Map<String, Object>) valueObj; value = "{" + jsonMaptoSqlString(otMap, ",") + "}"; break; } @@ -430,7 +436,8 @@ public class MusicUtil { * @throws MusicTypeConversionException * @throws Exception */ - public static Object convertToActualDataType(DataType colType, Object valueObj) throws Exception { + @SuppressWarnings("unchecked") + public static Object convertToActualDataType(DataType colType, Object valueObj) throws Exception { String valueObjString = valueObj + ""; switch (colType.getName()) { case UUID: @@ -449,6 +456,8 @@ public class MusicUtil { return Boolean.parseBoolean(valueObjString); case MAP: return (Map<String, Object>) valueObj; + case LIST: + return (List<String>)valueObj; default: return valueObjString; } @@ -480,7 +489,6 @@ public class MusicUtil { return sqlString.toString(); } - @SuppressWarnings("unused") public static String buildVersion(String major, String minor, String patch) { if (minor != null) { major += "." + minor; diff --git a/src/main/java/org/onap/music/rest/RestMusicDataAPI.java b/src/main/java/org/onap/music/rest/RestMusicDataAPI.java index 93b8f82a..39d5a890 100755 --- a/src/main/java/org/onap/music/rest/RestMusicDataAPI.java +++ b/src/main/java/org/onap/music/rest/RestMusicDataAPI.java @@ -1139,7 +1139,10 @@ public class RestMusicDataAPI { results = MusicCore.atomicGetWithDeleteLock(keyspace, tablename, rowId.primarKeyValue, queryObject); } - return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicCore.marshallResults(results)).toMap()).build(); + if(results!=null && results.getAvailableWithoutFetching() >0) { + return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicCore.marshallResults(results)).toMap()).build(); + } + return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setError("No data found").setDataResult(MusicCore.marshallResults(results)).toMap()).build(); } /** @@ -1200,7 +1203,10 @@ public class RestMusicDataAPI { try { ResultSet results = MusicCore.get(queryObject); - return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicCore.marshallResults(results)).toMap()).build(); + if(results!=null && results.getAvailableWithoutFetching() >0) { + return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicCore.marshallResults(results)).toMap()).build(); + } + return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setError("No data found").setDataResult(MusicCore.marshallResults(results)).toMap()).build(); } catch (MusicServiceException ex) { logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.UNKNOWNERROR ,ErrorSeverity.ERROR, ErrorTypes.MUSICSERVICEERROR); return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); @@ -1274,6 +1280,7 @@ public class RestMusicDataAPI { } catch (Exception e) { logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); } + if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey())) primaryKey.append(indValue); rowSpec.append(keyName + "= ?"); queryObject.addValue(formattedValue); diff --git a/version.properties b/version.properties index 8cfb5921..d80599bb 100644 --- a/version.properties +++ b/version.properties @@ -4,7 +4,7 @@ major=2 minor=5 -patch=3 +patch=11 base_version=${major}.${minor}.${patch} |