diff options
Diffstat (limited to 'src/main/java/org')
27 files changed, 1051 insertions, 636 deletions
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<AAFPermission> filterNameSpacesAAFPermissions(String nameSpace, List<AAFPermission> allPermissionsList) { List<AAFPermission> list = new ArrayList<>(); - for (Iterator iterator = allPermissionsList.iterator(); iterator.hasNext();) { + for (Iterator<AAFPermission> iterator = allPermissionsList.iterator(); iterator.hasNext();) { AAFPermission aafPermission = (AAFPermission) iterator.next(); if(aafPermission.getType().indexOf(nameSpace) == 0) { list.add(aafPermission); @@ -152,15 +152,15 @@ public class AuthUtil { List<AAFPermission> aafPermsFinalList = filterNameSpacesAAFPermissions(nameSpace, aafPermsList); - logger.debug(EELFLoggerDelegate.applicationLogger, - "AuthUtil list of AAFPermission for the specific namespace ::::::::::::::::::::::::::::::::::::::::::::" + logger.debug(EELFLoggerDelegate.securityLogger, + "AuthUtil list of AAFPermission for the specific namespace :::" + aafPermsFinalList); HttpServletRequest httpRequest = (HttpServletRequest) request; String requestUri = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length() + 1); - logger.debug(EELFLoggerDelegate.applicationLogger, - "AuthUtil requestUri ::::::::::::::::::::::::::::::::::::::::::::" + requestUri); + logger.debug(EELFLoggerDelegate.securityLogger, + "AuthUtil requestUri :::" + requestUri); for (Iterator iterator = aafPermsFinalList.iterator(); iterator.hasNext();) { 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 <code>CadiAuthFilter</code> doFilter - logger.debug(EELFLoggerDelegate.applicationLogger, - "Time took for authentication & authorization : " - + (endTime - startTime) + " milliseconds"); + logger.debug(EELFLoggerDelegate.securityLogger, + "Time took for authentication & authorization : " + + (endTime - startTime) + " milliseconds"); if (!isAuthAllowed) { - logger.debug(EELFLoggerDelegate.applicationLogger, + logger.info(EELFLoggerDelegate.securityLogger, "Unauthorized Access"); AuthorizationError authError = new AuthorizationError(); authError.setResponseCode(HttpServletResponse.SC_UNAUTHORIZED); @@ -124,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<String, byte[]> objectMap; private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonInsert.class); - @ApiModelProperty(value = "objectMap") + @ApiModelProperty(value = "objectMap",hidden = true) public Map<String, byte[]> getObjectMap() { return objectMap; } @@ -90,7 +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<String, Object> 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<String, Object> 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<String, EELFLoggerDelegate> classMap = new ConcurrentHashMap<>(); @@ -230,9 +231,7 @@ public class EELFLoggerDelegate extends SLF4jWrapper implements EELFLogger { * @param logger * @param msg * - * @deprecated use {@link #error(EELF, Exception)} instead */ - @Deprecated public void error(EELFLogger logger, String msg) { logger.error(className+ " - " + msg); } @@ -254,9 +253,7 @@ public class EELFLoggerDelegate extends SLF4jWrapper implements EELFLogger { * @param msg * @param arguments * - * @deprecated use {@link #error(EELF, Exception, Object...)} instead */ - @Deprecated public void error(EELFLogger logger, String msg, Object... arguments) { logger.error(msg, arguments); } @@ -289,9 +286,7 @@ public class EELFLoggerDelegate extends SLF4jWrapper implements EELFLogger { * @param logger * @param msg * @param severtiy - * @deprecated use {@link #error(EELF, Exception)} instead */ - @Deprecated public void error(EELFLogger logger, String msg, Object /* AlarmSeverityEnum */ severtiy) { logger.error(msg); } @@ -309,6 +304,8 @@ public class EELFLoggerDelegate extends SLF4jWrapper implements EELFLogger { debug(debugLogger, msg); info(auditLogger, msg); info(metricsLogger, msg); + info(securityLogger, msg); + } /** diff --git a/src/main/java/org/onap/music/eelf/logging/MusicContainerFilter.java b/src/main/java/org/onap/music/eelf/logging/MusicContainerFilter.java index 23f29595..bac02afa 100644 --- a/src/main/java/org/onap/music/eelf/logging/MusicContainerFilter.java +++ b/src/main/java/org/onap/music/eelf/logging/MusicContainerFilter.java @@ -39,32 +39,30 @@ import org.springframework.stereotype.Component; @Component public class MusicContainerFilter implements ContainerResponseFilter { - private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicContainerFilter.class); - - public MusicContainerFilter() { - - } - - @Override - public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) - throws IOException { - logger.info(EELFLoggerDelegate.applicationLogger, "In MusicContainerFilter response filter ::::::::::::::::::::::::"); - - if (null != EELFLoggerDelegate.mdcGet("transactionId")) { - EELFLoggerDelegate.mdcRemove("transactionId"); - } - - if (null != EELFLoggerDelegate.mdcGet("conversationId")) { - EELFLoggerDelegate.mdcRemove("conversationId"); - } - - if (null != EELFLoggerDelegate.mdcGet("clientId")) { - EELFLoggerDelegate.mdcRemove("clientId"); - } - - if (null != EELFLoggerDelegate.mdcGet("messageId")) { - EELFLoggerDelegate.mdcRemove("messageId"); - } - } - + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicContainerFilter.class); + + public MusicContainerFilter() { + + } + + @Override + public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) + throws IOException { + if (null != EELFLoggerDelegate.mdcGet("transactionId")) { + EELFLoggerDelegate.mdcRemove("transactionId"); + } + + if (null != EELFLoggerDelegate.mdcGet("conversationId")) { + EELFLoggerDelegate.mdcRemove("conversationId"); + } + + if (null != EELFLoggerDelegate.mdcGet("clientId")) { + EELFLoggerDelegate.mdcRemove("clientId"); + } + + if (null != EELFLoggerDelegate.mdcGet("messageId")) { + EELFLoggerDelegate.mdcRemove("messageId"); + } + } + } diff --git a/src/main/java/org/onap/music/eelf/logging/MusicLoggingServletFilter.java b/src/main/java/org/onap/music/eelf/logging/MusicLoggingServletFilter.java index cb688c54..7eca73e1 100644 --- a/src/main/java/org/onap/music/eelf/logging/MusicLoggingServletFilter.java +++ b/src/main/java/org/onap/music/eelf/logging/MusicLoggingServletFilter.java @@ -85,8 +85,8 @@ public class MusicLoggingServletFilter implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - logger.info(EELFLoggerDelegate.applicationLogger, - "In MusicLogginServletFilter doFilter start() ::::::::::::::::::::::: [\"+MusicUtil.getTransIdRequired()+\",\"+MusicUtil.getConversationIdRequired()+\",\"+MusicUtil.getClientIdRequired()+\",\"+MusicUtil.getMessageIdRequired()"); + logger.info(EELFLoggerDelegate.securityLogger, + "In MusicLogginServletFilter doFilter start() :: [\"+MusicUtil.getTransIdRequired()+\",\"+MusicUtil.getConversationIdRequired()+\",\"+MusicUtil.getClientIdRequired()+\",\"+MusicUtil.getMessageIdRequired()"); HttpServletRequest httpRequest = null; HttpServletResponse httpResponse = null; @@ -149,7 +149,7 @@ public class MusicLoggingServletFilter implements Filter { } - logger.info(EELFLoggerDelegate.applicationLogger, + logger.info(EELFLoggerDelegate.securityLogger, "In MusicLogginServletFilter doFilter. Header values validated sucessfully"); chain.doFilter(request, response); diff --git a/src/main/java/org/onap/music/lockingservice/cassandra/CassaLockStore.java b/src/main/java/org/onap/music/lockingservice/cassandra/CassaLockStore.java index 3c3f7160..06a087ab 100644 --- a/src/main/java/org/onap/music/lockingservice/cassandra/CassaLockStore.java +++ b/src/main/java/org/onap/music/lockingservice/cassandra/CassaLockStore.java @@ -274,7 +274,7 @@ public class CassaLockStore { String lockReference = "" + row.getLong("lockReference"); String createTime = row.getString("createTime"); String acquireTime = row.getString("acquireTime"); - LockType locktype = row.getBool("writeLock") ? LockType.WRITE : LockType.READ; + LockType locktype = row.isNull("writeLock") || row.getBool("writeLock") ? LockType.WRITE : LockType.READ; return new LockObject(true, lockReference, createTime, acquireTime, locktype); } @@ -283,29 +283,37 @@ public class CassaLockStore { throws MusicServiceException, MusicQueryException { logger.info(EELFLoggerDelegate.applicationLogger, "Getting lockholders in lock table for " + keyspace + "." + table + "." + key); + String origTable = table; table = table_prepend_name + table; String selectQuery = "select * from " + keyspace + "." + table + " where key=?;"; + List<String> lockHolders = new ArrayList<>(); PreparedQueryObject queryObject = new PreparedQueryObject(); queryObject.appendQueryString(selectQuery); queryObject.addValue(key); ResultSet rs = dsHandle.executeOneConsistencyGet(queryObject); - - List<String> lockHolders = new ArrayList<>(); boolean topOfQueue = true; + StringBuilder lock = new StringBuilder(). + append("$").append(keyspace).append(".").append(origTable). + append(".").append(key).append("$"); + StringBuilder lockReference = new StringBuilder(); for (Row row : rs) { - String lockReference = "" + row.getLong("lockReference"); - if (row.getBool("writeLock")) { + if ( row.isNull("lockReference") ) { + return lockHolders; + } + lockReference.append(lock).append(row.getLong("lockReference")); + if (row.isNull("writeLock") || row.getBool("writeLock")) { if (topOfQueue) { - lockHolders.add(lockReference); + lockHolders.add(lockReference.toString()); break; } else { break; } } // read lock - lockHolders.add(lockReference); + lockHolders.add(lockReference.toString()); topOfQueue = false; + lockReference.delete(0,lockReference.length()); } return lockHolders; } @@ -335,16 +343,16 @@ public class CassaLockStore { boolean topOfQueue = true; for (Row row : rs) { - String lockReference = "" + row.getLong("lockReference"); - if (row.getBool("writeLock")) { + String lockReference = "" + row.getLong("lockReference"); + if (row.isNull("writeLock") || row.getBool("writeLock")) { if (topOfQueue && lockRef.equals(lockReference)) { - return true; + return true; } else { - return false; + return false; } } if (lockRef.equals(lockReference)) { - return true; + return true; } topOfQueue = false; } @@ -384,7 +392,7 @@ public class CassaLockStore { String lockReference = "" + row.getLong("lockReference"); String createTime = row.getString("createTime"); String acquireTime = row.getString("acquireTime"); - LockType locktype = row.getBool("writeLock") ? LockType.WRITE : LockType.READ; + LockType locktype = row.isNull("writeLock") || row.getBool("writeLock") ? LockType.WRITE : LockType.READ; boolean isLockOwner = isLockOwner(keyspace, table, key, lockRef); return new LockObject(isLockOwner, lockReference, createTime, acquireTime, locktype); @@ -441,8 +449,9 @@ public class CassaLockStore { String updateQuery = "update " + keyspace + "." + table + " set acquireTime='" + System.currentTimeMillis() + "' where key='" + key + "' AND lockReference = " + lockReferenceL + " IF EXISTS;"; queryObject.appendQueryString(updateQuery); - dsHandle.executePut(queryObject, "eventual"); + //cannot use executePut because we need to ignore music timestamp adjustments for lock store + dsHandle.getSession().execute(updateQuery); } } diff --git a/src/main/java/org/onap/music/main/CipherUtil.java b/src/main/java/org/onap/music/main/CipherUtil.java new file mode 100644 index 00000000..0d5b7710 --- /dev/null +++ b/src/main/java/org/onap/music/main/CipherUtil.java @@ -0,0 +1,270 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.main; + +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.UnsupportedEncodingException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Scanner; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.lang3.ArrayUtils; +import org.onap.music.eelf.logging.EELFLoggerDelegate; + +public class CipherUtil { + + + /** + * Default key. + */ + private static String keyString = MusicUtil.getCipherEncKey(); + + private static final String ALGORITHM = "AES"; + private static final String ALGORYTHM_DETAILS = ALGORITHM + "/CBC/PKCS5PADDING"; + private static final int BLOCK_SIZE = 128; + @SuppressWarnings("unused") + private static SecretKeySpec secretKeySpec; + private static IvParameterSpec ivspec; + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(CipherUtil.class); + /** + * @deprecated Please use {@link #encryptPKC(String)} to encrypt the text. + * + * Encrypts the text using the specified secret key. + * + * @param plainText + * Text to encrypt + * @param secretKey + * Key to use for encryption + * @return encrypted version of plain text. + * @ + * if any encryption step fails + * + */ + @Deprecated + public static String encrypt(String plainText, String secretKey) { + String encryptedString = null; + try { + byte[] encryptText = plainText.getBytes("UTF-8"); + byte[] rawKey = Base64.decodeBase64(secretKey); + SecretKeySpec sKeySpec = new SecretKeySpec(rawKey, "AES"); + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.ENCRYPT_MODE, sKeySpec); + encryptedString = Base64.encodeBase64String(cipher.doFinal(encryptText)); + } catch (BadPaddingException | IllegalBlockSizeException | InvalidKeyException | NoSuchAlgorithmException + | NoSuchPaddingException | UnsupportedEncodingException ex) { + } + return encryptedString; + } + + /** + * @deprecated Please use {@link #encryptPKC(String)} to encrypt the text. + * Encrypts the text using the secret key in key.properties file. + * + * @param plainText + * Text to encrypt + * @return Encrypted Text + * @ + * if any decryption step fails + */ + @Deprecated + public static String encrypt(String plainText) { + return CipherUtil.encrypt(plainText, keyString); + } + + /** + * Encrypts the text using a secret key. + * + * @param plainText + * Text to encrypt + * @return Encrypted Text + * @ + * if any decryption step fails + */ + public static String encryptPKC(String plainText) { + return CipherUtil.encryptPKC(plainText, keyString); + } + + /** + * + * @deprecated Please use {@link #decryptPKC(String)} to Decryption the text. + * + * Decrypts the text using the specified secret key. + * + * @param encryptedText + * Text to decrypt + * @param secretKey + * Key to use for decryption + * @return plain text version of encrypted text + * @ + * if any decryption step fails + * + */ + @Deprecated + public static String decrypt(String encryptedText, String secretKey) { + String encryptedString = null; + try { + byte[] rawKey = Base64.decodeBase64(secretKey); + SecretKeySpec sKeySpec = new SecretKeySpec(rawKey, "AES"); + byte[] encryptText = Base64.decodeBase64(encryptedText.getBytes("UTF-8")); + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.DECRYPT_MODE, sKeySpec); + encryptedString = new String(cipher.doFinal(encryptText)); + } catch (BadPaddingException | IllegalBlockSizeException | InvalidKeyException | NoSuchAlgorithmException + | NoSuchPaddingException | UnsupportedEncodingException ex) { + } + return encryptedString; + } + + private static SecretKeySpec getSecretKeySpec() { + byte[] key = Base64.decodeBase64(keyString); + return new SecretKeySpec(key, ALGORITHM); + } + + private static SecretKeySpec getSecretKeySpec(String keyString) { + byte[] key = Base64.decodeBase64(keyString); + return new SecretKeySpec(key, ALGORITHM); + } + + /** + * Encrypt the text using the secret key in key.properties file + * + * @param value + * @return The encrypted string + * @throws BadPaddingException + * @ + * In case of issue with the encryption + */ + public static String encryptPKC(String value, String skey) { + Cipher cipher = null; + byte[] iv = null, finalByte = null; + + try { + cipher = Cipher.getInstance(ALGORYTHM_DETAILS, "SunJCE"); + + SecureRandom r = SecureRandom.getInstance("SHA1PRNG"); + iv = new byte[BLOCK_SIZE / 8]; + r.nextBytes(iv); + ivspec = new IvParameterSpec(iv); + cipher.init(Cipher.ENCRYPT_MODE, getSecretKeySpec(skey), ivspec); + finalByte = cipher.doFinal(value.getBytes()); + + } catch (Exception ex) { + + } + return Base64.encodeBase64String(ArrayUtils.addAll(iv, finalByte)); + } + + /** + * Decrypts the text using the secret key in key.properties file. + * + * @param message + * The encrypted string that must be decrypted using the ecomp + * Encryption Key + * @return The String decrypted + * @ + * if any decryption step fails + */ + public static String decryptPKC(String message, String skey) { + byte[] encryptedMessage = Base64.decodeBase64(message); + Cipher cipher; + byte[] decrypted = null; + try { + cipher = Cipher.getInstance(ALGORYTHM_DETAILS, "SunJCE"); + ivspec = new IvParameterSpec(ArrayUtils.subarray(encryptedMessage, 0, BLOCK_SIZE / 8)); + byte[] realData = ArrayUtils.subarray(encryptedMessage, BLOCK_SIZE / 8, encryptedMessage.length); + cipher.init(Cipher.DECRYPT_MODE, getSecretKeySpec(skey), ivspec); + decrypted = cipher.doFinal(realData); + + } catch (Exception ex) { + + + } + + return new String(decrypted); + } + + /** + * @deprecated Please use {@link #decryptPKC(String)} to Decrypt the text. + * + * Decrypts the text using the secret key in key.properties file. + * + * @param encryptedText + * Text to decrypt + * @return Decrypted text + * @ + * if any decryption step fails + */ + @Deprecated + public static String decrypt(String encryptedText) { + return CipherUtil.decrypt(encryptedText, keyString); + } + + /** + * + * Decrypts the text using the secret key in key.properties file. + * + * @param encryptedText + * Text to decrypt + * @return Decrypted text + * @ + * if any decryption step fails + */ + public static String decryptPKC(String encryptedText) { + return CipherUtil.decryptPKC(encryptedText, keyString); + } + + + public static void readAndSetKeyString() { + try { + Scanner in = new Scanner(new FileReader("/opt/app/music/etc/properties.txt")); + StringBuilder sb = new StringBuilder(); + while(in.hasNext()) { + sb.append(in.next()); + } + in.close(); + keyString = sb.toString(); + } catch (FileNotFoundException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + } + } + + /*public static void main(String[] args) { + + System.out.println("Encrypted password: "+encryptPKC("cassandra")); + + System.out.println("Decrypted password: "+decryptPKC("dDhqAp5/RwZbl9yRSZg15fN7Qul9eiE/JFkKemtTib0=")); + System.out.println("Decrypted password: "+decryptPKC("I/dOtD/YYzBStbtOYhKuUUyPHSW2G9ZzdSyB8bJp4vk=")); + System.out.println("Decrypted password: "+decryptPKC("g7zJqg74dLsH/fyL7I75b4eySy3pbMS2xVqkrB5lDl8=")); + }*/ + +} diff --git a/src/main/java/org/onap/music/main/MusicCore.java b/src/main/java/org/onap/music/main/MusicCore.java index 324f4681..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"); } /** @@ -256,30 +200,14 @@ public class MusicUtil { } /** - * @return the aafEndpointUrl - */ - public static String getAafEndpointUrl() { - return aafEndpointUrl; - } - - /** - * - * @param aafEndpointUrl - */ - public static void setAafEndpointUrl(String aafEndpointUrl) { - MusicUtil.aafEndpointUrl = aafEndpointUrl; - } - - - /** * Returns An array of property names that should be in the Properties * files. * - * @return - */ - public static String[] getPropkeys() { - return propKeys.clone(); - } +// * @return +// */ +// public static String[] getPropkeys() { +// return propKeys.clone(); +// } /** * Get MusicPropertiesFilePath - Default = /opt/music/music.properties @@ -390,24 +318,6 @@ public class MusicUtil { public static void setMyCassaHost(String myCassaHost) { MusicUtil.myCassaHost = myCassaHost; } - - /** - * Get DefaultMusicIp - Default = localhost property file value - music.ip - * - * @return - */ - public static String getDefaultMusicIp() { - return defaultMusicIp; - } - - /** - * Set DefaultMusicIp - * - * @param defaultMusicIp . - */ - public static void setDefaultMusicIp(String defaultMusicIp) { - MusicUtil.defaultMusicIp = defaultMusicIp; - } /** * Gey default retry count @@ -443,9 +353,11 @@ public class MusicUtil { } /** - * . + * This method depricated as its not used or needed. + * * @return String */ + @Deprecated public static String getTestType() { String testType = ""; try { @@ -462,7 +374,9 @@ public class MusicUtil { } /** - * + * Method to do a Thread Sleep. + * Used for adding a delay. + * * @param time */ public static void sleep(long time) { @@ -638,7 +552,7 @@ public class MusicUtil { response.header(XPATCHVERSION,verArray[2]); } response.header(XLATESTVERSION,version); - logger.info(EELFLoggerDelegate.applicationLogger,"Version In:" + versionIn); + logger.info(EELFLoggerDelegate.auditLogger,"Version In:" + versionIn); return response; } @@ -655,29 +569,6 @@ public class MusicUtil { return consistencyName.get(consistency.toUpperCase()); } - public static void setNotifyInterval(int notifyinterval) { - MusicUtil.notifyinterval = notifyinterval; - } - public static void setNotifyTimeOut(int notifytimeout) { - MusicUtil.notifytimeout = notifytimeout; - } - - public static int getNotifyInterval() { - return MusicUtil.notifyinterval; - } - - public static int getNotifyTimeout() { - return MusicUtil.notifytimeout; - } - - public static int getCacheObjectMaxLife() { - return MusicUtil.cacheObjectMaxLife; - } - - public static void setCacheObjectMaxLife(int cacheObjectMaxLife) { - MusicUtil.cacheObjectMaxLife = cacheObjectMaxLife; - } - /** * Given the time of write for an update in a critical section, this method provides a transformed timestamp * that ensures that a previous lock holder who is still alive can never corrupt a later critical section. @@ -839,67 +730,89 @@ public class MusicUtil { } /** - * @return the transIdRequired - */ - public static String getTransIdRequired() { - return transIdRequired; - } - - - /** - * @param transIdRequired the transIdRequired to set - */ - public static void setTransIdRequired(String transIdRequired) { - MusicUtil.transIdRequired = transIdRequired; - } - - - /** - * @return the conversationIdRequired - */ - public static String getConversationIdRequired() { - return conversationIdRequired; - } - - - /** - * @param conversationIdRequired the conversationIdRequired to set - */ - public static void setConversationIdRequired(String conversationIdRequired) { - MusicUtil.conversationIdRequired = conversationIdRequired; - } - - - /** - * @return the clientIdRequired - */ - public static String getClientIdRequired() { - return clientIdRequired; - } - - - /** - * @param clientIdRequired the clientIdRequired to set - */ - public static void setClientIdRequired(String clientIdRequired) { - MusicUtil.clientIdRequired = clientIdRequired; - } - - - /** - * @return the messageIdRequired - */ - public static String getMessageIdRequired() { - return messageIdRequired; - } - - - /** - * @param messageIdRequired the messageIdRequired to set - */ - public static void setMessageIdRequired(String messageIdRequired) { - MusicUtil.messageIdRequired = messageIdRequired; - } + * @return the transIdRequired + */ + public static Boolean getTransIdRequired() { + return transIdRequired; + } + + + /** + * @param transIdRequired the transIdRequired to set + */ + public static void setTransIdRequired(Boolean transIdRequired) { + MusicUtil.transIdRequired = transIdRequired; + } + + + /** + * @return the conversationIdRequired + */ + public static Boolean getConversationIdRequired() { + return conversationIdRequired; + } + + + /** + * @param conversationIdRequired the conversationIdRequired to set + */ + public static void setConversationIdRequired(Boolean conversationIdRequired) { + MusicUtil.conversationIdRequired = conversationIdRequired; + } + + + /** + * @return the clientIdRequired + */ + public static Boolean getClientIdRequired() { + return clientIdRequired; + } + + + /** + * @param clientIdRequired the clientIdRequired to set + */ + public static void setClientIdRequired(Boolean clientIdRequired) { + MusicUtil.clientIdRequired = clientIdRequired; + } + + + /** + * @return the messageIdRequired + */ + public static Boolean getMessageIdRequired() { + return messageIdRequired; + } + + /** + * @param messageIdRequired the messageIdRequired to set + */ + public static void setMessageIdRequired(Boolean messageIdRequired) { + MusicUtil.messageIdRequired = messageIdRequired; + } + + + public static String getCipherEncKey() { + return MusicUtil.cipherEncKey; + } + + + public static void setCipherEncKey(String cipherEncKey) { + MusicUtil.cipherEncKey = cipherEncKey; + if ( null == cipherEncKey || cipherEncKey.equals("") || + cipherEncKey.equals("nothing to see here")) { + logger.error(EELFLoggerDelegate.errorLogger, "Missing Cipher Encryption Key."); + } + } + + public static String getMusicAafNs() { + return MusicUtil.musicAafNs; + } + + + public static void setMusicAafNs(String musicAafNs) { + MusicUtil.musicAafNs = musicAafNs; + } diff --git a/src/main/java/org/onap/music/main/PropertiesLoader.java b/src/main/java/org/onap/music/main/PropertiesLoader.java index c20ce5c5..f99650ae 100644 --- a/src/main/java/org/onap/music/main/PropertiesLoader.java +++ b/src/main/java/org/onap/music/main/PropertiesLoader.java @@ -22,9 +22,6 @@ package org.onap.music.main; -import java.util.ArrayList; -import java.util.Arrays; - import org.onap.music.eelf.logging.EELFLoggerDelegate; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Value; @@ -33,7 +30,7 @@ import org.springframework.context.annotation.PropertySource; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.stereotype.Component; -@PropertySource(value = {"file:/opt/app/music/etc/music.properties", "classpath:/project.properties"}) +@PropertySource(value = {"file:/opt/app/music/etc/music.properties", "classpath:/project.properties","file:/opt/app/music/etc/key.properties"}) @Component public class PropertiesLoader implements InitializingBean { @@ -64,33 +61,9 @@ public class PropertiesLoader implements InitializingBean { @Value("${cassandra.password}") public String cassandraPassword; - @Value("${aaf.endpoint.url}") - public String aafEndpointUrl; - - @Value("${admin.username}") - public String adminUsername; - - @Value("${admin.password}") - public String adminPassword; - @Value("${cassandra.port}") public String cassandraPort; - @Value("${aaf.admin.url}") - public String aafAdminUrl; - - @Value("${music.namespace}") - public String musicNamespace; - - @Value("${admin.aaf.role}") - public String adminAafRole; - - @Value("${notify.interval}") - public String notifyInterval; - - @Value("${notify.timeout}") - public String notifyTimeout; - @Value("${cadi}") public String isCadi; @@ -113,16 +86,22 @@ public class PropertiesLoader implements InitializingBean { private String messageIdPrefix; @Value("${transId.header.required}") - private String transIdRequired; + private Boolean transIdRequired; @Value("${conversation.header.required}") - private String conversationIdRequired; + private Boolean conversationIdRequired; @Value("${clientId.header.required}") - private String clientIdRequired; + private Boolean clientIdRequired; @Value("${messageId.header.required}") - private String messageIdRequired; + private Boolean messageIdRequired; + + @Value("${music.aaf.ns}") + private String musicAafNs; + + @Value("${cipher.enc.key}") + private String cipherEncKey; private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(PropertiesLoader.class); @@ -139,20 +118,11 @@ public class PropertiesLoader implements InitializingBean { * . */ public void loadProperties() { - if (aafAdminUrl != null && !aafAdminUrl.equals("${aaf.admin.url}")) { - MusicUtil.setAafAdminUrl(aafAdminUrl); + if(cipherEncKey != null) { + MusicUtil.setCipherEncKey(cipherEncKey); } - if (aafEndpointUrl != null && !aafEndpointUrl.equals("${aaf.endpoint.url}")) { - MusicUtil.setAafEndpointUrl(aafEndpointUrl); - } - if (adminAafRole != null && !adminAafRole.equals("${admin.aaf.role}")) { - MusicUtil.setAdminAafRole(adminAafRole); - } - if (adminPassword != null && !adminPassword.equals("${admin.password}")) { - MusicUtil.setAdminPass(adminPassword); - } - if (adminUsername != null && !adminUsername.equals("${admin.username}")) { - MusicUtil.setAdminId(adminUsername); + if (musicAafNs != null) { + MusicUtil.setMusicAafNs(musicAafNs); } if (cassandraPort != null && !cassandraPort.equals("${cassandra.port}")) { MusicUtil.setCassandraPort(Integer.parseInt(cassandraPort)); @@ -169,24 +139,12 @@ public class PropertiesLoader implements InitializingBean { if (lockLeasePeriod != null && !lockLeasePeriod.equals("${lock.lease.period}")) { MusicUtil.setDefaultLockLeasePeriod(Long.parseLong(lockLeasePeriod)); } - if (musicIp != null && !musicIp.equals("${music.ip}")) { - MusicUtil.setDefaultMusicIp(musicIp); - } - if (musicNamespace != null && !musicNamespace.equals("${music.namespace}")) { - MusicUtil.setMusicNamespace(musicNamespace); - } if (musicProperties != null && !musicProperties.equals("${music.properties}")) { MusicUtil.setMusicPropertiesFilePath(musicProperties); } if (cassandraHost != null && !cassandraHost.equals("${cassandra.host}")) { MusicUtil.setMyCassaHost(cassandraHost); } - if (notifyInterval != null && !notifyInterval.equals("${notify.interval}")) { - MusicUtil.setNotifyInterval(Integer.parseInt(notifyInterval)); - } - if (notifyTimeout != null && !notifyTimeout.equals("${notify.timeout}")) { - MusicUtil.setNotifyTimeOut(Integer.parseInt(notifyTimeout)); - } if (version != null && !version.equals("${version}")) { MusicUtil.setVersion(version); } @@ -202,8 +160,6 @@ public class PropertiesLoader implements InitializingBean { if (isKeyspaceActive != null && !isKeyspaceActive.equals("${keyspace.active}")) { MusicUtil.setKeyspaceActive(Boolean.parseBoolean(isKeyspaceActive)); } - - if(transIdPrefix!=null) { MusicUtil.setTransIdPrefix(transIdPrefix); } @@ -236,6 +192,8 @@ public class PropertiesLoader implements InitializingBean { MusicUtil.setMessageIdRequired(messageIdRequired); } } + + @Override diff --git a/src/main/java/org/onap/music/response/jsonobjects/JsonResponse.java b/src/main/java/org/onap/music/response/jsonobjects/JsonResponse.java index 2c419e18..f0793dc2 100644 --- a/src/main/java/org/onap/music/response/jsonobjects/JsonResponse.java +++ b/src/main/java/org/onap/music/response/jsonobjects/JsonResponse.java @@ -56,9 +56,19 @@ public class JsonResponse { private LockStatus lockStatus; private List<String> lockHolders; private String lockLease; + private boolean isLockHolders=false; - /** + public boolean isLockHolders() { + return isLockHolders; + } + + public JsonResponse setisLockHolders(boolean isLockHolders) { + this.isLockHolders = isLockHolders; + return this; + } + + /** * Create a JSONLock Response * Use setters to provide more information as in * JsonLockResponse(ResultType.SUCCESS).setMessage("We did it").setLock(mylockname) @@ -282,7 +292,7 @@ public class JsonResponse { lockMap.put("lock-status", lockStatus); } if (lockHolders != null && !lockHolders.isEmpty()) { - if (lockHolders.size()==1) { + if (lockHolders.size()==1 && !isLockHolders) { //for backwards compatability lockMap.put("lock-holder", lockHolders.get(0)); } else { diff --git a/src/main/java/org/onap/music/rest/RestMusicDataAPI.java b/src/main/java/org/onap/music/rest/RestMusicDataAPI.java index 219e713c..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 <keyspace> Created\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"<errorMessage>\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response createKeySpace( @ApiParam(value = "Major Version",required = true) @PathParam("version") String version, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @@ -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 <keyspace> Deleted\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"<errorMessage>\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response dropKeySpace( @ApiParam(value = "Major Version",required = true) @PathParam("version") String version, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @@ -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 <tablename> Created under keyspace <keyspace>\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"<errorMessage>\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response createTable( @ApiParam(value = "Major Version",required = true) @PathParam("version") String version, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "AID", required = false,hidden = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam(NS) String ns, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, JsonTable tableObj, @@ -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 <keyspace>.<table>.<field>\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"<errorMessage>\"," + + "\"status\" : \"FAILURE\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Unknown Error in create index.\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response createIndex( @ApiParam(value = "Major Version",required = true) @PathParam("version") String version, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid, - @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam(NS) String ns, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, @ApiParam(value = "Keyspace Name",required = true) @PathParam("keyspace") String keyspace, @ApiParam(value = "Table Name",required = true) @PathParam("tablename") String tablename, @@ -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\" : \"<errorMessage>\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response insertIntoTable( @ApiParam(value = "Major Version",required = true) @PathParam("version") String version, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @@ -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\" : \"<errorMessage>\"," + + "\"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\" : \"<errorMessage>\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response selectCritical( @ApiParam(value = "Major Version", - required = true) @PathParam("version") String version, - @ApiParam(value = "Minor Version", + required = true) @PathParam("version") String version, + @ApiParam(value = "Minor Version",example = "0", required = false) @HeaderParam(XMINORVERSION) String minorVersion, - @ApiParam(value = "Patch Version", + @ApiParam(value = "Patch Version",example = "0", required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", @@ -1205,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\" : \"<errorMessage>\"," + + "\"status\" : \"FAILURE\"}") + })) + }) + public Response selectWithCritical( + @ApiParam(value = "Major Version",example = "v2", required = true) @PathParam("version") String version, - @ApiParam(value = "Minor Version", + @ApiParam(value = "Minor Version",example = "1", required = false) @HeaderParam(XMINORVERSION) String minorVersion, - @ApiParam(value = "Patch Version", + @ApiParam(value = "Patch Version",example = "0", required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", required = false,hidden = true) @HeaderParam(NS) String ns, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "Keyspace Name", - required = true) @PathParam("keyspace") String keyspace, - @ApiParam(value = "Table Name", - required = true) @PathParam("tablename") String tablename, + JsonInsert selObj, + @ApiParam(value = "Keyspace Name", required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Table Name", required = true) @PathParam("tablename") String tablename, @Context UriInfo info) throws Exception { + if ((minorVersion != null && patchVersion != null) && + (Integer.parseInt(minorVersion) == 1 && Integer.parseInt(patchVersion) == 0) && + (!(null == selObj) && !selObj.getConsistencyInfo().isEmpty())) { + return selectCritical(version, minorVersion, patchVersion, aid, ns, authorization, selObj, keyspace, tablename, info); + } else { + return select(version, minorVersion, patchVersion, aid, ns, authorization, keyspace, tablename, info); + } + } + + /** + * + * @param keyspace + * @param tablename + * @param info + * @return + * @throws Exception + */ + private Response select( + String version,String minorVersion,String patchVersion, + String aid,String ns,String authorization,String keyspace, + String tablename,UriInfo info) throws Exception { try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){ 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<String, Object> 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$<integer>\"}," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Unable to aquire lock\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response createLockReference( @ApiParam(value="Lock Name",required=true) @PathParam("lockname") String lockName, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, JsonLock lockObject, @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map<String, Object> resultMap = MusicCore.validateLock(lockName); @@ -138,19 +160,32 @@ public class RestMusicLocksAPI { * @throws Exception */ @GET - @Path("/acquire/{lockreference}") - @ApiOperation(value = "Aquire Lock", + @Path("/acquire/{lockId}") + @ApiOperation(value = "Aquire Lock Id ", notes = "Checks if the node is in the top of the queue and hence acquires the lock", response = Map.class) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"lock\" : {\"lock\" : \"$keyspace.table.rowId$<integer>\"}," + + "\"message\" : \"<integer> is the lock holder for the key\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Unable to aquire lock\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response accquireLock( - @ApiParam(value="Lock Reference",required=true) @PathParam("lockreference") String lockId, + @ApiParam(value="Lock Id",required=true) @PathParam("lockId") String lockId, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map<String, Object> resultMap = MusicCore.validateLock(lockId); @@ -182,21 +217,40 @@ public class RestMusicLocksAPI { } - - @POST - @Path("/acquire-with-lease/{lockreference}") - @ApiOperation(value = "Aquire Lock with Lease", response = Map.class) + @Path("/acquire-with-lease/{lockId}") + @ApiOperation( + hidden = false, + value = " ** DEPRECATED ** - Aquire Lock with Lease", + notes = "Acquire the lock with a lease, where lease period is in Milliseconds.\n" + + "This will ensure that a lock will expire in set milliseconds.\n" + + "This is no longer available after v3.2.0", + response = Map.class) @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - public Response accquireLockWithLease(JsonLeasedLock lockObj, - @ApiParam(value="Lock Reference",required=true) @PathParam("lockreference") String lockId, - @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, - @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, - @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"lock\" : {\"lock\" : \"$keyspace.table.rowId$<integer>\"," + + "\"lock-lease\" : \"6000\"}," + + "\"message\" : \"<integer> is the lock holder for the key\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Unable to aquire lock\"," + + "\"status\" : \"FAILURE\"}") + })) + }) + @Deprecated + public Response accquireLockWithLease( + JsonLeasedLock lockObj, + @ApiParam(value="Lock Id",required=true) @PathParam("lockId") String lockId, + @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, + @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, + @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map<String, Object> resultMap = MusicCore.validateLock(lockId); @@ -220,6 +274,8 @@ public class RestMusicLocksAPI { } finally { EELFLoggerDelegate.mdcRemove("keyspace"); } + + } @@ -229,14 +285,27 @@ public class RestMusicLocksAPI { notes = "Gets the current single lockholder at top of lock queue", response = Map.class) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"lock\" : {\"lock\" : \"keyspace.table.rowId\"," + + "\"lock-holder\" : \"$tomtest.employees.tom$<integer>\"}}," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Error Message\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response enquireLock( @ApiParam(value="Lock Name",required=true) @PathParam("lockname") String lockName, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map<String, Object> resultMap = MusicCore.validateLock(lockName); @@ -265,16 +334,30 @@ public class RestMusicLocksAPI { @GET @Path("/holders/{lockname}") @ApiOperation(value = "Get Lock Holders", - notes = "Gets the current Lock Holders", + notes = "Gets the current Lock Holders.\n" + + "Will return an array of READ Lock References.", response = Map.class) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"lock\" : {\"lock\" : \"keyspace.table.rowId\"," + + "\"lock-holder\" : [\"$keyspace.table.rowId$<integer1>\",\"$keyspace.table.rowId$<integer2>\"]}}," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Error message\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response currentLockHolder(@ApiParam(value="Lock Name",required=true) @PathParam("lockname") String lockName, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map<String, Object> resultMap = MusicCore.validateLock(lockName); @@ -290,9 +373,9 @@ public class RestMusicLocksAPI { List<String> who = MusicCore.getCurrentLockHolders(lockName); ResultType status = ResultType.SUCCESS; String error = ""; - if (who == null) { + if (who == null || who.isEmpty()) { status = ResultType.FAILURE; - error = "There was a problem getting the lock holder"; + error = (who !=null && who.isEmpty()) ? "No lock holders for the key":"There was a problem getting the lock holder"; logger.error(EELFLoggerDelegate.errorLogger, "There was a problem getting the lock holder", AppMessages.INCORRECTDATA, ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); return response.status(Status.BAD_REQUEST) @@ -300,8 +383,8 @@ public class RestMusicLocksAPI { .build(); } return response.status(Status.OK) - .entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).toMap()) - .build(); + .entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).setisLockHolders(true).toMap()) + .build(); } finally { EELFLoggerDelegate.mdcRemove("keyspace"); } @@ -312,16 +395,29 @@ public class RestMusicLocksAPI { @Path("/{lockname}") @ApiOperation(value = "Lock State", notes = "Returns current Lock State and Holder.", - response = Map.class) + response = Map.class,hidden = true) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"lock\" : {\"lock\" : \"$keyspace.table.rowId$<integer>\"}," + + "\"message\" : \"<integer> is the lock holder for the key\"," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Unable to aquire lock\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response currentLockState( @ApiParam(value="Lock Name",required=true) @PathParam("lockname") String lockName, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map<String, Object> resultMap = MusicCore.validateLock(lockName); @@ -358,16 +454,29 @@ public class RestMusicLocksAPI { @DELETE @Path("/release/{lockreference}") @ApiOperation(value = "Release Lock", - notes = "deletes the process from the lock queue", + notes = "Releases the lock from the lock queue.", response = Map.class) @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success - UNLOCKED = Lock Removed.",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"lock\" : {\"lock\" : \"$keyspace.table.rowId$<integer>\"}," + + "\"lock-status\" : \"UNLOCKED\"}," + + "\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Unable to aquire lock\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response unLock(@PathParam("lockreference") String lockId, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map<String, Object> resultMap = MusicCore.validateLock(lockId); @@ -409,17 +518,32 @@ public class RestMusicLocksAPI { * @param lockName * @throws Exception */ + @Deprecated @DELETE @Path("/delete/{lockname}") - @ApiOperation(value = "Delete Lock", response = Map.class) + @ApiOperation( + hidden = true, + value = "-DEPRECATED- Delete Lock", response = Map.class, + notes = "-DEPRECATED- Delete the lock.") @Produces(MediaType.APPLICATION_JSON) + @ApiResponses(value={ + @ApiResponse(code=200, message = "Success",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"status\" : \"SUCCESS\"}") + })), + @ApiResponse(code=400, message = "Failure",examples = @Example( value = { + @ExampleProperty(mediaType="application/json",value = + "{\"error\" : \"Error Message if any\"," + + "\"status\" : \"FAILURE\"}") + })) + }) public Response deleteLock(@PathParam("lockname") String lockName, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid, @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns) throws Exception{ + required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{ try { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); Map<String, Object> resultMap = MusicCore.validateLock(lockName); diff --git a/src/main/java/org/onap/music/rest/RestMusicQAPI.java b/src/main/java/org/onap/music/rest/RestMusicQAPI.java index 768f1a44..4def0e45 100755 --- a/src/main/java/org/onap/music/rest/RestMusicQAPI.java +++ b/src/main/java/org/onap/music/rest/RestMusicQAPI.java @@ -25,7 +25,6 @@ package org.onap.music.rest; -import java.util.HashMap; import java.util.Map; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; @@ -67,7 +66,7 @@ import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; @Path("/v2/priorityq/") -@Api(value = "Q Api") +@Api(value = "Q Api",hidden = true) public class RestMusicQAPI { private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicQAPI.class); @@ -95,7 +94,7 @@ public class RestMusicQAPI { @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, JsonTable tableObj, @ApiParam(value = "Key Space", required = true) @PathParam("keyspace") String keyspace, - @ApiParam(value = "Table Name", required = true) @PathParam("qname") String tablename) throws Exception { + @ApiParam(value = "Table Name", required = true) @PathParam("qname") String tablename) throws Exception { ResponseBuilder response = MusicUtil.buildVersionResponse(version, minorVersion, patchVersion); Map<String, String> fields = tableObj.getFields(); @@ -409,7 +408,7 @@ public class RestMusicQAPI { @ApiParam(value = "Table Name", required = true) @PathParam("qname") String tablename, @Context UriInfo info) throws Exception { - return new RestMusicDataAPI().select(version, minorVersion, patchVersion, aid, ns, authorization, keyspace, tablename, info);// , limit) + return new RestMusicDataAPI().selectWithCritical(version, minorVersion, patchVersion, aid, ns, authorization,null, keyspace, tablename, info);// , limit) } diff --git a/src/main/java/org/onap/music/rest/RestMusicTestAPI.java b/src/main/java/org/onap/music/rest/RestMusicTestAPI.java index 6d973acb..c1c04b09 100644 --- a/src/main/java/org/onap/music/rest/RestMusicTestAPI.java +++ b/src/main/java/org/onap/music/rest/RestMusicTestAPI.java @@ -51,6 +51,7 @@ public class RestMusicTestAPI { * @return */ @GET + @Path("/") @ApiOperation(value = "Get Test", response = Map.class) @Produces(MediaType.APPLICATION_JSON) public Map<String, HashMap<String, String>> simpleTests( @@ -60,6 +61,7 @@ public class RestMusicTestAPI { for(int i=0; i < 3; i++){ HashMap<String, String> innerMap = new HashMap<>(); innerMap.put("Music Version",MusicUtil.getVersion()); + innerMap.put("Music Build",MusicUtil.getBuild()); innerMap.put(i+1+"", i+2+""); testMap.put(i+"", innerMap); } diff --git a/src/main/java/org/onap/music/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; } |