From 881f14bc8676cedd68e17bd007a869fa85578fa1 Mon Sep 17 00:00:00 2001 From: Thomas Nelson arthudent3 Date: Wed, 19 Jun 2019 22:19:10 +0000 Subject: Some bug fixes and Minor Chages. Remove some Commented out code. Cleaned up Variables. Encryption of passwords added Updated Test Cases Fixed some errors in how they were reported. Reduced Logging clutter Some Vulnerability fixes. Change-Id: I64c7935d167d4a976681b5a18fd51aa667d0cd95 Issue-ID: MUSIC-413 Signed-off-by: Thomas Nelson arthudent3 --- src/main/java/org/onap/music/JerseyConfig.java | 32 +- src/main/java/org/onap/music/MusicApplication.java | 10 +- .../org/onap/music/authentication/AuthUtil.java | 14 +- .../onap/music/authentication/CadiAuthFilter.java | 2 +- .../authentication/MusicAuthorizationFilter.java | 33 +- .../org/onap/music/datastore/MusicDataStore.java | 40 +-- .../music/datastore/jsonobjects/JsonInsert.java | 20 +- .../datastore/jsonobjects/JsonLeasedLock.java | 11 +- .../onap/music/datastore/jsonobjects/JsonLock.java | 8 +- .../music/eelf/healthcheck/MusicHealthCheck.java | 28 +- .../music/eelf/logging/EELFLoggerDelegate.java | 9 +- .../music/eelf/logging/MusicContainerFilter.java | 54 ++-- .../eelf/logging/MusicLoggingServletFilter.java | 6 +- .../lockingservice/cassandra/CassaLockStore.java | 37 ++- src/main/java/org/onap/music/main/CipherUtil.java | 270 ++++++++++++++++ src/main/java/org/onap/music/main/MusicCore.java | 2 +- src/main/java/org/onap/music/main/MusicDigest.java | 79 ----- src/main/java/org/onap/music/main/MusicUtil.java | 339 ++++++++------------- .../java/org/onap/music/main/PropertiesLoader.java | 76 ++--- .../music/response/jsonobjects/JsonResponse.java | 14 +- .../java/org/onap/music/rest/RestMusicDataAPI.java | 296 ++++++++++++++---- .../onap/music/rest/RestMusicHealthCheckAPI.java | 26 +- .../org/onap/music/rest/RestMusicLocksAPI.java | 212 ++++++++++--- .../java/org/onap/music/rest/RestMusicQAPI.java | 7 +- .../java/org/onap/music/rest/RestMusicTestAPI.java | 2 + .../org/onap/music/service/MusicCoreService.java | 2 +- .../onap/music/service/impl/MusicCassaCore.java | 58 ++-- 27 files changed, 1051 insertions(+), 636 deletions(-) create mode 100644 src/main/java/org/onap/music/main/CipherUtil.java delete mode 100644 src/main/java/org/onap/music/main/MusicDigest.java (limited to 'src/main/java/org/onap') diff --git a/src/main/java/org/onap/music/JerseyConfig.java b/src/main/java/org/onap/music/JerseyConfig.java index fbf71f3a..b64e7044 100755 --- a/src/main/java/org/onap/music/JerseyConfig.java +++ b/src/main/java/org/onap/music/JerseyConfig.java @@ -1,17 +1,23 @@ /* - * Copyright 2012-2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== */ package org.onap.music; diff --git a/src/main/java/org/onap/music/MusicApplication.java b/src/main/java/org/onap/music/MusicApplication.java index 8f5f773e..9b831e37 100755 --- a/src/main/java/org/onap/music/MusicApplication.java +++ b/src/main/java/org/onap/music/MusicApplication.java @@ -33,6 +33,7 @@ import org.onap.music.authentication.CadiAuthFilter; import org.onap.music.authentication.MusicAuthorizationFilter; import org.onap.music.eelf.logging.EELFLoggerDelegate; import org.onap.music.eelf.logging.MusicLoggingServletFilter; +import org.onap.music.main.CipherUtil; import org.onap.music.main.MusicUtil; import org.onap.music.main.PropertiesLoader; import org.springframework.beans.factory.annotation.Autowired; @@ -42,7 +43,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.FilterRegistrationBean; -//import org.springframework.boot.web.support.SpringBootServletInitializer; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; @@ -51,7 +51,7 @@ import org.springframework.context.annotation.DependsOn; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.web.context.request.RequestContextListener; -@SpringBootApplication(scanBasePackages = { "org.onap.music.rest" }) +@SpringBootApplication(scanBasePackages = { "org.onap.music.rest"}) @EnableAutoConfiguration(exclude = { CassandraDataAutoConfiguration.class }) @ComponentScan(value = { "org.onap.music" }) @EnableScheduling @@ -62,10 +62,6 @@ public class MusicApplication extends SpringBootServletInitializer { private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicApplication.class); public static void main(String[] args) { - System.setProperty("AFT_DME2_CLIENT_IGNORE_SSL_CONFIG", "false"); - System.setProperty("AFT_DME2_CLIENT_KEYSTORE", "/opt/app/music/etc/truststore2018.jks"); - System.setProperty("AFT_DME2_CLIENT_KEYSTORE_PASSWORD", "changeit"); - System.setProperty("AFT_DME2_CLIENT_SSL_INCLUDE_PROTOCOLS", "TLSv1.1,TLSv1.2"); new MusicApplication().configure(new SpringApplicationBuilder(MusicApplication.class)).run(args); } @@ -210,4 +206,4 @@ public class MusicApplication extends SpringBootServletInitializer { public RequestContextListener requestContextListener() { return new RequestContextListener(); } -} \ No newline at end of file +} diff --git a/src/main/java/org/onap/music/authentication/AuthUtil.java b/src/main/java/org/onap/music/authentication/AuthUtil.java index 51e3dac0..de9c2729 100644 --- a/src/main/java/org/onap/music/authentication/AuthUtil.java +++ b/src/main/java/org/onap/music/authentication/AuthUtil.java @@ -88,7 +88,7 @@ public class AuthUtil { private static List filterNameSpacesAAFPermissions(String nameSpace, List allPermissionsList) { List list = new ArrayList<>(); - for (Iterator iterator = allPermissionsList.iterator(); iterator.hasNext();) { + for (Iterator iterator = allPermissionsList.iterator(); iterator.hasNext();) { AAFPermission aafPermission = (AAFPermission) iterator.next(); if(aafPermission.getType().indexOf(nameSpace) == 0) { list.add(aafPermission); @@ -152,15 +152,15 @@ public class AuthUtil { List aafPermsFinalList = filterNameSpacesAAFPermissions(nameSpace, aafPermsList); - logger.debug(EELFLoggerDelegate.applicationLogger, - "AuthUtil list of AAFPermission for the specific namespace ::::::::::::::::::::::::::::::::::::::::::::" + logger.debug(EELFLoggerDelegate.securityLogger, + "AuthUtil list of AAFPermission for the specific namespace :::" + aafPermsFinalList); HttpServletRequest httpRequest = (HttpServletRequest) request; String requestUri = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length() + 1); - logger.debug(EELFLoggerDelegate.applicationLogger, - "AuthUtil requestUri ::::::::::::::::::::::::::::::::::::::::::::" + requestUri); + logger.debug(EELFLoggerDelegate.securityLogger, + "AuthUtil requestUri :::" + requestUri); for (Iterator iterator = aafPermsFinalList.iterator(); iterator.hasNext();) { AAFPermission aafPermission = (AAFPermission) iterator.next(); @@ -169,7 +169,7 @@ public class AuthUtil { } } - logger.debug(EELFLoggerDelegate.applicationLogger, + logger.debug(EELFLoggerDelegate.securityLogger, "isAccessAllowed for the request uri: " + requestUri + "is :" + isauthorized); return isauthorized; } @@ -215,7 +215,7 @@ public class AuthUtil { String permKey = aafPermission.getKey(); - logger.info(EELFLoggerDelegate.applicationLogger, "isMatchPattern permKey: " + logger.debug(EELFLoggerDelegate.auditLogger, "isMatchPattern permKey: " + permKey + ", requestUri " + requestUri + " ," + method); String[] keyArray = permKey.split("\\|"); diff --git a/src/main/java/org/onap/music/authentication/CadiAuthFilter.java b/src/main/java/org/onap/music/authentication/CadiAuthFilter.java index 765face7..cd58d354 100644 --- a/src/main/java/org/onap/music/authentication/CadiAuthFilter.java +++ b/src/main/java/org/onap/music/authentication/CadiAuthFilter.java @@ -57,7 +57,7 @@ public class CadiAuthFilter extends CadiFilter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - logger.info(EELFLoggerDelegate.applicationLogger, "Request is entering cadifilter"); + logger.info(EELFLoggerDelegate.securityLogger, "Request is entering cadifilter"); long startTime = System.currentTimeMillis(); request.setAttribute("startTime", startTime); diff --git a/src/main/java/org/onap/music/authentication/MusicAuthorizationFilter.java b/src/main/java/org/onap/music/authentication/MusicAuthorizationFilter.java index b1db1083..a9930d88 100644 --- a/src/main/java/org/onap/music/authentication/MusicAuthorizationFilter.java +++ b/src/main/java/org/onap/music/authentication/MusicAuthorizationFilter.java @@ -40,9 +40,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.onap.music.eelf.logging.EELFLoggerDelegate; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.PropertySource; - +import org.onap.music.main.MusicUtil; import com.fasterxml.jackson.databind.ObjectMapper; /** @@ -51,11 +49,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; * @author sp931a * */ -@PropertySource(value = {"file:/opt/app/music/etc/music.properties"}) +//@PropertySource(value = {"file:/opt/app/music/etc/music.properties"}) public class MusicAuthorizationFilter implements Filter { - @Value("${music.aaf.ns}") - private String musicNS; + private String musicNS = MusicUtil.getMusicAafNs(); private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicAuthorizationFilter.class); @@ -70,21 +67,13 @@ public class MusicAuthorizationFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) - throws IOException, ServletException { - - logger.debug(EELFLoggerDelegate.applicationLogger, - "In MusicAuthorizationFilter doFilter start() ::::::::::::::::::::::::"); - + throws IOException, ServletException { HttpServletResponse httpResponse = null; boolean isAuthAllowed = false; if (null != servletRequest && null != servletResponse) { httpResponse = (HttpServletResponse) servletResponse; - - logger.debug(EELFLoggerDelegate.applicationLogger, - "Music NS defined in music property file --------------------------" + musicNS); - long startTime = 0; if( null != servletRequest.getAttribute("startTime")) { startTime = ((Long)servletRequest.getAttribute("startTime")).longValue(); @@ -95,19 +84,19 @@ public class MusicAuthorizationFilter implements Filter { try { isAuthAllowed = AuthUtil.isAccessAllowed(servletRequest, musicNS); } catch (Exception e) { - logger.error(EELFLoggerDelegate.applicationLogger, - "Error while checking authorization :::" + e.getMessage()); + logger.error(EELFLoggerDelegate.securityLogger, + "Error while checking authorization Music Namespace: " + musicNS + " : " + e.getMessage()); } long endTime = System.currentTimeMillis(); //startTime set in CadiAuthFilter doFilter - logger.debug(EELFLoggerDelegate.applicationLogger, - "Time took for authentication & authorization : " - + (endTime - startTime) + " milliseconds"); + logger.debug(EELFLoggerDelegate.securityLogger, + "Time took for authentication & authorization : " + + (endTime - startTime) + " milliseconds"); if (!isAuthAllowed) { - logger.debug(EELFLoggerDelegate.applicationLogger, + logger.info(EELFLoggerDelegate.securityLogger, "Unauthorized Access"); AuthorizationError authError = new AuthorizationError(); authError.setResponseCode(HttpServletResponse.SC_UNAUTHORIZED); @@ -124,8 +113,6 @@ public class MusicAuthorizationFilter implements Filter { filterChain.doFilter(servletRequest, servletResponse); } } - logger.debug(EELFLoggerDelegate.applicationLogger, - "In MusicAuthorizationFilter doFilter exit() ::::::::::::::::::::::::"); } private byte[] restResponseBytes(AuthorizationError eErrorResponse) throws IOException { diff --git a/src/main/java/org/onap/music/datastore/MusicDataStore.java b/src/main/java/org/onap/music/datastore/MusicDataStore.java index c771d80a..6195dbef 100755 --- a/src/main/java/org/onap/music/datastore/MusicDataStore.java +++ b/src/main/java/org/onap/music/datastore/MusicDataStore.java @@ -35,15 +35,14 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import org.apache.commons.jcs.access.CacheAccess; import org.onap.music.eelf.logging.EELFLoggerDelegate; import org.onap.music.eelf.logging.format.AppMessages; import org.onap.music.eelf.logging.format.ErrorSeverity; import org.onap.music.eelf.logging.format.ErrorTypes; import org.onap.music.exceptions.MusicQueryException; import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.main.CipherUtil; import org.onap.music.main.MusicUtil; -import com.codahale.metrics.JmxReporter; import com.datastax.driver.core.Cluster; import com.datastax.driver.core.ColumnDefinitions; import com.datastax.driver.core.ColumnDefinitions.Definition; @@ -53,7 +52,6 @@ import com.datastax.driver.core.HostDistance; import com.datastax.driver.core.KeyspaceMetadata; import com.datastax.driver.core.Metadata; import com.datastax.driver.core.PoolingOptions; -import com.datastax.driver.core.PreparedStatement; import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.Row; import com.datastax.driver.core.Session; @@ -62,7 +60,6 @@ import com.datastax.driver.core.TableMetadata; import com.datastax.driver.core.exceptions.AlreadyExistsException; import com.datastax.driver.core.exceptions.InvalidQueryException; import com.datastax.driver.core.exceptions.NoHostAvailableException; -import com.sun.jersey.core.util.Base64; /** * @author nelson24 @@ -177,10 +174,11 @@ public class MusicDataStore { while (it.hasNext()) { try { if(MusicUtil.getCassName() != null && MusicUtil.getCassPwd() != null) { + String cassPwd = CipherUtil.decryptPKC(MusicUtil.getCassPwd()); logger.info(EELFLoggerDelegate.applicationLogger, "Building with credentials "+MusicUtil.getCassName()+" & "+MusicUtil.getCassPwd()); cluster = Cluster.builder().withPort(MusicUtil.getCassandraPort()) - .withCredentials(MusicUtil.getCassName(), MusicUtil.getCassPwd()) + .withCredentials(MusicUtil.getCassName(), cassPwd) //.withLoadBalancingPolicy(new RoundRobinPolicy()) .withoutJMXReporting() .withPoolingOptions(poolingOptions) @@ -225,10 +223,11 @@ public class MusicDataStore { .setConnectionsPerHost(HostDistance.LOCAL, 4, 10) .setConnectionsPerHost(HostDistance.REMOTE, 2, 4); if(MusicUtil.getCassName() != null && MusicUtil.getCassPwd() != null) { + String cassPwd = CipherUtil.decryptPKC(MusicUtil.getCassPwd()); logger.info(EELFLoggerDelegate.applicationLogger, - "Building with credentials "+MusicUtil.getCassName()+" & "+MusicUtil.getCassPwd()); + "Building with credentials "+MusicUtil.getCassName()+" & "+ MusicUtil.getCassPwd()); cluster = Cluster.builder().withPort(MusicUtil.getCassandraPort()) - .withCredentials(MusicUtil.getCassName(), MusicUtil.getCassPwd()) + .withCredentials(MusicUtil.getCassName(), cassPwd) //.withLoadBalancingPolicy(new RoundRobinPolicy()) .withoutJMXReporting() .withPoolingOptions(poolingOptions) @@ -410,7 +409,7 @@ public class MusicDataStore { throw new MusicQueryException("Ill formed queryObject for the request = " + "[" + queryObject.getQuery() + "]"); } - logger.info(EELFLoggerDelegate.applicationLogger, + logger.debug(EELFLoggerDelegate.applicationLogger, "In preprared Execute Put: the actual insert query:" + queryObject.getQuery() + "; the values" + queryObject.getValues()); @@ -442,18 +441,19 @@ public class MusicDataStore { } catch (AlreadyExistsException ae) { - logger.error(EELFLoggerDelegate.errorLogger, ae.getMessage(),AppMessages.SESSIONFAILED+ " [" + - queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR, ae); - throw new MusicServiceException(ae.getMessage()); - } - catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.SESSIONFAILED + " [" - + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR, e); + // logger.error(EELFLoggerDelegate.errorLogger,"AlreadExistsException: " + ae.getMessage(),AppMessages.QUERYERROR, + // ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicQueryException("AlreadyExistsException: " + ae.getMessage(),ae); + } catch ( InvalidQueryException e ) { + // logger.error(EELFLoggerDelegate.errorLogger,"InvalidQueryException: " + e.getMessage(),AppMessages.SESSIONFAILED + " [" + // + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicQueryException("InvalidQueryException: " + e.getMessage(),e); + } catch (Exception e) { + // logger.error(EELFLoggerDelegate.errorLogger,e.getClass().toString() + ":" + e.getMessage(),AppMessages.SESSIONFAILED + " [" + // + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR, e); throw new MusicServiceException("Executing Session Failure for Request = " + "[" - + queryObject.getQuery() + "]" + " Reason = " + e.getMessage()); + + queryObject.getQuery() + "]" + " Reason = " + e.getMessage(),e); } - - return result; } @@ -556,9 +556,9 @@ public class MusicDataStore { results = session.execute(statement); } catch (Exception ex) { - logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(),AppMessages.UNKNOWNERROR+ "[" + queryObject + logger.error(EELFLoggerDelegate.errorLogger, "Execute Get Error" + ex.getMessage(),AppMessages.UNKNOWNERROR+ "[" + queryObject .getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR, ex); - throw new MusicServiceException(ex.getMessage()); + throw new MusicServiceException("Execute Get Error" + ex.getMessage()); } return results; diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java b/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java index 09cd65dc..d3ec10da 100644 --- a/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java +++ b/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java @@ -40,7 +40,7 @@ import org.onap.music.eelf.logging.format.AppMessages; import org.onap.music.eelf.logging.format.ErrorSeverity; import org.onap.music.eelf.logging.format.ErrorTypes; -@ApiModel(value = "JsonTable", description = "Json model for table vlaues insert") +@ApiModel(value = "InsertTable", description = "Json model for table vlaues insert") @JsonIgnoreProperties(ignoreUnknown = true) public class JsonInsert implements Serializable { private static final long serialVersionUID = 1L; @@ -54,7 +54,7 @@ public class JsonInsert implements Serializable { private Map objectMap; private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonInsert.class); - @ApiModelProperty(value = "objectMap") + @ApiModelProperty(value = "objectMap",hidden = true) public Map getObjectMap() { return objectMap; } @@ -90,7 +90,10 @@ public class JsonInsert implements Serializable { this.consistencyInfo = consistencyInfo; } - @ApiModelProperty(value = "Time to live information") + @ApiModelProperty(value = "Columns and tables support an optional " + + "expiration period called TTL (time-to-live) in seconds.", + notes="TTL precision is one second, which is calculated by the coordinator " + + "node. When using TTL, ensure that all nodes in the cluster have synchronized clocks.",allowEmptyValue = true) public String getTtl() { return ttl; } @@ -99,7 +102,10 @@ public class JsonInsert implements Serializable { this.ttl = ttl; } - @ApiModelProperty(value = "Time stamp") + @ApiModelProperty(value = "Time stamp (epoch_in_microseconds)", + notes = "Marks inserted data (write time) with TIMESTAMP. " + + "Enter the time since epoch (January 1, 1970) in microseconds." + + "By default, the actual time of write is used.", allowEmptyValue = true) public String getTimestamp() { return timestamp; } @@ -108,7 +114,9 @@ public class JsonInsert implements Serializable { this.timestamp = timestamp; } - @ApiModelProperty(value = "values returned") + @ApiModelProperty(value = "Json Object of key/values", notes="Where key is the column name and value is the data value for that column.", + example = "{'emp_id': 'df98a3d40cd6','emp_name': 'john'," + + "'emp_salary': 50,'address':{'street' : '1 Some way','city' : 'New York'}}") public Map getValues() { return values; } @@ -117,7 +125,7 @@ public class JsonInsert implements Serializable { this.values = values; } - @ApiModelProperty(value = "Information for selecting specific rows for insert") + @ApiModelProperty(value = "Information for selecting specific rows for insert",hidden = true) public Map getRowSpecification() { return rowSpecification; } diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/JsonLeasedLock.java b/src/main/java/org/onap/music/datastore/jsonobjects/JsonLeasedLock.java index edb30857..86bbe3dc 100644 --- a/src/main/java/org/onap/music/datastore/jsonobjects/JsonLeasedLock.java +++ b/src/main/java/org/onap/music/datastore/jsonobjects/JsonLeasedLock.java @@ -27,11 +27,10 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; -@ApiModel(value = "JsonTable", description = "model for leased lock") +@ApiModel(value = "Json Leasesd Lock", description = "model for leased lock") @JsonIgnoreProperties(ignoreUnknown = true) public class JsonLeasedLock { private long leasePeriod; - private String notifyUrl; @ApiModelProperty(value = "Lease period") public long getLeasePeriod() { @@ -42,12 +41,4 @@ public class JsonLeasedLock { this.leasePeriod = leasePeriod; } - @ApiModelProperty(value = "URL to be notified") - public String getNotifyUrl() { - return notifyUrl; - } - - public void setNotifyUrl(String notifyUrl) { - this.notifyUrl = notifyUrl; - } } diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/JsonLock.java b/src/main/java/org/onap/music/datastore/jsonobjects/JsonLock.java index 88e1c3f3..f353c018 100644 --- a/src/main/java/org/onap/music/datastore/jsonobjects/JsonLock.java +++ b/src/main/java/org/onap/music/datastore/jsonobjects/JsonLock.java @@ -29,12 +29,16 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; -@ApiModel(value = "JsonTable", description = "model for leased lock") +@ApiModel(value = "Json Lock Type", description = "Model for Lock Type") @JsonIgnoreProperties(ignoreUnknown = true) public class JsonLock { private LockType locktype; - @ApiModelProperty(value = "Type of music lock") + @ApiModelProperty( + value = "Type of music lock", + name = "lockType", + allowEmptyValue = false, + allowableValues = "READ|WRITE") public LockType getLocktype() { return this.locktype; } diff --git a/src/main/java/org/onap/music/eelf/healthcheck/MusicHealthCheck.java b/src/main/java/org/onap/music/eelf/healthcheck/MusicHealthCheck.java index df6cc265..cf4b2bc9 100644 --- a/src/main/java/org/onap/music/eelf/healthcheck/MusicHealthCheck.java +++ b/src/main/java/org/onap/music/eelf/healthcheck/MusicHealthCheck.java @@ -58,17 +58,20 @@ public class MusicHealthCheck { UUID randomUUID = UUID.randomUUID(); try { result = getAdminKeySpace(consistency, randomUUID); - } catch(Exception e) { + } catch( Exception e) { if(e.getMessage().toLowerCase().contains("unconfigured table healthcheck")) { logger.error("Error", e); logger.debug("Creating table...."); - boolean ksresult = createKeyspace(); - if(ksresult) - try { + try { + boolean ksresult = createKeyspace(); + if(ksresult) { result = getAdminKeySpace(consistency, randomUUID); - } catch (MusicServiceException e1) { - logger.error(EELFLoggerDelegate.errorLogger, e1, AppMessages.UNKNOWNERROR, ErrorSeverity.ERROR, ErrorTypes.UNKNOWN); } + } catch (MusicServiceException e1) { + logger.error(EELFLoggerDelegate.errorLogger, e1.getMessage(), AppMessages.UNKNOWNERROR, ErrorSeverity.ERROR, ErrorTypes.UNKNOWN); + } catch (MusicQueryException e1) { + logger.error(EELFLoggerDelegate.errorLogger, e1.getMessage(), AppMessages.UNKNOWNERROR, ErrorSeverity.ERROR, ErrorTypes.UNKNOWN,e1); + } } else { logger.error("Error", e); return "One or more nodes are down or not responding."; @@ -88,11 +91,12 @@ public class MusicHealthCheck { } } - private Boolean getAdminKeySpace(String consistency, UUID randomUUID) throws MusicServiceException { + private Boolean getAdminKeySpace(String consistency, UUID randomUUID) throws MusicServiceException,MusicQueryException { PreparedQueryObject pQuery = new PreparedQueryObject(); pQuery.appendQueryString("insert into admin.healthcheck (id) values (?)"); pQuery.addValue(randomUUID); - ResultType rs = MusicCore.nonKeyRelatedPut(pQuery, consistency); + ResultType rs = null; + rs = MusicCore.nonKeyRelatedPut(pQuery, consistency); logger.info(rs.toString()); return null != rs; @@ -109,15 +113,11 @@ public class MusicHealthCheck { - private boolean createKeyspace() { + private boolean createKeyspace() throws MusicServiceException,MusicQueryException { PreparedQueryObject pQuery = new PreparedQueryObject(); pQuery.appendQueryString("CREATE TABLE admin.healthcheck (id uuid PRIMARY KEY)"); ResultType rs = null ; - try { - rs = MusicCore.nonKeyRelatedPut(pQuery, ConsistencyLevel.ONE.toString()); - } catch (MusicServiceException e) { - logger.error(EELFLoggerDelegate.errorLogger, e, AppMessages.UNKNOWNERROR, ErrorSeverity.ERROR, ErrorTypes.UNKNOWN); - } + rs = MusicCore.nonKeyRelatedPut(pQuery, ConsistencyLevel.ONE.toString()); return rs != null && rs.getResult().toLowerCase().contains("success"); } diff --git a/src/main/java/org/onap/music/eelf/logging/EELFLoggerDelegate.java b/src/main/java/org/onap/music/eelf/logging/EELFLoggerDelegate.java index 64960b1e..a8012c82 100644 --- a/src/main/java/org/onap/music/eelf/logging/EELFLoggerDelegate.java +++ b/src/main/java/org/onap/music/eelf/logging/EELFLoggerDelegate.java @@ -44,6 +44,7 @@ public class EELFLoggerDelegate extends SLF4jWrapper implements EELFLogger { public static final EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger(); public static final EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger(); public static final EELFLogger debugLogger = EELFManager.getInstance().getDebugLogger(); + public static final EELFLogger securityLogger = EELFManager.getInstance().getSecurityLogger(); private String className; private static ConcurrentMap classMap = new ConcurrentHashMap<>(); @@ -230,9 +231,7 @@ public class EELFLoggerDelegate extends SLF4jWrapper implements EELFLogger { * @param logger * @param msg * - * @deprecated use {@link #error(EELF, Exception)} instead */ - @Deprecated public void error(EELFLogger logger, String msg) { logger.error(className+ " - " + msg); } @@ -254,9 +253,7 @@ public class EELFLoggerDelegate extends SLF4jWrapper implements EELFLogger { * @param msg * @param arguments * - * @deprecated use {@link #error(EELF, Exception, Object...)} instead */ - @Deprecated public void error(EELFLogger logger, String msg, Object... arguments) { logger.error(msg, arguments); } @@ -289,9 +286,7 @@ public class EELFLoggerDelegate extends SLF4jWrapper implements EELFLogger { * @param logger * @param msg * @param severtiy - * @deprecated use {@link #error(EELF, Exception)} instead */ - @Deprecated public void error(EELFLogger logger, String msg, Object /* AlarmSeverityEnum */ severtiy) { logger.error(msg); } @@ -309,6 +304,8 @@ public class EELFLoggerDelegate extends SLF4jWrapper implements EELFLogger { debug(debugLogger, msg); info(auditLogger, msg); info(metricsLogger, msg); + info(securityLogger, msg); + } /** diff --git a/src/main/java/org/onap/music/eelf/logging/MusicContainerFilter.java b/src/main/java/org/onap/music/eelf/logging/MusicContainerFilter.java index 23f29595..bac02afa 100644 --- a/src/main/java/org/onap/music/eelf/logging/MusicContainerFilter.java +++ b/src/main/java/org/onap/music/eelf/logging/MusicContainerFilter.java @@ -39,32 +39,30 @@ import org.springframework.stereotype.Component; @Component public class MusicContainerFilter implements ContainerResponseFilter { - private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicContainerFilter.class); - - public MusicContainerFilter() { - - } - - @Override - public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) - throws IOException { - logger.info(EELFLoggerDelegate.applicationLogger, "In MusicContainerFilter response filter ::::::::::::::::::::::::"); - - if (null != EELFLoggerDelegate.mdcGet("transactionId")) { - EELFLoggerDelegate.mdcRemove("transactionId"); - } - - if (null != EELFLoggerDelegate.mdcGet("conversationId")) { - EELFLoggerDelegate.mdcRemove("conversationId"); - } - - if (null != EELFLoggerDelegate.mdcGet("clientId")) { - EELFLoggerDelegate.mdcRemove("clientId"); - } - - if (null != EELFLoggerDelegate.mdcGet("messageId")) { - EELFLoggerDelegate.mdcRemove("messageId"); - } - } - + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicContainerFilter.class); + + public MusicContainerFilter() { + + } + + @Override + public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) + throws IOException { + if (null != EELFLoggerDelegate.mdcGet("transactionId")) { + EELFLoggerDelegate.mdcRemove("transactionId"); + } + + if (null != EELFLoggerDelegate.mdcGet("conversationId")) { + EELFLoggerDelegate.mdcRemove("conversationId"); + } + + if (null != EELFLoggerDelegate.mdcGet("clientId")) { + EELFLoggerDelegate.mdcRemove("clientId"); + } + + if (null != EELFLoggerDelegate.mdcGet("messageId")) { + EELFLoggerDelegate.mdcRemove("messageId"); + } + } + } diff --git a/src/main/java/org/onap/music/eelf/logging/MusicLoggingServletFilter.java b/src/main/java/org/onap/music/eelf/logging/MusicLoggingServletFilter.java index cb688c54..7eca73e1 100644 --- a/src/main/java/org/onap/music/eelf/logging/MusicLoggingServletFilter.java +++ b/src/main/java/org/onap/music/eelf/logging/MusicLoggingServletFilter.java @@ -85,8 +85,8 @@ public class MusicLoggingServletFilter implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - logger.info(EELFLoggerDelegate.applicationLogger, - "In MusicLogginServletFilter doFilter start() ::::::::::::::::::::::: [\"+MusicUtil.getTransIdRequired()+\",\"+MusicUtil.getConversationIdRequired()+\",\"+MusicUtil.getClientIdRequired()+\",\"+MusicUtil.getMessageIdRequired()"); + logger.info(EELFLoggerDelegate.securityLogger, + "In MusicLogginServletFilter doFilter start() :: [\"+MusicUtil.getTransIdRequired()+\",\"+MusicUtil.getConversationIdRequired()+\",\"+MusicUtil.getClientIdRequired()+\",\"+MusicUtil.getMessageIdRequired()"); HttpServletRequest httpRequest = null; HttpServletResponse httpResponse = null; @@ -149,7 +149,7 @@ public class MusicLoggingServletFilter implements Filter { } - logger.info(EELFLoggerDelegate.applicationLogger, + logger.info(EELFLoggerDelegate.securityLogger, "In MusicLogginServletFilter doFilter. Header values validated sucessfully"); chain.doFilter(request, response); diff --git a/src/main/java/org/onap/music/lockingservice/cassandra/CassaLockStore.java b/src/main/java/org/onap/music/lockingservice/cassandra/CassaLockStore.java index 3c3f7160..06a087ab 100644 --- a/src/main/java/org/onap/music/lockingservice/cassandra/CassaLockStore.java +++ b/src/main/java/org/onap/music/lockingservice/cassandra/CassaLockStore.java @@ -274,7 +274,7 @@ public class CassaLockStore { String lockReference = "" + row.getLong("lockReference"); String createTime = row.getString("createTime"); String acquireTime = row.getString("acquireTime"); - LockType locktype = row.getBool("writeLock") ? LockType.WRITE : LockType.READ; + LockType locktype = row.isNull("writeLock") || row.getBool("writeLock") ? LockType.WRITE : LockType.READ; return new LockObject(true, lockReference, createTime, acquireTime, locktype); } @@ -283,29 +283,37 @@ public class CassaLockStore { throws MusicServiceException, MusicQueryException { logger.info(EELFLoggerDelegate.applicationLogger, "Getting lockholders in lock table for " + keyspace + "." + table + "." + key); + String origTable = table; table = table_prepend_name + table; String selectQuery = "select * from " + keyspace + "." + table + " where key=?;"; + List lockHolders = new ArrayList<>(); PreparedQueryObject queryObject = new PreparedQueryObject(); queryObject.appendQueryString(selectQuery); queryObject.addValue(key); ResultSet rs = dsHandle.executeOneConsistencyGet(queryObject); - - List lockHolders = new ArrayList<>(); boolean topOfQueue = true; + StringBuilder lock = new StringBuilder(). + append("$").append(keyspace).append(".").append(origTable). + append(".").append(key).append("$"); + StringBuilder lockReference = new StringBuilder(); for (Row row : rs) { - String lockReference = "" + row.getLong("lockReference"); - if (row.getBool("writeLock")) { + if ( row.isNull("lockReference") ) { + return lockHolders; + } + lockReference.append(lock).append(row.getLong("lockReference")); + if (row.isNull("writeLock") || row.getBool("writeLock")) { if (topOfQueue) { - lockHolders.add(lockReference); + lockHolders.add(lockReference.toString()); break; } else { break; } } // read lock - lockHolders.add(lockReference); + lockHolders.add(lockReference.toString()); topOfQueue = false; + lockReference.delete(0,lockReference.length()); } return lockHolders; } @@ -335,16 +343,16 @@ public class CassaLockStore { boolean topOfQueue = true; for (Row row : rs) { - String lockReference = "" + row.getLong("lockReference"); - if (row.getBool("writeLock")) { + String lockReference = "" + row.getLong("lockReference"); + if (row.isNull("writeLock") || row.getBool("writeLock")) { if (topOfQueue && lockRef.equals(lockReference)) { - return true; + return true; } else { - return false; + return false; } } if (lockRef.equals(lockReference)) { - return true; + return true; } topOfQueue = false; } @@ -384,7 +392,7 @@ public class CassaLockStore { String lockReference = "" + row.getLong("lockReference"); String createTime = row.getString("createTime"); String acquireTime = row.getString("acquireTime"); - LockType locktype = row.getBool("writeLock") ? LockType.WRITE : LockType.READ; + LockType locktype = row.isNull("writeLock") || row.getBool("writeLock") ? LockType.WRITE : LockType.READ; boolean isLockOwner = isLockOwner(keyspace, table, key, lockRef); return new LockObject(isLockOwner, lockReference, createTime, acquireTime, locktype); @@ -441,8 +449,9 @@ public class CassaLockStore { String updateQuery = "update " + keyspace + "." + table + " set acquireTime='" + System.currentTimeMillis() + "' where key='" + key + "' AND lockReference = " + lockReferenceL + " IF EXISTS;"; queryObject.appendQueryString(updateQuery); - dsHandle.executePut(queryObject, "eventual"); + //cannot use executePut because we need to ignore music timestamp adjustments for lock store + dsHandle.getSession().execute(updateQuery); } } diff --git a/src/main/java/org/onap/music/main/CipherUtil.java b/src/main/java/org/onap/music/main/CipherUtil.java new file mode 100644 index 00000000..0d5b7710 --- /dev/null +++ b/src/main/java/org/onap/music/main/CipherUtil.java @@ -0,0 +1,270 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.main; + +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.UnsupportedEncodingException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Scanner; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.lang3.ArrayUtils; +import org.onap.music.eelf.logging.EELFLoggerDelegate; + +public class CipherUtil { + + + /** + * Default key. + */ + private static String keyString = MusicUtil.getCipherEncKey(); + + private static final String ALGORITHM = "AES"; + private static final String ALGORYTHM_DETAILS = ALGORITHM + "/CBC/PKCS5PADDING"; + private static final int BLOCK_SIZE = 128; + @SuppressWarnings("unused") + private static SecretKeySpec secretKeySpec; + private static IvParameterSpec ivspec; + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(CipherUtil.class); + /** + * @deprecated Please use {@link #encryptPKC(String)} to encrypt the text. + * + * Encrypts the text using the specified secret key. + * + * @param plainText + * Text to encrypt + * @param secretKey + * Key to use for encryption + * @return encrypted version of plain text. + * @ + * if any encryption step fails + * + */ + @Deprecated + public static String encrypt(String plainText, String secretKey) { + String encryptedString = null; + try { + byte[] encryptText = plainText.getBytes("UTF-8"); + byte[] rawKey = Base64.decodeBase64(secretKey); + SecretKeySpec sKeySpec = new SecretKeySpec(rawKey, "AES"); + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.ENCRYPT_MODE, sKeySpec); + encryptedString = Base64.encodeBase64String(cipher.doFinal(encryptText)); + } catch (BadPaddingException | IllegalBlockSizeException | InvalidKeyException | NoSuchAlgorithmException + | NoSuchPaddingException | UnsupportedEncodingException ex) { + } + return encryptedString; + } + + /** + * @deprecated Please use {@link #encryptPKC(String)} to encrypt the text. + * Encrypts the text using the secret key in key.properties file. + * + * @param plainText + * Text to encrypt + * @return Encrypted Text + * @ + * if any decryption step fails + */ + @Deprecated + public static String encrypt(String plainText) { + return CipherUtil.encrypt(plainText, keyString); + } + + /** + * Encrypts the text using a secret key. + * + * @param plainText + * Text to encrypt + * @return Encrypted Text + * @ + * if any decryption step fails + */ + public static String encryptPKC(String plainText) { + return CipherUtil.encryptPKC(plainText, keyString); + } + + /** + * + * @deprecated Please use {@link #decryptPKC(String)} to Decryption the text. + * + * Decrypts the text using the specified secret key. + * + * @param encryptedText + * Text to decrypt + * @param secretKey + * Key to use for decryption + * @return plain text version of encrypted text + * @ + * if any decryption step fails + * + */ + @Deprecated + public static String decrypt(String encryptedText, String secretKey) { + String encryptedString = null; + try { + byte[] rawKey = Base64.decodeBase64(secretKey); + SecretKeySpec sKeySpec = new SecretKeySpec(rawKey, "AES"); + byte[] encryptText = Base64.decodeBase64(encryptedText.getBytes("UTF-8")); + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.DECRYPT_MODE, sKeySpec); + encryptedString = new String(cipher.doFinal(encryptText)); + } catch (BadPaddingException | IllegalBlockSizeException | InvalidKeyException | NoSuchAlgorithmException + | NoSuchPaddingException | UnsupportedEncodingException ex) { + } + return encryptedString; + } + + private static SecretKeySpec getSecretKeySpec() { + byte[] key = Base64.decodeBase64(keyString); + return new SecretKeySpec(key, ALGORITHM); + } + + private static SecretKeySpec getSecretKeySpec(String keyString) { + byte[] key = Base64.decodeBase64(keyString); + return new SecretKeySpec(key, ALGORITHM); + } + + /** + * Encrypt the text using the secret key in key.properties file + * + * @param value + * @return The encrypted string + * @throws BadPaddingException + * @ + * In case of issue with the encryption + */ + public static String encryptPKC(String value, String skey) { + Cipher cipher = null; + byte[] iv = null, finalByte = null; + + try { + cipher = Cipher.getInstance(ALGORYTHM_DETAILS, "SunJCE"); + + SecureRandom r = SecureRandom.getInstance("SHA1PRNG"); + iv = new byte[BLOCK_SIZE / 8]; + r.nextBytes(iv); + ivspec = new IvParameterSpec(iv); + cipher.init(Cipher.ENCRYPT_MODE, getSecretKeySpec(skey), ivspec); + finalByte = cipher.doFinal(value.getBytes()); + + } catch (Exception ex) { + + } + return Base64.encodeBase64String(ArrayUtils.addAll(iv, finalByte)); + } + + /** + * Decrypts the text using the secret key in key.properties file. + * + * @param message + * The encrypted string that must be decrypted using the ecomp + * Encryption Key + * @return The String decrypted + * @ + * if any decryption step fails + */ + public static String decryptPKC(String message, String skey) { + byte[] encryptedMessage = Base64.decodeBase64(message); + Cipher cipher; + byte[] decrypted = null; + try { + cipher = Cipher.getInstance(ALGORYTHM_DETAILS, "SunJCE"); + ivspec = new IvParameterSpec(ArrayUtils.subarray(encryptedMessage, 0, BLOCK_SIZE / 8)); + byte[] realData = ArrayUtils.subarray(encryptedMessage, BLOCK_SIZE / 8, encryptedMessage.length); + cipher.init(Cipher.DECRYPT_MODE, getSecretKeySpec(skey), ivspec); + decrypted = cipher.doFinal(realData); + + } catch (Exception ex) { + + + } + + return new String(decrypted); + } + + /** + * @deprecated Please use {@link #decryptPKC(String)} to Decrypt the text. + * + * Decrypts the text using the secret key in key.properties file. + * + * @param encryptedText + * Text to decrypt + * @return Decrypted text + * @ + * if any decryption step fails + */ + @Deprecated + public static String decrypt(String encryptedText) { + return CipherUtil.decrypt(encryptedText, keyString); + } + + /** + * + * Decrypts the text using the secret key in key.properties file. + * + * @param encryptedText + * Text to decrypt + * @return Decrypted text + * @ + * if any decryption step fails + */ + public static String decryptPKC(String encryptedText) { + return CipherUtil.decryptPKC(encryptedText, keyString); + } + + + public static void readAndSetKeyString() { + try { + Scanner in = new Scanner(new FileReader("/opt/app/music/etc/properties.txt")); + StringBuilder sb = new StringBuilder(); + while(in.hasNext()) { + sb.append(in.next()); + } + in.close(); + keyString = sb.toString(); + } catch (FileNotFoundException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + } + } + + /*public static void main(String[] args) { + + System.out.println("Encrypted password: "+encryptPKC("cassandra")); + + System.out.println("Decrypted password: "+decryptPKC("dDhqAp5/RwZbl9yRSZg15fN7Qul9eiE/JFkKemtTib0=")); + System.out.println("Decrypted password: "+decryptPKC("I/dOtD/YYzBStbtOYhKuUUyPHSW2G9ZzdSyB8bJp4vk=")); + System.out.println("Decrypted password: "+decryptPKC("g7zJqg74dLsH/fyL7I75b4eySy3pbMS2xVqkrB5lDl8=")); + }*/ + +} diff --git a/src/main/java/org/onap/music/main/MusicCore.java b/src/main/java/org/onap/music/main/MusicCore.java index 324f4681..6a0d2471 100644 --- a/src/main/java/org/onap/music/main/MusicCore.java +++ b/src/main/java/org/onap/music/main/MusicCore.java @@ -122,7 +122,7 @@ public class MusicCore { } public static ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) - throws MusicServiceException { + throws MusicServiceException,MusicQueryException { return musicCore.nonKeyRelatedPut(queryObject, consistency); } diff --git a/src/main/java/org/onap/music/main/MusicDigest.java b/src/main/java/org/onap/music/main/MusicDigest.java deleted file mode 100644 index d05969e3..00000000 --- a/src/main/java/org/onap/music/main/MusicDigest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * ============LICENSE_START========================================== - * org.onap.music - * =================================================================== - * Copyright (c) 2017 AT&T Intellectual Property - * =================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ============LICENSE_END============================================= - * ==================================================================== - */ - -package org.onap.music.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/src/main/java/org/onap/music/main/MusicUtil.java b/src/main/java/org/onap/music/main/MusicUtil.java index 9ffa2503..21e5c255 100755 --- a/src/main/java/org/onap/music/main/MusicUtil.java +++ b/src/main/java/org/onap/music/main/MusicUtil.java @@ -31,20 +31,13 @@ import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.Row; import java.io.File; import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; import java.math.BigInteger; import java.nio.ByteBuffer; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.Scanner; -import java.util.StringTokenizer; import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.ResponseBuilder; @@ -61,7 +54,6 @@ import org.onap.music.service.impl.MusicCassaCore; import com.datastax.driver.core.ConsistencyLevel; import com.datastax.driver.core.DataType; -import com.sun.jersey.core.util.Base64; /** * @author nelson24 @@ -103,30 +95,27 @@ public class MusicUtil { private static final String PROPERTIES_FILE = "/opt/app/music/etc/music.properties"; public static final String DEFAULTKEYSPACENAME = "TBD"; - private static String myCassaHost = LOCALHOST; - private static String defaultMusicIp = LOCALHOST; - private static int cassandraPort = 9042; - private static int notifytimeout = 30000; - private static int notifyinterval = 5000; private static long defaultLockLeasePeriod = 6000; + // Amount of times to retry to delete a lock in atomic. private static int retryCount = 3; - private static int cacheObjectMaxLife = -1; private static String lockUsing = MusicUtil.CASSANDRA; + // Cadi OnOff private static boolean isCadi = false; + // Keyspace Creation on/off private static boolean isKeyspaceActive = false; private static boolean debug = true; private static String version = "0.0.0"; private static String build = ""; private static String musicPropertiesFilePath = PROPERTIES_FILE; - private static final String[] propKeys = new String[] { "cassandra.host", "music.ip", "debug", - "version", "music.rest.ip", "music.properties", "lock.lease.period", "id", "all.ids", - "public.ip","all.pubic.ips", "cassandra.user", "cassandra.password", "aaf.endpoint.url", - "admin.username","admin.password","aaf.admin.url","music.namespace","admin.aaf.role", - "cassandra.port","lock.using","retry.count","transId.header.required", - "conversation.header.required","clientId.header.required","messageId.header.required", - "transId.header.prefix","conversation.header.prefix","clientId.header.prefix", - "messageId.header.prefix"}; + // private static final String[] propKeys = new String[] { MusicUtil.class.getDeclaredMethod(arg0, )"build","cassandra.host", "debug", + // "version", "music.properties", "lock.lease.period", "cassandra.user", + // "cassandra.password", "aaf.endpoint.url","admin.username","admin.password", + // "music.namespace","admin.aaf.role","cassandra.port","lock.using","retry.count", + // "transId.header.required","conversation.header.required","clientId.header.required", + // "messageId.header.required","transId.header.prefix","conversation.header.prefix", + // "clientId.header.prefix","messageId.header.prefix"}; + // Consistency Constants and variables. private static final String[] cosistencyLevel = new String[] { "ALL","EACH_QUORUM","QUORUM","LOCAL_QUORUM","ONE","TWO", "THREE","LOCAL_ONE","ANY","SERIAL","LOCAL_SERIAL"}; @@ -143,87 +132,42 @@ public class MusicUtil { consistencyName.put("LOCAL_ONE",ConsistencyLevel.LOCAL_ONE); consistencyName.put("LOCAL_SERIAL",ConsistencyLevel.LOCAL_SERIAL); } + + // Cassandra Values private static String cassName = "cassandra"; private static String cassPwd; - private static String aafEndpointUrl = null; - private static String adminId = "username"; - private static String adminPass= "password"; - private static String aafAdminUrl= null; - private static String musicNamespace= "org.onap.music.api"; - private static String adminAafRole= "org.onap.music.api.admin_api"; + private static String myCassaHost = LOCALHOST; + private static int cassandraPort = 9042; + + // AAF + private static String musicAafNs = "org.onap.music.cadi"; + // Locking public static final long MusicEternityEpochMillis = 1533081600000L; // Wednesday, August 1, 2018 12:00:00 AM public static final long MaxLockReferenceTimePart = 1000000000000L; // millis after eternity (eq sometime in 2050) public static final long MaxCriticalSectionDurationMillis = 1L * 24 * 60 * 60 * 1000; // 1 day - private static String transIdPrefix= "false"; - private static String conversationIdPrefix= "false"; - private static String clientIdPrefix= "false"; - private static String messageIdPrefix= "false"; - private static String transIdRequired= "false"; - private static String conversationIdRequired= "false"; - private static String clientIdRequired= "false"; - private static String messageIdRequired= "false"; + // Response/Request tracking headers + private static String transIdPrefix = "false"; + private static String conversationIdPrefix = "false"; + private static String clientIdPrefix = "false"; + private static String messageIdPrefix = "false"; + private static Boolean transIdRequired = false; + private static Boolean conversationIdRequired = false; + private static Boolean clientIdRequired = false; + private static Boolean messageIdRequired = false; + private static String cipherEncKey = ""; + public static String getLockUsing() { return lockUsing; } - public static void setLockUsing(String lockUsing) { MusicUtil.lockUsing = lockUsing; } - - public static String getAafAdminUrl() { - return aafAdminUrl; - } - - - public static void setAafAdminUrl(String aafAdminUrl) { - MusicUtil.aafAdminUrl = aafAdminUrl; - } - - - public static String getMusicNamespace() { - return musicNamespace; - } - - - public static void setMusicNamespace(String musicNamespace) { - MusicUtil.musicNamespace = musicNamespace; - } - - - public static String getAdminAafRole() { - return adminAafRole; - } - - - public static void setAdminAafRole(String adminAafRole) { - MusicUtil.adminAafRole = adminAafRole; - } - - - - public static String getAdminId() { - return adminId; - } - - public static void setAdminId(String adminId) { - MusicUtil.adminId = adminId; - } - - - public static String getAdminPass() { - return adminPass; - } - - public static void setAdminPass(String adminPass) { - MusicUtil.adminPass = adminPass; - } - - private MusicUtil() { + public MusicUtil() { throw new IllegalStateException("Utility Class"); } /** @@ -255,31 +199,15 @@ public class MusicUtil { return cassPwd; } - /** - * @return the aafEndpointUrl - */ - public static String getAafEndpointUrl() { - return aafEndpointUrl; - } - - /** - * - * @param aafEndpointUrl - */ - public static void setAafEndpointUrl(String aafEndpointUrl) { - MusicUtil.aafEndpointUrl = aafEndpointUrl; - } - - /** * Returns An array of property names that should be in the Properties * files. * - * @return - */ - public static String[] getPropkeys() { - return propKeys.clone(); - } +// * @return +// */ +// public static String[] getPropkeys() { +// return propKeys.clone(); +// } /** * Get MusicPropertiesFilePath - Default = /opt/music/music.properties @@ -390,24 +318,6 @@ public class MusicUtil { public static void setMyCassaHost(String myCassaHost) { MusicUtil.myCassaHost = myCassaHost; } - - /** - * Get DefaultMusicIp - Default = localhost property file value - music.ip - * - * @return - */ - public static String getDefaultMusicIp() { - return defaultMusicIp; - } - - /** - * Set DefaultMusicIp - * - * @param defaultMusicIp . - */ - public static void setDefaultMusicIp(String defaultMusicIp) { - MusicUtil.defaultMusicIp = defaultMusicIp; - } /** * Gey default retry count @@ -443,9 +353,11 @@ public class MusicUtil { } /** - * . + * This method depricated as its not used or needed. + * * @return String */ + @Deprecated public static String getTestType() { String testType = ""; try { @@ -462,7 +374,9 @@ public class MusicUtil { } /** - * + * Method to do a Thread Sleep. + * Used for adding a delay. + * * @param time */ public static void sleep(long time) { @@ -638,7 +552,7 @@ public class MusicUtil { response.header(XPATCHVERSION,verArray[2]); } response.header(XLATESTVERSION,version); - logger.info(EELFLoggerDelegate.applicationLogger,"Version In:" + versionIn); + logger.info(EELFLoggerDelegate.auditLogger,"Version In:" + versionIn); return response; } @@ -655,29 +569,6 @@ public class MusicUtil { return consistencyName.get(consistency.toUpperCase()); } - public static void setNotifyInterval(int notifyinterval) { - MusicUtil.notifyinterval = notifyinterval; - } - public static void setNotifyTimeOut(int notifytimeout) { - MusicUtil.notifytimeout = notifytimeout; - } - - public static int getNotifyInterval() { - return MusicUtil.notifyinterval; - } - - public static int getNotifyTimeout() { - return MusicUtil.notifytimeout; - } - - public static int getCacheObjectMaxLife() { - return MusicUtil.cacheObjectMaxLife; - } - - public static void setCacheObjectMaxLife(int cacheObjectMaxLife) { - MusicUtil.cacheObjectMaxLife = cacheObjectMaxLife; - } - /** * Given the time of write for an update in a critical section, this method provides a transformed timestamp * that ensures that a previous lock holder who is still alive can never corrupt a later critical section. @@ -839,67 +730,89 @@ public class MusicUtil { } /** - * @return the transIdRequired - */ - public static String getTransIdRequired() { - return transIdRequired; - } - - - /** - * @param transIdRequired the transIdRequired to set - */ - public static void setTransIdRequired(String transIdRequired) { - MusicUtil.transIdRequired = transIdRequired; - } - - - /** - * @return the conversationIdRequired - */ - public static String getConversationIdRequired() { - return conversationIdRequired; - } - - - /** - * @param conversationIdRequired the conversationIdRequired to set - */ - public static void setConversationIdRequired(String conversationIdRequired) { - MusicUtil.conversationIdRequired = conversationIdRequired; - } - - - /** - * @return the clientIdRequired - */ - public static String getClientIdRequired() { - return clientIdRequired; - } - - - /** - * @param clientIdRequired the clientIdRequired to set - */ - public static void setClientIdRequired(String clientIdRequired) { - MusicUtil.clientIdRequired = clientIdRequired; - } - - - /** - * @return the messageIdRequired - */ - public static String getMessageIdRequired() { - return messageIdRequired; - } - - - /** - * @param messageIdRequired the messageIdRequired to set - */ - public static void setMessageIdRequired(String messageIdRequired) { - MusicUtil.messageIdRequired = messageIdRequired; - } + * @return the transIdRequired + */ + public static Boolean getTransIdRequired() { + return transIdRequired; + } + + + /** + * @param transIdRequired the transIdRequired to set + */ + public static void setTransIdRequired(Boolean transIdRequired) { + MusicUtil.transIdRequired = transIdRequired; + } + + + /** + * @return the conversationIdRequired + */ + public static Boolean getConversationIdRequired() { + return conversationIdRequired; + } + + + /** + * @param conversationIdRequired the conversationIdRequired to set + */ + public static void setConversationIdRequired(Boolean conversationIdRequired) { + MusicUtil.conversationIdRequired = conversationIdRequired; + } + + + /** + * @return the clientIdRequired + */ + public static Boolean getClientIdRequired() { + return clientIdRequired; + } + + + /** + * @param clientIdRequired the clientIdRequired to set + */ + public static void setClientIdRequired(Boolean clientIdRequired) { + MusicUtil.clientIdRequired = clientIdRequired; + } + + + /** + * @return the messageIdRequired + */ + public static Boolean getMessageIdRequired() { + return messageIdRequired; + } + + /** + * @param messageIdRequired the messageIdRequired to set + */ + public static void setMessageIdRequired(Boolean messageIdRequired) { + MusicUtil.messageIdRequired = messageIdRequired; + } + + + public static String getCipherEncKey() { + return MusicUtil.cipherEncKey; + } + + + public static void setCipherEncKey(String cipherEncKey) { + MusicUtil.cipherEncKey = cipherEncKey; + if ( null == cipherEncKey || cipherEncKey.equals("") || + cipherEncKey.equals("nothing to see here")) { + logger.error(EELFLoggerDelegate.errorLogger, "Missing Cipher Encryption Key."); + } + } + + public static String getMusicAafNs() { + return MusicUtil.musicAafNs; + } + + + public static void setMusicAafNs(String musicAafNs) { + MusicUtil.musicAafNs = musicAafNs; + } diff --git a/src/main/java/org/onap/music/main/PropertiesLoader.java b/src/main/java/org/onap/music/main/PropertiesLoader.java index c20ce5c5..f99650ae 100644 --- a/src/main/java/org/onap/music/main/PropertiesLoader.java +++ b/src/main/java/org/onap/music/main/PropertiesLoader.java @@ -22,9 +22,6 @@ package org.onap.music.main; -import java.util.ArrayList; -import java.util.Arrays; - import org.onap.music.eelf.logging.EELFLoggerDelegate; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Value; @@ -33,7 +30,7 @@ import org.springframework.context.annotation.PropertySource; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.stereotype.Component; -@PropertySource(value = {"file:/opt/app/music/etc/music.properties", "classpath:/project.properties"}) +@PropertySource(value = {"file:/opt/app/music/etc/music.properties", "classpath:/project.properties","file:/opt/app/music/etc/key.properties"}) @Component public class PropertiesLoader implements InitializingBean { @@ -64,33 +61,9 @@ public class PropertiesLoader implements InitializingBean { @Value("${cassandra.password}") public String cassandraPassword; - @Value("${aaf.endpoint.url}") - public String aafEndpointUrl; - - @Value("${admin.username}") - public String adminUsername; - - @Value("${admin.password}") - public String adminPassword; - @Value("${cassandra.port}") public String cassandraPort; - @Value("${aaf.admin.url}") - public String aafAdminUrl; - - @Value("${music.namespace}") - public String musicNamespace; - - @Value("${admin.aaf.role}") - public String adminAafRole; - - @Value("${notify.interval}") - public String notifyInterval; - - @Value("${notify.timeout}") - public String notifyTimeout; - @Value("${cadi}") public String isCadi; @@ -113,16 +86,22 @@ public class PropertiesLoader implements InitializingBean { private String messageIdPrefix; @Value("${transId.header.required}") - private String transIdRequired; + private Boolean transIdRequired; @Value("${conversation.header.required}") - private String conversationIdRequired; + private Boolean conversationIdRequired; @Value("${clientId.header.required}") - private String clientIdRequired; + private Boolean clientIdRequired; @Value("${messageId.header.required}") - private String messageIdRequired; + private Boolean messageIdRequired; + + @Value("${music.aaf.ns}") + private String musicAafNs; + + @Value("${cipher.enc.key}") + private String cipherEncKey; private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(PropertiesLoader.class); @@ -139,20 +118,11 @@ public class PropertiesLoader implements InitializingBean { * . */ public void loadProperties() { - if (aafAdminUrl != null && !aafAdminUrl.equals("${aaf.admin.url}")) { - MusicUtil.setAafAdminUrl(aafAdminUrl); + if(cipherEncKey != null) { + MusicUtil.setCipherEncKey(cipherEncKey); } - if (aafEndpointUrl != null && !aafEndpointUrl.equals("${aaf.endpoint.url}")) { - MusicUtil.setAafEndpointUrl(aafEndpointUrl); - } - if (adminAafRole != null && !adminAafRole.equals("${admin.aaf.role}")) { - MusicUtil.setAdminAafRole(adminAafRole); - } - if (adminPassword != null && !adminPassword.equals("${admin.password}")) { - MusicUtil.setAdminPass(adminPassword); - } - if (adminUsername != null && !adminUsername.equals("${admin.username}")) { - MusicUtil.setAdminId(adminUsername); + if (musicAafNs != null) { + MusicUtil.setMusicAafNs(musicAafNs); } if (cassandraPort != null && !cassandraPort.equals("${cassandra.port}")) { MusicUtil.setCassandraPort(Integer.parseInt(cassandraPort)); @@ -169,24 +139,12 @@ public class PropertiesLoader implements InitializingBean { if (lockLeasePeriod != null && !lockLeasePeriod.equals("${lock.lease.period}")) { MusicUtil.setDefaultLockLeasePeriod(Long.parseLong(lockLeasePeriod)); } - if (musicIp != null && !musicIp.equals("${music.ip}")) { - MusicUtil.setDefaultMusicIp(musicIp); - } - if (musicNamespace != null && !musicNamespace.equals("${music.namespace}")) { - MusicUtil.setMusicNamespace(musicNamespace); - } if (musicProperties != null && !musicProperties.equals("${music.properties}")) { MusicUtil.setMusicPropertiesFilePath(musicProperties); } if (cassandraHost != null && !cassandraHost.equals("${cassandra.host}")) { MusicUtil.setMyCassaHost(cassandraHost); } - if (notifyInterval != null && !notifyInterval.equals("${notify.interval}")) { - MusicUtil.setNotifyInterval(Integer.parseInt(notifyInterval)); - } - if (notifyTimeout != null && !notifyTimeout.equals("${notify.timeout}")) { - MusicUtil.setNotifyTimeOut(Integer.parseInt(notifyTimeout)); - } if (version != null && !version.equals("${version}")) { MusicUtil.setVersion(version); } @@ -202,8 +160,6 @@ public class PropertiesLoader implements InitializingBean { if (isKeyspaceActive != null && !isKeyspaceActive.equals("${keyspace.active}")) { MusicUtil.setKeyspaceActive(Boolean.parseBoolean(isKeyspaceActive)); } - - if(transIdPrefix!=null) { MusicUtil.setTransIdPrefix(transIdPrefix); } @@ -236,6 +192,8 @@ public class PropertiesLoader implements InitializingBean { MusicUtil.setMessageIdRequired(messageIdRequired); } } + + @Override diff --git a/src/main/java/org/onap/music/response/jsonobjects/JsonResponse.java b/src/main/java/org/onap/music/response/jsonobjects/JsonResponse.java index 2c419e18..f0793dc2 100644 --- a/src/main/java/org/onap/music/response/jsonobjects/JsonResponse.java +++ b/src/main/java/org/onap/music/response/jsonobjects/JsonResponse.java @@ -56,9 +56,19 @@ public class JsonResponse { private LockStatus lockStatus; private List lockHolders; private String lockLease; + private boolean isLockHolders=false; - /** + public boolean isLockHolders() { + return isLockHolders; + } + + public JsonResponse setisLockHolders(boolean isLockHolders) { + this.isLockHolders = isLockHolders; + return this; + } + + /** * Create a JSONLock Response * Use setters to provide more information as in * JsonLockResponse(ResultType.SUCCESS).setMessage("We did it").setLock(mylockname) @@ -282,7 +292,7 @@ public class JsonResponse { lockMap.put("lock-status", lockStatus); } if (lockHolders != null && !lockHolders.isEmpty()) { - if (lockHolders.size()==1) { + if (lockHolders.size()==1 && !isLockHolders) { //for backwards compatability lockMap.put("lock-holder", lockHolders.get(0)); } else { diff --git a/src/main/java/org/onap/music/rest/RestMusicDataAPI.java b/src/main/java/org/onap/music/rest/RestMusicDataAPI.java index 219e713c..39778338 100755 --- a/src/main/java/org/onap/music/rest/RestMusicDataAPI.java +++ b/src/main/java/org/onap/music/rest/RestMusicDataAPI.java @@ -73,10 +73,14 @@ import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.TableMetadata; import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiResponses; import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.Example; +import io.swagger.annotations.ExampleProperty; /* Version 2 Class */ //@Path("/v{version: [0-9]+}/keyspaces") @@ -111,6 +115,8 @@ public class RestMusicDataAPI { private static final String XPATCHVERSION = "X-patchVersion"; private static final String NS = "ns"; private static final String VERSION = "v2"; + private static final String PARAMETER_ERROR = "Missing Row Identifier. Please provide the parameter of key=value for the row being selected."; + private class RowIdentifier { public String primarKeyValue; @@ -138,9 +144,22 @@ public class RestMusicDataAPI { */ @POST @Path("/{name}") - @ApiOperation(value = "Create Keyspace", response = String.class,hidden = true) + @ApiOperation(value = "Create Keyspace", response = String.class, + notes = "This API will not work if MUSIC properties has keyspace.active=false ") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"message\" : \"Keysapce Created\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response createKeySpace( @ApiParam(value = "Major Version",required = true) @PathParam("version") String version, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @@ -196,11 +215,14 @@ public class RestMusicDataAPI { ResultType result = ResultType.FAILURE; try { result = MusicCore.nonKeyRelatedPut(queryObject, consistency); - logger.info(EELFLoggerDelegate.applicationLogger, "result = " + result); + } catch ( MusicQueryException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.QUERYERROR + ,ErrorSeverity.WARN, ErrorTypes.QUERYERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); } catch ( MusicServiceException ex) { logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity .WARN, ErrorTypes.MUSICSERVICEERROR, ex); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("err:" + ex.getMessage()).toMap()).build(); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); } return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Created").toMap()).build(); @@ -225,8 +247,21 @@ public class RestMusicDataAPI { */ @DELETE @Path("/{name}") - @ApiOperation(value = "Delete Keyspace", response = String.class,hidden=true) + @ApiOperation(value = "Delete Keyspace", response = String.class, + notes = "This API will not work if MUSIC properties has keyspace.active=false ") @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"message\" : \"Keysapce Deleted\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response dropKeySpace( @ApiParam(value = "Major Version",required = true) @PathParam("version") String version, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @@ -243,9 +278,20 @@ public class RestMusicDataAPI { String consistency = MusicUtil.EVENTUAL;// for now this needs only PreparedQueryObject queryObject = new PreparedQueryObject(); queryObject.appendQueryString("DROP KEYSPACE " + keyspaceName + ";"); - ResultType result = MusicCore.nonKeyRelatedPut(queryObject, consistency); - if ( result.equals(ResultType.FAILURE) ) { - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Error Deleteing Keyspace " + keyspaceName).toMap()).build(); + String droperror = "Error Deleteing Keyspace " + keyspaceName; + try{ + ResultType result = MusicCore.nonKeyRelatedPut(queryObject, consistency); + if ( result.equals(ResultType.FAILURE) ) { + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError(droperror).toMap()).build(); + } + } catch ( MusicQueryException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.QUERYERROR + ,ErrorSeverity.WARN, ErrorTypes.QUERYERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(droperror + " " + ex.getMessage()).toMap()).build(); + } catch ( MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR + ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR, ex); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(droperror + " " + ex.getMessage()).toMap()).build(); } return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Deleted").toMap()).build(); } else { @@ -271,18 +317,27 @@ public class RestMusicDataAPI { */ @POST @Path("/{keyspace: .*}/tables/{tablename: .*}") - @ApiOperation(value = "Create Table", response = String.class) + @ApiOperation(value = "Create Table", response = String.class, + notes = "Create a table with the required json in the body.") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @ApiResponses(value={ - @ApiResponse(code= 400, message = "Will return JSON response with message"), - @ApiResponse(code= 401, message = "Unautorized User") - }) + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"message\" : \"Tablename Created under keyspace \"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response createTable( @ApiParam(value = "Major Version",required = true) @PathParam("version") String version, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "AID", required = false,hidden = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam(NS) String ns, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, JsonTable tableObj, @@ -501,14 +556,34 @@ public class RestMusicDataAPI { */ @POST @Path("/{keyspace: .*}/tables/{tablename: .*}/index/{field: .*}") - @ApiOperation(value = "Create Index", response = String.class) + @ApiOperation(value = "Create Index", response = String.class, + notes = "An index provides a means to access data using attributes " + + "other than the partition key. The benefit is fast, efficient lookup " + + "of data matching a given condition.") @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"message\" : \"Index Created on ..\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"\"," + + "\"status\" : \"FAILURE\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Unknown Error in create index.\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response createIndex( @ApiParam(value = "Major Version",required = true) @PathParam("version") String version, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid, - @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam(NS) String ns, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, @ApiParam(value = "Keyspace Name",required = true) @PathParam("keyspace") String keyspace, @ApiParam(value = "Table Name",required = true) @PathParam("tablename") String tablename, @@ -559,9 +634,22 @@ public class RestMusicDataAPI { */ @POST @Path("/{keyspace: .*}/tables/{tablename: .*}/rows") - @ApiOperation(value = "Insert Into Table", response = String.class) + @ApiOperation(value = "Insert Into Table", response = String.class, + notes = "Insert into table with data in json body.") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"message\" : \"Insert Successful\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure - Generic",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response insertIntoTable( @ApiParam(value = "Major Version",required = true) @PathParam("version") String version, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @@ -764,7 +852,8 @@ public class RestMusicDataAPI { */ @PUT @Path("/{keyspace: .*}/tables/{tablename: .*}/rows") - @ApiOperation(value = "Update Table", response = String.class) + @ApiOperation(value = "Update Table", response = String.class, + notes = "Update the table with the data in the JSON body.") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response updateTable( @@ -921,8 +1010,14 @@ public class RestMusicDataAPI { return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock " + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build(); } - operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue, - queryObject, lockId, conditionInfo); + try { + operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue, + queryObject, lockId, conditionInfo); + } catch ( Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, + ErrorTypes.GENERALSERVICEERROR, e); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Error doing critical put: " + e.getMessage()).toMap()).build(); + } } else if (consistency.equalsIgnoreCase("atomic_delete_lock")) { // this function is mainly for the benchmarks try { @@ -987,7 +1082,8 @@ public class RestMusicDataAPI { */ @DELETE @Path("/{keyspace: .*}/tables/{tablename: .*}/rows") - @ApiOperation(value = "Delete From table", response = String.class) + @ApiOperation(value = "Delete From table", response = String.class, + notes = "Delete from a table, the row or parts of a row. Based on JSON body.") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response deleteFromTable( @@ -1135,6 +1231,17 @@ public class RestMusicDataAPI { @Path("/{keyspace: .*}/tables/{tablename: .*}") @ApiOperation(value = "Drop Table", response = String.class) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response dropTable( @ApiParam(value = "Major Version", required = true) @PathParam("version") String version, @@ -1142,7 +1249,7 @@ public class RestMusicDataAPI { required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version", required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "AID", required = false,hidden = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", required = false, hidden = true) @HeaderParam(NS) String ns, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, @@ -1163,9 +1270,13 @@ public class RestMusicDataAPI { query.appendQueryString("DROP TABLE " + keyspace + "." + tablename + ";"); try { return response.status(Status.OK).entity(new JsonResponse(MusicCore.nonKeyRelatedPut(query, consistency)).toMap()).build(); + } catch (MusicQueryException ex) { + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), AppMessages.QUERYERROR,ErrorSeverity.WARN + , ErrorTypes.QUERYERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); } catch (MusicServiceException ex) { - logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes - .GENERALSERVICEERROR); + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN + , ErrorTypes.GENERALSERVICEERROR,ex); return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); } } finally { @@ -1183,15 +1294,34 @@ public class RestMusicDataAPI { */ @PUT @Path("/{keyspace: .*}/tables/{tablename: .*}/rows/criticalget") - @ApiOperation(value = "Select Critical", response = Map.class) + @ApiOperation(value = "** Depreciated ** - Select Critical", response = Map.class, + notes = "This API is depreciated in favor of the regular select api.\n" + + "Avaliable to use with the select api by providing a minorVersion of 1 " + + "and patchVersion of 0.\n" + + "Critical Get requires parameter rowId=value and consistency in order to work.\n" + + "It will fail if either are missing.") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"result\":{\"row 0\":{\"address\":" + + "{\"city\":\"Someplace\",\"street\":\"1 Some way\"}," + + "\"emp_salary\":50,\"emp_name\":\"tom\",\"emp_id\":" + + "\"cfd66ccc-d857-4e90-b1e5-df98a3d40cd6\"}},\"status\":\"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response selectCritical( @ApiParam(value = "Major Version", - required = true) @PathParam("version") String version, - @ApiParam(value = "Minor Version", + required = true) @PathParam("version") String version, + @ApiParam(value = "Minor Version",example = "0", required = false) @HeaderParam(XMINORVERSION) String minorVersion, - @ApiParam(value = "Patch Version", + @ApiParam(value = "Patch Version",example = "0", required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", @@ -1205,22 +1335,33 @@ public class RestMusicDataAPI { @Context UriInfo info) throws Exception { try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); - if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){ + if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())) { return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) .setError("one or more path parameters are not set, please check and try again") .toMap()).build(); } - if(selObj == null) { - logger.error(EELFLoggerDelegate.errorLogger,ResultType.BODYMISSING.getResult(), AppMessages.MISSINGDATA ,ErrorSeverity.WARN, ErrorTypes.DATAERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ResultType.BODYMISSING.getResult()).toMap()).build(); + EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspace + " )"); + if (info.getQueryParameters().isEmpty()) { + logger.error(EELFLoggerDelegate.errorLogger,RestMusicDataAPI.PARAMETER_ERROR, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes + .GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(RestMusicDataAPI.PARAMETER_ERROR).toMap()).build(); + } + if (selObj == null || selObj.getConsistencyInfo().isEmpty()) { + String error = " Missing Body or Consistency type."; + logger.error(EELFLoggerDelegate.errorLogger,ResultType.BODYMISSING.getResult() + error, AppMessages.MISSINGDATA ,ErrorSeverity.WARN, ErrorTypes.DATAERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ResultType.BODYMISSING.getResult() + error).toMap()).build(); } - EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) "); String lockId = selObj.getConsistencyInfo().get("lockId"); PreparedQueryObject queryObject = new PreparedQueryObject(); RowIdentifier rowId = null; try { rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject); + if ( "".equals(rowId)) { + logger.error(EELFLoggerDelegate.errorLogger,RestMusicDataAPI.PARAMETER_ERROR, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes + .GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(RestMusicDataAPI.PARAMETER_ERROR).toMap()).build(); + } } catch (MusicServiceException ex) { logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes .GENERALSERVICEERROR, ex); @@ -1233,18 +1374,24 @@ public class RestMusicDataAPI { String consistency = selObj.getConsistencyInfo().get("type"); try { - if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { - if(lockId == null) { - logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" - + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock " - + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build(); + if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + if(lockId == null) { + logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" + + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock " + + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build(); + } + results = MusicCore.criticalGet(keyspace, tablename, rowId.primarKeyValue, queryObject,lockId); + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + results = MusicCore.atomicGet(keyspace, tablename, rowId.primarKeyValue, queryObject); + } else { + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + .setError("Consistency must be: " + MusicUtil.ATOMIC + " or " + MusicUtil.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); - } - }catch(Exception ex) { + } catch ( MusicLockingException | MusicServiceException me ) { + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Music Exception" + me.getMessage()).toMap()).build(); + } catch ( Exception ex) { return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); } @@ -1258,33 +1405,74 @@ public class RestMusicDataAPI { } /** - * + * This API will replace the original select and provide a single API fro select and critical. + * The idea is to depreciate the older api of criticalGet and use a single API. + * + * @param selObj * @param keyspace * @param tablename * @param info * @return - * @throws Exception */ @GET @Path("/{keyspace: .*}/tables/{tablename: .*}/rows") - @ApiOperation(value = "Select All or Select Specific", response = Map.class) + @ApiOperation(value = "Select", response = Map.class, + notes = "This has 2 versions: if minorVersion and patchVersion is null or 0, this will be a Eventual Select only.\n" + + "If minorVersion is 1 and patchVersion is 0, this will act like the Critical Select \n" + + "Critical Get requires parameter rowId=value and consistency in order to work.\n" + + "If parameters are missing or consistency information is missing. An eventual select will be preformed.") + @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - public Response select( - @ApiParam(value = "Major Version", + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"result\":{\"row 0\":{\"address\":" + + "{\"city\":\"Someplace\",\"street\":\"1 Some way\"}," + + "\"emp_salary\":50,\"emp_name\":\"tom\",\"emp_id\":" + + "\"cfd66ccc-d857-4e90-b1e5-df98a3d40cd6\"}},\"status\":\"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"\"," + + "\"status\" : \"FAILURE\"}") + })) + }) + public Response selectWithCritical( + @ApiParam(value = "Major Version",example = "v2", required = true) @PathParam("version") String version, - @ApiParam(value = "Minor Version", + @ApiParam(value = "Minor Version",example = "1", required = false) @HeaderParam(XMINORVERSION) String minorVersion, - @ApiParam(value = "Patch Version", + @ApiParam(value = "Patch Version",example = "0", required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", required = false,hidden = true) @HeaderParam(NS) String ns, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "Keyspace Name", - required = true) @PathParam("keyspace") String keyspace, - @ApiParam(value = "Table Name", - required = true) @PathParam("tablename") String tablename, + JsonInsert selObj, + @ApiParam(value = "Keyspace Name", required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Table Name", required = true) @PathParam("tablename") String tablename, @Context UriInfo info) throws Exception { + if ((minorVersion != null && patchVersion != null) && + (Integer.parseInt(minorVersion) == 1 && Integer.parseInt(patchVersion) == 0) && + (!(null == selObj) && !selObj.getConsistencyInfo().isEmpty())) { + return selectCritical(version, minorVersion, patchVersion, aid, ns, authorization, selObj, keyspace, tablename, info); + } else { + return select(version, minorVersion, patchVersion, aid, ns, authorization, keyspace, tablename, info); + } + } + + /** + * + * @param keyspace + * @param tablename + * @param info + * @return + * @throws Exception + */ + private Response select( + String version,String minorVersion,String patchVersion, + String aid,String ns,String authorization,String keyspace, + String tablename,UriInfo info) throws Exception { try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){ diff --git a/src/main/java/org/onap/music/rest/RestMusicHealthCheckAPI.java b/src/main/java/org/onap/music/rest/RestMusicHealthCheckAPI.java index cb8965ee..73afe6a1 100644 --- a/src/main/java/org/onap/music/rest/RestMusicHealthCheckAPI.java +++ b/src/main/java/org/onap/music/rest/RestMusicHealthCheckAPI.java @@ -62,32 +62,42 @@ public class RestMusicHealthCheckAPI { private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicUtil.class); private static final String ACTIVE_STATUS = "ACTIVE"; + private static final String INVALID_STATUS = "INVALID"; + private static final String INACTIVE_STATUS = "INACTIVE"; + private static final String INVALID_MESSAGE = "Consistency level is invalid..."; + private static final String INACTIVE_MESSAGE = "One or more nodes in the Cluster is/are down or not responding."; + private static final String ACTIVE_MESSAGE = "Cassandra Running and Listening to requests"; @GET @Path("/pingCassandra/{consistency}") @ApiOperation(value = "Get Health Status", response = Map.class) @Produces(MediaType.APPLICATION_JSON) - public Response cassandraStatus(@Context HttpServletResponse response, @ApiParam(value = "Consistency level", - required = true) @PathParam("consistency") String consistency) { + public Response cassandraStatus( + @Context HttpServletResponse response, + @ApiParam(value = "Consistency level",required = true) + @PathParam("consistency") String consistency) { logger.info(EELFLoggerDelegate.applicationLogger,"Replying to request for MUSIC Health Check status for Cassandra"); Map resultMap = new HashMap<>(); if(ConsistencyLevel.valueOf(consistency) == null) { - resultMap.put("INVALID", "Consistency level is invalid..."); + resultMap.put("status",INVALID_STATUS); + resultMap.put("message", INVALID_MESSAGE); + resultMap.put(INVALID_STATUS, INVALID_STATUS); return Response.status(Status.BAD_REQUEST).entity(resultMap).build(); } MusicHealthCheck cassHealthCheck = new MusicHealthCheck(); String status = cassHealthCheck.getCassandraStatus(consistency); if(status.equals(ACTIVE_STATUS)) { - resultMap.put(ACTIVE_STATUS, "Cassandra Running and Listening to requests"); + resultMap.put("status",ACTIVE_STATUS); + resultMap.put("message", ACTIVE_MESSAGE); + resultMap.put(ACTIVE_STATUS, ACTIVE_MESSAGE); return Response.status(Status.OK).entity(resultMap).build(); } else { - resultMap.put("INACTIVE", "One or more nodes in the Cluster is/are down or not responding."); + resultMap.put("status",INACTIVE_STATUS); + resultMap.put("message", INACTIVE_MESSAGE); + resultMap.put(INACTIVE_STATUS, INACTIVE_MESSAGE); return Response.status(Status.BAD_REQUEST).entity(resultMap).build(); } - - - } @GET diff --git a/src/main/java/org/onap/music/rest/RestMusicLocksAPI.java b/src/main/java/org/onap/music/rest/RestMusicLocksAPI.java index 079fe97c..35f03e60 100644 --- a/src/main/java/org/onap/music/rest/RestMusicLocksAPI.java +++ b/src/main/java/org/onap/music/rest/RestMusicLocksAPI.java @@ -59,10 +59,14 @@ import org.onap.music.response.jsonobjects.JsonResponse; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import io.swagger.annotations.Example; +import io.swagger.annotations.ExampleProperty; @Path("/v2/locks/") -@Api(value="Lock Api") +@Api(value="Locking Api") public class RestMusicLocksAPI { private EELFLoggerDelegate logger =EELFLoggerDelegate.getLogger(RestMusicLocksAPI.class); @@ -80,22 +84,40 @@ public class RestMusicLocksAPI { */ @POST @Path("/create/{lockname}") - @ApiOperation(value = "Create Lock", - notes = "Puts the requesting process in the q for this lock." + - " The corresponding lock will be created if it did not already exist." + - " Lock Name is the \"key\" of the form keyspaceName.tableName.rowId", + @ApiOperation(value = "Create and Acquire a Lock Id for a single row.", + notes = "Creates and Acquires a Lock Id for a specific Row in a table based on the key of that row.\n" + + " The corresponding lock will be created if it did not already exist." + + " Lock Name also the Lock is in the form of keyspaceName.tableName.rowId.\n" + + " The Response will be in the form of \"$kesypaceName.tableName.rowId$lockRef\" " + + " where the lockRef is a integer representing the Lock Name buffered by \"$\" " + + " followed by the lock number. This term for " + + " this response is a lockId and it will be used in other /locks API calls where a " + + " lockId is required. If just a lock is required then the form that would be " + + " the original lockname(without the buffered \"$\").", response = Map.class) @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"lock\" : {\"lock\" : \"$keyspace.table.rowId$\"}," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Unable to aquire lock\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response createLockReference( @ApiParam(value="Lock Name",required=true) @PathParam("lockname") String lockName, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, JsonLock lockObject, @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map resultMap = MusicCore.validateLock(lockName); @@ -138,19 +160,32 @@ public class RestMusicLocksAPI { * @throws Exception */ @GET - @Path("/acquire/{lockreference}") - @ApiOperation(value = "Aquire Lock", + @Path("/acquire/{lockId}") + @ApiOperation(value = "Aquire Lock Id ", notes = "Checks if the node is in the top of the queue and hence acquires the lock", response = Map.class) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"lock\" : {\"lock\" : \"$keyspace.table.rowId$\"}," + + "\"message\" : \" is the lock holder for the key\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Unable to aquire lock\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response accquireLock( - @ApiParam(value="Lock Reference",required=true) @PathParam("lockreference") String lockId, + @ApiParam(value="Lock Id",required=true) @PathParam("lockId") String lockId, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map resultMap = MusicCore.validateLock(lockId); @@ -182,21 +217,40 @@ public class RestMusicLocksAPI { } - - @POST - @Path("/acquire-with-lease/{lockreference}") - @ApiOperation(value = "Aquire Lock with Lease", response = Map.class) + @Path("/acquire-with-lease/{lockId}") + @ApiOperation( + hidden = false, + value = " ** DEPRECATED ** - Aquire Lock with Lease", + notes = "Acquire the lock with a lease, where lease period is in Milliseconds.\n" + + "This will ensure that a lock will expire in set milliseconds.\n" + + "This is no longer available after v3.2.0", + response = Map.class) @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - public Response accquireLockWithLease(JsonLeasedLock lockObj, - @ApiParam(value="Lock Reference",required=true) @PathParam("lockreference") String lockId, - @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, - @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, - @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"lock\" : {\"lock\" : \"$keyspace.table.rowId$\"," + + "\"lock-lease\" : \"6000\"}," + + "\"message\" : \" is the lock holder for the key\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Unable to aquire lock\"," + + "\"status\" : \"FAILURE\"}") + })) + }) + @Deprecated + public Response accquireLockWithLease( + JsonLeasedLock lockObj, + @ApiParam(value="Lock Id",required=true) @PathParam("lockId") String lockId, + @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, + @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, + @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map resultMap = MusicCore.validateLock(lockId); @@ -220,6 +274,8 @@ public class RestMusicLocksAPI { } finally { EELFLoggerDelegate.mdcRemove("keyspace"); } + + } @@ -229,14 +285,27 @@ public class RestMusicLocksAPI { notes = "Gets the current single lockholder at top of lock queue", response = Map.class) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"lock\" : {\"lock\" : \"keyspace.table.rowId\"," + + "\"lock-holder\" : \"$tomtest.employees.tom$\"}}," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Error Message\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response enquireLock( @ApiParam(value="Lock Name",required=true) @PathParam("lockname") String lockName, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map resultMap = MusicCore.validateLock(lockName); @@ -265,16 +334,30 @@ public class RestMusicLocksAPI { @GET @Path("/holders/{lockname}") @ApiOperation(value = "Get Lock Holders", - notes = "Gets the current Lock Holders", + notes = "Gets the current Lock Holders.\n" + + "Will return an array of READ Lock References.", response = Map.class) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"lock\" : {\"lock\" : \"keyspace.table.rowId\"," + + "\"lock-holder\" : [\"$keyspace.table.rowId$\",\"$keyspace.table.rowId$\"]}}," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Error message\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response currentLockHolder(@ApiParam(value="Lock Name",required=true) @PathParam("lockname") String lockName, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map resultMap = MusicCore.validateLock(lockName); @@ -290,9 +373,9 @@ public class RestMusicLocksAPI { List who = MusicCore.getCurrentLockHolders(lockName); ResultType status = ResultType.SUCCESS; String error = ""; - if (who == null) { + if (who == null || who.isEmpty()) { status = ResultType.FAILURE; - error = "There was a problem getting the lock holder"; + error = (who !=null && who.isEmpty()) ? "No lock holders for the key":"There was a problem getting the lock holder"; logger.error(EELFLoggerDelegate.errorLogger, "There was a problem getting the lock holder", AppMessages.INCORRECTDATA, ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); return response.status(Status.BAD_REQUEST) @@ -300,8 +383,8 @@ public class RestMusicLocksAPI { .build(); } return response.status(Status.OK) - .entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).toMap()) - .build(); + .entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).setisLockHolders(true).toMap()) + .build(); } finally { EELFLoggerDelegate.mdcRemove("keyspace"); } @@ -312,16 +395,29 @@ public class RestMusicLocksAPI { @Path("/{lockname}") @ApiOperation(value = "Lock State", notes = "Returns current Lock State and Holder.", - response = Map.class) + response = Map.class,hidden = true) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"lock\" : {\"lock\" : \"$keyspace.table.rowId$\"}," + + "\"message\" : \" is the lock holder for the key\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Unable to aquire lock\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response currentLockState( @ApiParam(value="Lock Name",required=true) @PathParam("lockname") String lockName, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map resultMap = MusicCore.validateLock(lockName); @@ -358,16 +454,29 @@ public class RestMusicLocksAPI { @DELETE @Path("/release/{lockreference}") @ApiOperation(value = "Release Lock", - notes = "deletes the process from the lock queue", + notes = "Releases the lock from the lock queue.", response = Map.class) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success - UNLOCKED = Lock Removed.",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"lock\" : {\"lock\" : \"$keyspace.table.rowId$\"}," + + "\"lock-status\" : \"UNLOCKED\"}," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Unable to aquire lock\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response unLock(@PathParam("lockreference") String lockId, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map resultMap = MusicCore.validateLock(lockId); @@ -409,17 +518,32 @@ public class RestMusicLocksAPI { * @param lockName * @throws Exception */ + @Deprecated @DELETE @Path("/delete/{lockname}") - @ApiOperation(value = "Delete Lock", response = Map.class) + @ApiOperation( + hidden = true, + value = "-DEPRECATED- Delete Lock", response = Map.class, + notes = "-DEPRECATED- Delete the lock.") @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Error Message if any\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response deleteLock(@PathParam("lockname") String lockName, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map resultMap = MusicCore.validateLock(lockName); diff --git a/src/main/java/org/onap/music/rest/RestMusicQAPI.java b/src/main/java/org/onap/music/rest/RestMusicQAPI.java index 768f1a44..4def0e45 100755 --- a/src/main/java/org/onap/music/rest/RestMusicQAPI.java +++ b/src/main/java/org/onap/music/rest/RestMusicQAPI.java @@ -25,7 +25,6 @@ package org.onap.music.rest; -import java.util.HashMap; import java.util.Map; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; @@ -67,7 +66,7 @@ import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; @Path("/v2/priorityq/") -@Api(value = "Q Api") +@Api(value = "Q Api",hidden = true) public class RestMusicQAPI { private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicQAPI.class); @@ -95,7 +94,7 @@ public class RestMusicQAPI { @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, JsonTable tableObj, @ApiParam(value = "Key Space", required = true) @PathParam("keyspace") String keyspace, - @ApiParam(value = "Table Name", required = true) @PathParam("qname") String tablename) throws Exception { + @ApiParam(value = "Table Name", required = true) @PathParam("qname") String tablename) throws Exception { ResponseBuilder response = MusicUtil.buildVersionResponse(version, minorVersion, patchVersion); Map fields = tableObj.getFields(); @@ -409,7 +408,7 @@ public class RestMusicQAPI { @ApiParam(value = "Table Name", required = true) @PathParam("qname") String tablename, @Context UriInfo info) throws Exception { - return new RestMusicDataAPI().select(version, minorVersion, patchVersion, aid, ns, authorization, keyspace, tablename, info);// , limit) + return new RestMusicDataAPI().selectWithCritical(version, minorVersion, patchVersion, aid, ns, authorization,null, keyspace, tablename, info);// , limit) } diff --git a/src/main/java/org/onap/music/rest/RestMusicTestAPI.java b/src/main/java/org/onap/music/rest/RestMusicTestAPI.java index 6d973acb..c1c04b09 100644 --- a/src/main/java/org/onap/music/rest/RestMusicTestAPI.java +++ b/src/main/java/org/onap/music/rest/RestMusicTestAPI.java @@ -51,6 +51,7 @@ public class RestMusicTestAPI { * @return */ @GET + @Path("/") @ApiOperation(value = "Get Test", response = Map.class) @Produces(MediaType.APPLICATION_JSON) public Map> simpleTests( @@ -60,6 +61,7 @@ public class RestMusicTestAPI { for(int i=0; i < 3; i++){ HashMap innerMap = new HashMap<>(); innerMap.put("Music Version",MusicUtil.getVersion()); + innerMap.put("Music Build",MusicUtil.getBuild()); innerMap.put(i+1+"", i+2+""); testMap.put(i+"", innerMap); } diff --git a/src/main/java/org/onap/music/service/MusicCoreService.java b/src/main/java/org/onap/music/service/MusicCoreService.java index a50e7c2a..9bbef9c1 100644 --- a/src/main/java/org/onap/music/service/MusicCoreService.java +++ b/src/main/java/org/onap/music/service/MusicCoreService.java @@ -51,7 +51,7 @@ public interface MusicCoreService { PreparedQueryObject queryObject, String lockId, Condition conditionInfo); public ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) - throws MusicServiceException; + throws MusicServiceException,MusicQueryException; public ResultSet get(PreparedQueryObject queryObject) throws MusicServiceException; diff --git a/src/main/java/org/onap/music/service/impl/MusicCassaCore.java b/src/main/java/org/onap/music/service/impl/MusicCassaCore.java index cebdc667..253081e0 100644 --- a/src/main/java/org/onap/music/service/impl/MusicCassaCore.java +++ b/src/main/java/org/onap/music/service/impl/MusicCassaCore.java @@ -498,14 +498,22 @@ public class MusicCassaCore implements MusicCoreService { PreparedQueryObject queryObject, String lockId, Condition conditionInfo) { long start = System.currentTimeMillis(); try { + String keyLock = lockId.substring(lockId.lastIndexOf(".") + 1,lockId.lastIndexOf("$")); + if (lockId.contains(".") && !keyLock.equals(primaryKeyValue)) { + return new ReturnType(ResultType.FAILURE,"Lock value '" + keyLock + "' and key value '" + + primaryKeyValue + "' not match. Please check your values: " + + lockId + " ."); + } LockObject lockObject = getLockingServiceHandle().getLockInfo(keyspace, table, primaryKeyValue, lockId.substring(lockId.lastIndexOf("$") + 1)); - if (!lockObject.getIsLockOwner()) { + if ( lockObject == null ) { + return new ReturnType(ResultType.FAILURE, lockId + " does not exist."); + } else if (!lockObject.getIsLockOwner()) { return new ReturnType(ResultType.FAILURE, lockId + " is not the lock holder"); } else if (lockObject.getLocktype() != LockType.WRITE) { return new ReturnType(ResultType.FAILURE, - "Attempting to do write operation, but " + lockId + " is a write lock"); + "Attempting to do write operation, but " + lockId + " is a read lock"); } if (conditionInfo != null) { @@ -536,10 +544,10 @@ public class MusicCassaCore implements MusicCoreService { dsHandle.executePut(queryObject, MusicUtil.CRITICAL); long end = System.currentTimeMillis(); logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the critical put:" + (end - start) + " ms"); - }catch (MusicQueryException | MusicServiceException | MusicLockingException e) { + } catch (MusicQueryException | MusicServiceException | MusicLockingException e) { logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), e); return new ReturnType(ResultType.FAILURE, - "Exception thrown while doing the critical put\n" + "Exception thrown while doing the critical put: " + e.getMessage()); } return new ReturnType(ResultType.SUCCESS, "Update performed"); @@ -555,17 +563,17 @@ public class MusicCassaCore implements MusicCoreService { * * */ - public ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) throws MusicServiceException { + public ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) throws MusicServiceException,MusicQueryException { // this is mainly for some functions like keyspace creation etc which does not // really need the bells and whistles of Music locking. boolean result = false; - try { - result = MusicDataStoreHandle.getDSHandle().executePut(queryObject, consistency); - } catch (MusicQueryException | MusicServiceException ex) { - logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), AppMessages.UNKNOWNERROR, - ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR, ex); - throw new MusicServiceException(ex.getMessage()); - } +// try { + result = MusicDataStoreHandle.getDSHandle().executePut(queryObject, consistency); +// } catch (MusicQueryException | MusicServiceException ex) { + // logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), AppMessages.UNKNOWNERROR, + // ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR, ex); +// throw new MusicServiceException(ex.getMessage(),ex); +// } return result ? ResultType.SUCCESS : ResultType.FAILURE; } @@ -601,17 +609,33 @@ public class MusicCassaCore implements MusicCoreService { public ResultSet criticalGet(String keyspace, String table, String primaryKeyValue, PreparedQueryObject queryObject, String lockId) throws MusicServiceException { ResultSet results = null; - + String keyLock = lockId.substring(lockId.lastIndexOf(".") + 1,lockId.lastIndexOf("$")); try { + if (lockId.contains(".") && !keyLock.equals(primaryKeyValue)) { + throw new MusicLockingException("Lock value '" + keyLock + "' and key value '" + + primaryKeyValue + "' do not match. Please check your values: " + + lockId + " ."); + } LockObject lockObject = getLockingServiceHandle().getLockInfo(keyspace, table, primaryKeyValue, - lockId.substring(lockId.lastIndexOf("$") + 1)); - if (!lockObject.getIsLockOwner()) { + lockId.substring(lockId.lastIndexOf("$") + 1)); + if (null == lockObject) { + throw new MusicLockingException("No Lock Object. Please check if lock name or key is correct." + + lockId + " ."); + } + if ( !lockObject.getIsLockOwner()) { return null;// not top of the lock store q } results = MusicDataStoreHandle.getDSHandle().executeQuorumConsistencyGet(queryObject); - } catch (MusicQueryException | MusicServiceException | MusicLockingException e) { - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity + } catch ( MusicLockingException e ) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity + .WARN, ErrorTypes.MUSICSERVICEERROR); + throw new MusicServiceException( + "Cannot perform critical get for key: " + primaryKeyValue + " : " + e.getMessage()); + } catch (MusicQueryException | MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity .WARN, ErrorTypes.MUSICSERVICEERROR, e); + throw new MusicServiceException( + "Cannot perform critical get for key: " + primaryKeyValue + " : " + e.getMessage()); } return results; } -- cgit 1.2.3-korg