From 66aac8e2b8f61f075b285f969c1f8a88fdb313bd Mon Sep 17 00:00:00 2001 From: "Nelson, Thomas (arthurdent3)" Date: Tue, 14 May 2019 20:23:59 +0000 Subject: CADI and a few small updates. - Include CADI and remove Admin API and admin code. - A few Sonar Fixes. - Properties File Clean up. - Read/Write Locking API. - Various whitespace fixes. Issue-ID: MUSIC-394 Change-Id: I58e1b64b71796bb6bda1c97ea688f434a836d3c7 Signed-off-by: Nelson, Thomas (arthurdent3) --- pom.xml | 15 +- postman/MusicLocal.postman_collection.json | 2 +- src/main/java/org/onap/music/JerseyConfig.java | 4 +- src/main/java/org/onap/music/MusicApplication.java | 139 +- .../org/onap/music/authentication/AuthUtil.java | 270 ++++ .../music/authentication/AuthorizationError.java | 55 + .../org/onap/music/authentication/CachingUtil.java | 452 ------ .../onap/music/authentication/CadiAuthFilter.java | 90 +- .../authentication/MusicAAFAuthentication.java | 181 --- .../music/authentication/MusicAuthenticator.java | 62 - .../authentication/MusicAuthorizationFilter.java | 170 +++ .../conditionals/RestMusicConditionalAPI.java | 124 +- .../java/org/onap/music/datastore/Condition.java | 4 +- .../org/onap/music/datastore/MusicDataStore.java | 1 - .../onap/music/datastore/MusicDataStoreHandle.java | 2 +- .../music/datastore/jsonobjects/JsonDelete.java | 3 +- .../datastore/jsonobjects/JsonLeasedLock.java | 4 +- .../onap/music/datastore/jsonobjects/JsonLock.java | 45 + .../music/eelf/healthcheck/MusicHealthCheck.java | 2 +- .../music/eelf/logging/MusicContainerFilter.java | 70 + .../eelf/logging/MusicLoggingServletFilter.java | 205 +++ .../lockingservice/cassandra/CassaLockStore.java | 300 +++- .../music/lockingservice/cassandra/LockType.java | 30 + .../lockingservice/cassandra/MusicLockState.java | 9 +- src/main/java/org/onap/music/main/MusicCore.java | 105 +- src/main/java/org/onap/music/main/MusicUtil.java | 256 ++-- .../java/org/onap/music/main/PropertiesLoader.java | 94 +- .../music/response/jsonobjects/JsonResponse.java | 26 +- .../org/onap/music/rest/RestMusicAdminAPI.java | 635 --------- .../java/org/onap/music/rest/RestMusicDataAPI.java | 1437 +++++++++----------- .../org/onap/music/rest/RestMusicLocksAPI.java | 427 +++--- .../java/org/onap/music/rest/RestMusicQAPI.java | 12 +- .../org/onap/music/service/MusicCoreService.java | 28 + .../onap/music/service/impl/MusicCassaCore.java | 347 ++--- src/main/resources/logback.xml | 2 +- .../org/onap/music/unittests/JsonResponseTest.java | 17 + .../onap/music/unittests/MusicDataStoreTest.java | 3 +- .../org/onap/music/unittests/MusicUtilTest.java | 42 - .../onap/music/unittests/TestRestMusicQAPI.java | 85 +- .../onap/music/unittests/TestsUsingCassandra.java | 111 +- .../org/onap/music/unittests/TstCachingUtil.java | 167 --- .../onap/music/unittests/TstRestMusicAdminAPI.java | 464 ------- .../unittests/TstRestMusicConditionalAPI.java | 3 - .../onap/music/unittests/TstRestMusicDataAPI.java | 240 ---- .../onap/music/unittests/TstRestMusicLockAPI.java | 612 ++++----- version.properties | 2 +- 46 files changed, 3018 insertions(+), 4336 deletions(-) create mode 100644 src/main/java/org/onap/music/authentication/AuthUtil.java create mode 100644 src/main/java/org/onap/music/authentication/AuthorizationError.java delete mode 100755 src/main/java/org/onap/music/authentication/CachingUtil.java delete mode 100644 src/main/java/org/onap/music/authentication/MusicAAFAuthentication.java delete mode 100644 src/main/java/org/onap/music/authentication/MusicAuthenticator.java create mode 100644 src/main/java/org/onap/music/authentication/MusicAuthorizationFilter.java create mode 100644 src/main/java/org/onap/music/datastore/jsonobjects/JsonLock.java create mode 100644 src/main/java/org/onap/music/eelf/logging/MusicContainerFilter.java create mode 100644 src/main/java/org/onap/music/eelf/logging/MusicLoggingServletFilter.java create mode 100644 src/main/java/org/onap/music/lockingservice/cassandra/LockType.java delete mode 100755 src/main/java/org/onap/music/rest/RestMusicAdminAPI.java delete mode 100644 src/test/java/org/onap/music/unittests/TstCachingUtil.java delete mode 100644 src/test/java/org/onap/music/unittests/TstRestMusicAdminAPI.java diff --git a/pom.xml b/pom.xml index 2226faf0..c575a64d 100755 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ org.onap.music MUSIC jar - 3.2.28-SNAPSHOT + 3.2.29-SNAPSHOT This is the MUSIC REST interface, packaged as a Springboot jar file. @@ -218,7 +218,7 @@ - + org.springframework.boot spring-boot-starter @@ -230,6 +230,10 @@ org.springframework.boot spring-boot-starter-jersey + + org.springframework.boot + spring-boot-starter-web + org.springframework.boot spring-boot-starter-tomcat @@ -685,6 +689,13 @@ default + + + nexus + attarch-releases + http://mavencentral.it.att.com:8084/nexus/content/repositories/attarch-releases + + diff --git a/postman/MusicLocal.postman_collection.json b/postman/MusicLocal.postman_collection.json index bfbc8aac..19597e15 100644 --- a/postman/MusicLocal.postman_collection.json +++ b/postman/MusicLocal.postman_collection.json @@ -439,7 +439,7 @@ "description": "", "collectionId": "a7ff2cf7-0a5a-1b0b-a393-829a672c80d6", "responses": [], - "rawModeData": "{\n \"values\": {\n \"emp_id\": \"cfd66ccc-d857-4e90-b1e5-df98a3d40cd6\",\n \"emp_name\": \"bharath\",\n \"emp_salary\": 50,\n \"address\":{ \"street\" : \"att way\", \"city\" : \"bedminster\" }\n },\n \"consistencyInfo\": {\n \"type\": \"atomic\",\n \"lockId\": \"$testks.employees$x-95351186188533762-0000000000\"\n }\n}" + "rawModeData": "{\n \"values\": {\n \"emp_id\": \"cfd66ccc-d857-4e90-b1e5-df98a3d40cd6\",\n \"emp_name\": \"bharath\",\n \"emp_salary\": 50,\n \"address\":{ \"street\" : \"Smith Way\", \"city\" : \"Bedminster\" }\n },\n \"consistencyInfo\": {\n \"type\": \"atomic\",\n \"lockId\": \"$testks.employees$x-95351186188533762-0000000000\"\n }\n}" }, { "id": "b667b219-8eec-2267-1994-7f0fb97b77ce", diff --git a/src/main/java/org/onap/music/JerseyConfig.java b/src/main/java/org/onap/music/JerseyConfig.java index bc394f69..fbf71f3a 100755 --- a/src/main/java/org/onap/music/JerseyConfig.java +++ b/src/main/java/org/onap/music/JerseyConfig.java @@ -25,7 +25,6 @@ import javax.annotation.PostConstruct; import org.glassfish.jersey.server.ResourceConfig; import org.onap.music.conductor.conditionals.RestMusicConditionalAPI; import org.onap.music.exceptions.MusicExceptionMapper; -import org.onap.music.rest.RestMusicAdminAPI; import org.onap.music.rest.RestMusicDataAPI; import org.onap.music.rest.RestMusicHealthCheckAPI; import org.onap.music.rest.RestMusicLocksAPI; @@ -52,7 +51,6 @@ public class JerseyConfig extends ResourceConfig { } private void registerEndpoints() { - register(RestMusicAdminAPI.class); register(RestMusicDataAPI.class); register(RestMusicLocksAPI.class); register(RestMusicConditionalAPI.class); @@ -60,7 +58,7 @@ public class JerseyConfig extends ResourceConfig { register(RestMusicTestAPI.class); register(RestMusicVersionAPI.class); register(RestMusicHealthCheckAPI.class); - + } private void configureSwagger() { diff --git a/src/main/java/org/onap/music/MusicApplication.java b/src/main/java/org/onap/music/MusicApplication.java index e6fee58f..8f5f773e 100755 --- a/src/main/java/org/onap/music/MusicApplication.java +++ b/src/main/java/org/onap/music/MusicApplication.java @@ -22,7 +22,6 @@ package org.onap.music; - import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.ServletException; @@ -31,6 +30,9 @@ import javax.servlet.ServletResponse; import org.onap.aaf.cadi.PropAccess; 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.MusicUtil; import org.onap.music.main.PropertiesLoader; import org.springframework.beans.factory.annotation.Autowired; @@ -49,31 +51,29 @@ 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"}) -@EnableAutoConfiguration(exclude={CassandraDataAutoConfiguration.class}) -@ComponentScan(value = {"org.onap.music"}) +@SpringBootApplication(scanBasePackages = { "org.onap.music.rest" }) +@EnableAutoConfiguration(exclude = { CassandraDataAutoConfiguration.class }) +@ComponentScan(value = { "org.onap.music" }) @EnableScheduling public class MusicApplication extends SpringBootServletInitializer { @Autowired - PropertiesLoader propertyLoader; - - + private PropertiesLoader propertyLoader; + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicApplication.class); + public static void main(String[] args) { - System.setProperty("AFT_DME2_CLIENT_IGNORE_SSL_CONFIG","false"); - System.setProperty("AFT_DME2_CLIENT_KEYSTORE","/opt/app/music/etc/truststore2018.jks"); - System.setProperty("AFT_DME2_CLIENT_KEYSTORE_PASSWORD","changeit"); - System.setProperty("AFT_DME2_CLIENT_SSL_INCLUDE_PROTOCOLS","TLSv1.1,TLSv1.2"); + 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); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { - + return application.sources(MusicApplication.class); } - @Bean("loadProperties") public void loadProperties() { @@ -82,57 +82,132 @@ public class MusicApplication extends SpringBootServletInitializer { @Autowired private ApplicationContext appContext; - + @Bean @DependsOn("loadProperties") public PropAccess propAccess() { - if(MusicUtil.getIsCadi()) - return new PropAccess(new String[] { "cadi_prop_files=/opt/app/music/etc/cadi.properties" }); - else + if (MusicUtil.getIsCadi()) { + return new PropAccess(new String[] { + "cadi_prop_files=/opt/app/music/etc/cadi.properties" }); + } else { return null; + } } - + @Bean(name = "cadiFilter") @DependsOn("loadProperties") public Filter cadiFilter() throws ServletException { propertyLoader.loadProperties(); - if(MusicUtil.getIsCadi()) { + if (MusicUtil.getIsCadi()) { PropAccess propAccess = propAccess(); CadiAuthFilter cadiFilter = new CadiAuthFilter(propAccess); + return cadiFilter; - } else + } else { return (ServletRequest request, ServletResponse response, FilterChain chain) -> { - //do nothing for now. + // do nothing for now. }; - + } + } + + /** + * Added for capturing custom header values from client. + * + * order is set to 1 for this filter + * + * sp931a + * + * @return + * @throws ServletException + */ + @Bean(name="logFilter") + @DependsOn("loadProperties") + public FilterRegistrationBean loggingFilterRegistration() throws ServletException { + logger.info("loggingFilterRegistration called for log filter.."); + propertyLoader.loadProperties(); + FilterRegistrationBean frb = new FilterRegistrationBean<>(); + frb.setFilter(new MusicLoggingServletFilter()); + frb.addUrlPatterns( + "/v2/keyspaces/*", + "/v2/locks/*", + "/v2/priorityq/*" + ); + frb.setName("logFilter"); + frb.setOrder(1); + return frb; } + @Bean @DependsOn("loadProperties") public FilterRegistrationBean cadiFilterRegistration() throws ServletException { + logger.info("cadiFilterRegistration called for cadi filter.."); FilterRegistrationBean frb = new FilterRegistrationBean<>(); frb.setFilter(cadiFilter()); + // The Following Patterns are used to control what APIs will be secure // TODO: Make this a configurable item. Build this from an array? - if(MusicUtil.getIsCadi()) { + if (MusicUtil.getIsCadi()) { frb.addUrlPatterns( - "/v2/keyspaces/*", - "/v2/locks/*", - "/v3/locks/*", - "/v2/priorityq/*", - "/v2/admin/*" - ); + "/v2/keyspaces/*", + "/v2/locks/*", + "/v2/priorityq/*" + ); } else { frb.addUrlPatterns("/v0/test"); } frb.setName("cadiFilter"); - frb.setOrder(0); + frb.setOrder(2); return frb; } + + /** + * Added for Authorization using CADI + * + * sp931a + * + * @return + * @throws ServletException + */ + @Bean + @DependsOn("loadProperties") + public FilterRegistrationBean cadiFilterRegistrationForAuth() throws ServletException { + logger.info("cadiFilterRegistrationForAuth called for cadi auth filter.."); + FilterRegistrationBean frb = new FilterRegistrationBean<>(); + frb.setFilter(cadiMusicAuthFilter()); + + if (MusicUtil.getIsCadi()) { + frb.addUrlPatterns( + "/v2/keyspaces/*", + "/v2/locks/*", + "/v2/priorityq/*" + ); + } else { + frb.addUrlPatterns("/v0/test"); + } + frb.setName("cadiMusicAuthFilter"); + frb.setOrder(3); + return frb; + } + + @Bean(name = "cadiMusicAuthFilter") + @DependsOn("loadProperties") + public Filter cadiMusicAuthFilter() throws ServletException { + propertyLoader.loadProperties(); + if (MusicUtil.getIsCadi()) { + MusicAuthorizationFilter authFilter = new MusicAuthorizationFilter(); + return authFilter; + } else { + return (ServletRequest request, ServletResponse response, FilterChain chain) -> { + // do nothing for now. + }; + } + } + @Bean @ConditionalOnMissingBean(RequestContextListener.class) 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 new file mode 100644 index 00000000..999acc75 --- /dev/null +++ b/src/main/java/org/onap/music/authentication/AuthUtil.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.authentication; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Pattern; + +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Hex; +import org.onap.aaf.cadi.CadiWrap; +import org.onap.aaf.cadi.Permission; +import org.onap.aaf.cadi.aaf.AAFPermission; +import org.onap.music.eelf.logging.EELFLoggerDelegate; + +public class AuthUtil { + + private static final String decodeValueOfForwardSlash = "2f"; + private static final String decodeValueOfHyphen = "2d"; + private static final String decodeValueOfAsterisk = "2a"; + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AuthUtil.class); + + /** + * Get the list of permissions from the Request object. + * + * + * @param request servlet request object + * @return returns list of AAFPermission of the requested MechId for all the + * namespaces + */ + public static List getAAFPermissions(ServletRequest request) { + CadiWrap wrapReq = (CadiWrap) request; + + List perms = wrapReq.getPermissions(wrapReq.getUserPrincipal()); + List aafPermsList = new ArrayList<>(); + for (Permission perm : perms) { + AAFPermission aafPerm = (AAFPermission) perm; + aafPermsList.add(aafPerm); + } + return aafPermsList; + } + + /** + * Here is a sample of a permission object in AAI. The key attribute will have + * Type|Instance|Action. + * AAFPermission: + * NS: null + * Type: org.onap.music.cadi.keyspace ( Permission Type ) + * Instance: tomtest ( Cassandra Keyspace ) + * Action: *|GET|ALL ( Access Level [*|ALL] for full access and [GET] for Read only) + * Key: org.onap.music.cadi.keyspace|tomtest|* + * + * This method will filter all permissions whose key starts with the requested namespace. + * The nsamespace here is the music namespace which is defined in music.property file. + * i;e is the type contains in key is org.onap.music.cadi.keyspace and the namespace + * value is org.onap.music.cadi.keyspace, it will add to list + * otherwise reject. + * + * @param nameSpace + * @param allPermissionsList + * @return + */ + private static List filterNameSpacesAAFPermissions(String nameSpace, + List allPermissionsList) { + List list = new ArrayList<>(); + for (Iterator iterator = allPermissionsList.iterator(); iterator.hasNext();) { + AAFPermission aafPermission = (AAFPermission) iterator.next(); + if(aafPermission.getType().indexOf(nameSpace) == 0) { + list.add(aafPermission); + } + } + return list; + } + + /** + * Decode certian characters from url encoded to normal. + * + * @param str - String being decoded. + * @return returns the decoded string. + * @throws Exception throws excpetion + */ + public static String decodeFunctionCode(String str) throws Exception { + String decodedString = str; + List decodingList = new ArrayList<>(); + decodingList.add(Pattern.compile(decodeValueOfForwardSlash)); + decodingList.add(Pattern.compile(decodeValueOfHyphen)); + decodingList.add(Pattern.compile(decodeValueOfAsterisk)); + for (Pattern xssInputPattern : decodingList) { + try { + decodedString = decodedString.replaceAll("%" + xssInputPattern, + new String(Hex.decodeHex(xssInputPattern.toString().toCharArray()))); + } catch (DecoderException e) { + logger.error(EELFLoggerDelegate.applicationLogger, + "AuthUtil Decode Failed! for instance: " + str); + throw new Exception("decode failed", e); + } + } + + return decodedString; + } + + /** + * + * + * @param request servlet request object + * @param nameSpace application namespace + * @return boolean value if the access is allowed + * @throws Exception throws exception + */ + public static boolean isAccessAllowed(ServletRequest request, String nameSpace) throws Exception { + + if (nameSpace.isEmpty()) { + throw new Exception("NameSpace not Declared!"); + } + + boolean isauthorized = false; + List aafPermsList = getAAFPermissions(request); + //logger.info(EELFLoggerDelegate.applicationLogger, + // "AAFPermission of the requested MechId for all the namespaces: " + aafPermsList); + + String requestUri = null; + logger.debug(EELFLoggerDelegate.applicationLogger, "Requested nameSpace: " + nameSpace); + HttpServletRequest httpRequest = null; + + + List aafPermsFinalList = filterNameSpacesAAFPermissions(nameSpace, aafPermsList); + + logger.debug(EELFLoggerDelegate.applicationLogger, + "AuthUtil list of AAFPermission for the specific namespace ::::::::::::::::::::::::::::::::::::::::::::" + + aafPermsFinalList); + + if (null != request) { + httpRequest = (HttpServletRequest) request; + requestUri = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length() + 1); + } + + logger.debug(EELFLoggerDelegate.applicationLogger, + "AuthUtil requestUri ::::::::::::::::::::::::::::::::::::::::::::" + requestUri); + + for (Iterator iterator = aafPermsFinalList.iterator(); iterator.hasNext();) { + AAFPermission aafPermission = (AAFPermission) iterator.next(); + if(!isauthorized) { + isauthorized = isMatchPatternWithInstanceAndAction(aafPermission, requestUri, httpRequest.getMethod()); + } + } + + logger.debug(EELFLoggerDelegate.applicationLogger, + "isAccessAllowed for the request uri: " + requestUri + "is :" + isauthorized); + return isauthorized; + } + + /** + * + * This method will check, if the requested URI matches any of the instance + * found with the AAF permission list. + * i;e if the request URI is; /v2/keyspaces/tomtest/tables/emp15 and in the + * AAF permission table, we have an instance + * defined as "tomtest" mapped the logged in user, it will allow else error. + * + * User trying to create or aquire a lock + * Here is the requested URI /v2/locks/create/tomtest.MyTable.Field1 + * Here the keyspace name i;e tomtest will be test throught out the URL if it + * matches, it will allow the user to create a lock. + * "tomtest" here is the key, which is mapped as an instance in permission object. + * Instance can be delimited with ":" i;e ":music-cassandra-1908-dev:admin". In this case, + * each delimited + * token will be matched with that of request URI. + * + * Example Permission: + * org.onap.music.api.user.access|tomtest|* or ALL + * org.onap.music.api.user.access|tomtest|GET + * In case of the action field is ALL and *, user will be allowed else it will + * be matched with the requested http method type. + * + * + * + * @param aafPermission - AAfpermission obtained by cadi. + * @param requestUri - Rest URL client is calling. + * @param method - REST Method being used (GET,POST,PUT,DELETE) + * @return returns a boolean + * @throws Exception - throws an exception + */ + private static boolean isMatchPatternWithInstanceAndAction( + AAFPermission aafPermission, + String requestUri, + String method) throws Exception { + if (null == aafPermission || null == requestUri || null == method) { + return false; + } + + String permKey = aafPermission.getKey(); + + logger.info(EELFLoggerDelegate.applicationLogger, "isMatchPattern permKey: " + + permKey + ", requestUri " + requestUri + " ," + method); + + String[] keyArray = permKey.split("\\|"); + String[] subPath = null; + //String type = null; + //type = keyArray[0]; + String instance = null; + instance = keyArray[1]; + String action = null; + action = keyArray[2]; + + //if the instance & action both are * , then allow + if ("*".equalsIgnoreCase(instance) && "*".equalsIgnoreCase(action)) { + return true; + } + //Decode string like %2f, %2d and %2a + if (!"*".equals(instance)) { + instance = decodeFunctionCode(instance); + } + if (!"*".equals(action)) { + action = decodeFunctionCode(action); + } + //Instance: :music-cassandra-1908-dev:admin + List instanceList = Arrays.asList(instance.split(":")); + + String[] path = requestUri.split("/"); + + for (int i = 0; i < path.length; i++) { + // Sometimes the value will begin with "$", so we need to remove it + if (path[i].startsWith("$")) { + path[i] = path[i].replace("$",""); + } + // Each path element can again delemited by ".";i;e + // tomtest.tables.emp. We have scenarios like lock aquire URL + subPath = path[i].split("\\."); + for (int j = 0; j < subPath.length; j++) { + if (instanceList.contains(subPath[j])) { + if ("*".equals(action) || "ALL".equalsIgnoreCase(action)) { + return true; + } else if (method.equalsIgnoreCase(action)) { + return true; + } else { + return false; + } + } else { + continue; + } + } + } + return false; + } +} \ No newline at end of file diff --git a/src/main/java/org/onap/music/authentication/AuthorizationError.java b/src/main/java/org/onap/music/authentication/AuthorizationError.java new file mode 100644 index 00000000..7015b550 --- /dev/null +++ b/src/main/java/org/onap/music/authentication/AuthorizationError.java @@ -0,0 +1,55 @@ +/* + * ============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.authentication; + + +/** + * Authorization error class used while setting error code and description back to client. + * + * + * @author sp931a + * + */ +public class AuthorizationError { + + private int responseCode; + + private String responseMessage; + + public int getResponseCode() { + return responseCode; + } + + public void setResponseCode(int responseCode) { + this.responseCode = responseCode; + } + + public String getResponseMessage() { + return responseMessage; + } + + public void setResponseMessage(String responseMessage) { + this.responseMessage = responseMessage; + } + +} \ No newline at end of file diff --git a/src/main/java/org/onap/music/authentication/CachingUtil.java b/src/main/java/org/onap/music/authentication/CachingUtil.java deleted file mode 100755 index dba23195..00000000 --- a/src/main/java/org/onap/music/authentication/CachingUtil.java +++ /dev/null @@ -1,452 +0,0 @@ -/* - * ============LICENSE_START========================================== - * org.onap.music - * =================================================================== - * Copyright (c) 2017 AT&T Intellectual Property - * =================================================================== - * Modifications Copyright (c) 2018 IBM - * Modifications Copyright (c) 2019 Samsung - * =================================================================== - * 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.authentication; - -import java.util.Calendar; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import javax.ws.rs.core.MediaType; - -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.jcs.JCS; -import org.apache.commons.jcs.access.CacheAccess; -import org.apache.commons.jcs.engine.CompositeCacheAttributes; -import org.apache.commons.jcs.engine.ElementAttributes; -import org.apache.commons.jcs.engine.behavior.ICompositeCacheAttributes; -import org.apache.commons.jcs.engine.behavior.IElementAttributes; -import org.mindrot.jbcrypt.BCrypt; -import org.onap.music.authentication.MusicAuthenticator.Operation; -import org.onap.music.datastore.PreparedQueryObject; -import org.onap.music.eelf.logging.EELFLoggerDelegate; -import org.onap.music.eelf.logging.format.AppMessages; -import org.onap.music.eelf.logging.format.ErrorSeverity; -import org.onap.music.eelf.logging.format.ErrorTypes; -import org.onap.music.exceptions.MusicServiceException; -import org.onap.music.main.MusicCore; -import org.onap.music.main.MusicUtil; -import com.datastax.driver.core.DataType; -import com.datastax.driver.core.ResultSet; -import com.datastax.driver.core.Row; -import com.datastax.driver.core.exceptions.InvalidQueryException; -import com.sun.jersey.api.client.Client; -import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.WebResource; - -/** - * All Caching related logic is handled by this class and a schedule cron runs to update cache. - * - * @author Vikram - * - */ -public class CachingUtil implements Runnable { - - private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(CachingUtil.class); - - /** keyspace & ns */ - private static CacheAccess musicCache = JCS.getInstance("musicCache"); - /** cache to hold isaaf application */ - private static CacheAccess appNameCache = JCS.getInstance("appNameCache"); - /** hold user creds for namespace */ - private static CacheAccess> musicValidateCache = JCS.getInstance("musicValidateCache"); - private static Map userAttempts = new HashMap<>(); - private static Map lastFailedTime = new HashMap<>(); - private static CacheAccess adminUserCache = JCS.getInstance("adminUserCache"); - - public static CacheAccess getAdminUserCache() { - return adminUserCache; - } - - public static void updateAdminUserCache(String authorization,String userId) { - adminUserCache.put(authorization,userId); - } - - private static final String USERNAME="username"; - private static final String PASSWORD="password"; - - - public void initializeAafCache() throws MusicServiceException { - logger.info(EELFLoggerDelegate.applicationLogger,"Resetting and initializing AAF Cache..."); - - String query = "SELECT uuid, application_name, keyspace_name, username, password FROM admin.keyspace_master WHERE is_api = ? allow filtering"; - PreparedQueryObject pQuery = new PreparedQueryObject(); - pQuery.appendQueryString(query); - try { - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), false)); - } catch (Exception e1) { - logger.error(EELFLoggerDelegate.errorLogger, e1.getMessage(),AppMessages.CACHEERROR, - ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR, e1); - } - ResultSet rs = MusicCore.get(pQuery); - Iterator it = rs.iterator(); - Map map = null; - while (it.hasNext()) { - Row row = it.next(); - String nameSpace = row.getString("keyspace_name"); - String userId = row.getString(USERNAME); - String password = row.getString(PASSWORD); - String keySpace = row.getString("application_name"); - try { - userAttempts.put(nameSpace, 0); - boolean responseObj = triggerAAF(nameSpace, userId, password); - if (responseObj) { - map = new HashMap<>(); - map.put(userId, password); - musicValidateCache.put(nameSpace, map); - musicCache.put(keySpace, nameSpace); - logger.debug("Cronjob: Cache Updated with AAF response for namespace " - + nameSpace); - } - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.UNKNOWNERROR, ErrorSeverity - .INFO, ErrorTypes.GENERALSERVICEERROR, e); - logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),"Something at AAF was changed for ns: " + nameSpace+" So not updating Cache for the namespace. "); - } - } - - } - - @Override - public void run() { - logger.info(EELFLoggerDelegate.applicationLogger,"Scheduled task invoked. Refreshing Cache..."); - try { - initializeAafCache(); - } catch (MusicServiceException e) { - logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.UNKNOWNERROR, ErrorSeverity.INFO, - ErrorTypes.GENERALSERVICEERROR, e); - } - } - - public static boolean authenticateAAFUser(String nameSpace, String userId, String password, - String keySpace) throws Exception { - - if (musicValidateCache.get(nameSpace) != null && musicCache.get(keySpace)!=null) { - if (keySpace != null && !musicCache.get(keySpace).equals(nameSpace)) { - logger.info(EELFLoggerDelegate.applicationLogger,"Create new application for the same namespace."); - } else if (musicValidateCache.get(nameSpace).get(userId).equals(password)) { - logger.info(EELFLoggerDelegate.applicationLogger,"Authenticated with cache value.."); - // reset invalid attempts to 0 - userAttempts.put(nameSpace, 0); - return true; - } else { - // call AAF update cache with new password - if (userAttempts.get(nameSpace) == null) - userAttempts.put(nameSpace, 0); - if ((Integer) userAttempts.get(nameSpace) >= 3) { - logger.info(EELFLoggerDelegate.applicationLogger,"Reached max attempts. Checking if time out.."); - logger.info(EELFLoggerDelegate.applicationLogger,"Failed time: "+lastFailedTime.get(nameSpace).getTime()); - Calendar calendar = Calendar.getInstance(); - long delayTime = (calendar.getTimeInMillis()-lastFailedTime.get(nameSpace).getTimeInMillis()); - logger.info(EELFLoggerDelegate.applicationLogger,"Delayed time: "+delayTime); - if( delayTime > 120000) { - logger.info(EELFLoggerDelegate.applicationLogger,"Resetting failed attempt."); - userAttempts.put(nameSpace, 0); - } else { - logger.info(EELFLoggerDelegate.applicationLogger,"No more attempts allowed. Please wait for atleast 2 min."); - throw new Exception("No more attempts allowed. Please wait for atleast 2 min."); - } - } - logger.error(EELFLoggerDelegate.errorLogger,"",AppMessages.CACHEAUTHENTICATION,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); - logger.info(EELFLoggerDelegate.applicationLogger,"Check AAF again..."); - } - } - - boolean responseObj = false; - try { - responseObj = triggerAAF(nameSpace, userId, password); - }catch (Exception ex) { - logger.info("Exception while trigger aaf", ex); - logger.info("Exception: " + ex.getMessage()); - throw new Exception("Exception raised while triggering AAF authentication" +ex.getMessage()); - } - if (responseObj) { - logger.info(EELFLoggerDelegate.applicationLogger,"Valid user. Cache is updated for "+nameSpace); - Map map = new HashMap<>(); - map.put(userId, password); - musicValidateCache.put(nameSpace, map); - musicCache.put(keySpace, nameSpace); - return true; - } - logger.info(EELFLoggerDelegate.applicationLogger,"Invalid user. Cache not updated"); - return false; - } - - private static boolean triggerAAF(String nameSpace, String userId, String password) - throws Exception { - logger.info(EELFLoggerDelegate.applicationLogger,"Inside AAF authorization"); - if (MusicUtil.getAafEndpointUrl() == null) { - logger.error(EELFLoggerDelegate.errorLogger,"AAF endpoint is not set. Please specify in the properties file.",AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); - throw new Exception("AAF endpoint is not set. Please specify in the properties file."); - } - Client client = Client.create(); - WebResource webResource = client.resource(MusicUtil.getAafEndpointUrl().concat(nameSpace)); - String plainCreds = userId + ":" + password; - byte[] plainCredsBytes = plainCreds.getBytes(); - byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes); - String base64Creds = new String(base64CredsBytes); - - ClientResponse response = webResource.accept(MediaType.APPLICATION_JSON) - .header("Authorization", "Basic " + base64Creds) - .header("content-type", "application/json").get(ClientResponse.class); - logger.info(EELFLoggerDelegate.applicationLogger, "aaf response: "+response.toString()); - if (response.getStatus() != 200) { - if (userAttempts.get(nameSpace) == null) - userAttempts.put(nameSpace, 0); - if ((Integer) userAttempts.get(nameSpace) >= 2) { - lastFailedTime.put(nameSpace, Calendar.getInstance()); - userAttempts.put(nameSpace, ((Integer) userAttempts.get(nameSpace) + 1)); - throw new Exception( - "Reached max invalid attempts. Please contact admin and retry with valid credentials."); - } - userAttempts.put(nameSpace, ((Integer) userAttempts.get(nameSpace) + 1)); - throw new Exception( - "Unable to authenticate. Please check the AAF credentials against namespace."); - // TODO Allow for 2-3 times and forbid any attempt to trigger AAF with invalid values - // for specific time. - } - /*response.getHeaders().put(HttpHeaders.CONTENT_TYPE, - Arrays.asList(MediaType.APPLICATION_JSON)); - // AAFResponse output = response.getEntity(AAFResponse.class); - response.bufferEntity(); - String x = response.getEntity(String.class); - AAFResponse responseObj = new ObjectMapper().readValue(x, AAFResponse.class);*/ - - return true; - } - - public static void updateMusicCache(String keyspace, String nameSpace) { - logger.info(EELFLoggerDelegate.applicationLogger,"Updating musicCache for keyspace " + keyspace + " with nameSpace " + nameSpace); - musicCache.put(keyspace, nameSpace); - } - - public static void updateCadiCache(String user, String keyspace) { - musicCache.put(user, keyspace); - } - - public static String getKSFromCadiCache(String user) { - return musicCache.get(user); - } - - public static void updateMusicValidateCache(String nameSpace, String userId, String password) { - logger.info(EELFLoggerDelegate.applicationLogger,"Updating musicCache for nameSpacce " + nameSpace + " with userId " + userId); - Map map = new HashMap<>(); - map.put(userId, password); - musicValidateCache.put(nameSpace, map); - } - - public static void updateisAAFCache(String namespace, String isAAF) { - appNameCache.put(namespace, isAAF); - } - - public static String isAAFApplication(String namespace) throws MusicServiceException { - String isAAF = appNameCache.get(namespace); - if (isAAF == null) { - PreparedQueryObject pQuery = new PreparedQueryObject(); - pQuery.appendQueryString( - "SELECT is_aaf from admin.keyspace_master where application_name = '" - + namespace + "' allow filtering"); - Row rs = null; - try { - rs = MusicCore.get(pQuery).one(); - } catch(InvalidQueryException e) { - logger.error(EELFLoggerDelegate.errorLogger,"Exception admin keyspace not configured."+ e.getMessage - (), e); - throw new MusicServiceException("Please make sure admin.keyspace_master table is configured."); - } - try { - isAAF = String.valueOf(rs.getBool("is_aaf")); - if(isAAF != null) - appNameCache.put(namespace, isAAF); - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), AppMessages.QUERYERROR,ErrorSeverity - .ERROR, ErrorTypes.QUERYERROR, e); - } - } - return isAAF; - } - - public static String getUuidFromMusicCache(String keyspace) throws MusicServiceException { - String uuid = null; - if (uuid == null) { - PreparedQueryObject pQuery = new PreparedQueryObject(); - pQuery.appendQueryString( - "SELECT uuid from admin.keyspace_master where keyspace_name = '" - + keyspace + "' allow filtering"); - Row rs = MusicCore.get(pQuery).one(); - try { - uuid = rs.getUUID("uuid").toString(); - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger,"Exception occurred during uuid retrieval from DB."+e - .getMessage(), e); - } - } - return uuid; - } - - public static String getAppName(String keyspace) throws MusicServiceException { - String appName = null; - PreparedQueryObject pQuery = new PreparedQueryObject(); - pQuery.appendQueryString( - "SELECT application_name from admin.keyspace_master where keyspace_name = '" - + keyspace + "' allow filtering"); - Row rs = MusicCore.get(pQuery).one(); - try { - appName = rs.getString("application_name"); - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), AppMessages.QUERYERROR, ErrorSeverity - .ERROR, ErrorTypes.QUERYERROR, e); - } - return appName; - } - - @Deprecated - public static Map validateRequest(String nameSpace, String userId, - String password, String keyspace, String aid, String operation) { - Map resultMap = new HashMap<>(); - if (!"createKeySpace".equals(operation)) { - if (nameSpace == null) { - resultMap.put("Exception", "Application namespace is mandatory."); - } - } - return resultMap; - } - - public static Map validateRequest(String nameSpace, String userId, - String password, String keyspace, String aid, Operation operation) { - Map resultMap = new HashMap<>(); - if (Operation.CREATE_KEYSPACE!=operation) { - if (nameSpace == null) { - resultMap.put("Exception", "Application namespace is mandatory."); - } - } - return resultMap; - } - - public static Map verifyOnboarding(String ns, String userId, String password) { - Map resultMap = new HashMap<>(); - if (ns == null || userId == null || password == null) { - logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); - logger.error(EELFLoggerDelegate.errorLogger,"One or more required headers is missing. userId: "+userId+" :: password: "+password); - resultMap.put("Exception", - "One or more required headers appName(ns), userId, password is missing. Please check."); - return resultMap; - } - PreparedQueryObject queryObject = new PreparedQueryObject(); - queryObject.appendQueryString( - "select * from admin.keyspace_master where application_name = ? allow filtering"); - try { - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), ns)); - } catch(Exception e) { - resultMap.put("Exception", - "Unable to process input data. Invalid input data type. Please check ns, userId and password values. "+e.getMessage()); - return resultMap; - } - Row rs = null; - try { - rs = MusicCore.get(queryObject).one(); - } catch (MusicServiceException e) { - String errorMsg = "Unable to process operation. Error is "+e.getMessage(); - logger.error(EELFLoggerDelegate.errorLogger, errorMsg, e); - resultMap.put("Exception", errorMsg); - return resultMap; - } catch (InvalidQueryException e) { - logger.error(EELFLoggerDelegate.errorLogger,"Exception admin keyspace not configured."+e.getMessage(), e); - resultMap.put("Exception", "Please make sure admin.keyspace_master table is configured."); - return resultMap; - } - if (rs == null) { - logger.error(EELFLoggerDelegate.errorLogger,"Application is not onboarded. Please contact admin."); - resultMap.put("Exception", "Application is not onboarded. Please contact admin."); - } else { - if(!(rs.getString(USERNAME).equals(userId)) || !(BCrypt.checkpw(password, rs.getString(PASSWORD)))) { - logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.AUTHENTICATIONERROR, ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); - logger.error(EELFLoggerDelegate.errorLogger,"Namespace, UserId and password doesn't match. namespace: "+ns+" and userId: "+userId); - resultMap.put("Exception", "Namespace, UserId and password doesn't match. namespace: "+ns+" and userId: "+userId); - return resultMap; - } - } - return resultMap; - } - - public static Map authenticateAIDUser(String nameSpace, String userId, String password, - String keyspace) { - Map resultMap = new HashMap<>(); - String pwd = null; - if((musicCache.get(keyspace) != null) && (musicValidateCache.get(nameSpace) != null) - && (musicValidateCache.get(nameSpace).containsKey(userId))) { - if(!musicCache.get(keyspace).equals(nameSpace)) { - resultMap.put("Exception", "Namespace and keyspace doesn't match"); - return resultMap; - } - if(!BCrypt.checkpw(password,musicValidateCache.get(nameSpace).get(userId))) { - resultMap.put("Exception", "Namespace, userId and password doesn't match"); - return resultMap; - } - return resultMap; - } - PreparedQueryObject queryObject = new PreparedQueryObject(); - queryObject.appendQueryString( - "select * from admin.keyspace_master where keyspace_name = ? allow filtering"); - try { - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), keyspace)); - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger,"Adding value to query object failed: " + e.getMessage(), e); - } - Row rs = null; - try { - rs = MusicCore.get(queryObject).one(); - } catch (MusicServiceException e) { - String errMsg = "Unable to process operation. Error is "+e.getMessage(); - logger.error(EELFLoggerDelegate.errorLogger, errMsg, e); - resultMap.put("Exception", errMsg); - return resultMap; - } - if(rs == null) { - resultMap.put("Exception", "Please make sure keyspace:"+keyspace+" exists."); - return resultMap; - } - else { - String user = rs.getString(USERNAME); - pwd = rs.getString(PASSWORD); - String ns = rs.getString("application_name"); - if(!ns.equals(nameSpace)) { - resultMap.put("Exception", "Namespace and keyspace doesn't match"); - return resultMap; - } - if(!user.equals(userId)) { - resultMap.put("Exception", "Invalid userId :"+userId); - return resultMap; - } - if(!BCrypt.checkpw(password, pwd)) { - resultMap.put("Exception", "Invalid password"); - return resultMap; - } - } - CachingUtil.updateMusicCache(keyspace, nameSpace); - CachingUtil.updateMusicValidateCache(nameSpace, userId, pwd); - return resultMap; - } -} diff --git a/src/main/java/org/onap/music/authentication/CadiAuthFilter.java b/src/main/java/org/onap/music/authentication/CadiAuthFilter.java index 56371c7d..765face7 100644 --- a/src/main/java/org/onap/music/authentication/CadiAuthFilter.java +++ b/src/main/java/org/onap/music/authentication/CadiAuthFilter.java @@ -21,25 +21,22 @@ */ package org.onap.music.authentication; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; + +import java.io.IOException; + +import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; -import javax.servlet.http.HttpServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.annotation.WebFilter; -import com.att.eelf.configuration.EELFLogger; -import org.onap.aaf.cadi.CadiWrap; -import org.onap.aaf.cadi.Permission; import org.onap.aaf.cadi.PropAccess; -import org.onap.aaf.cadi.aaf.AAFPermission; import org.onap.aaf.cadi.filter.CadiFilter; import org.onap.music.eelf.logging.EELFLoggerDelegate; -import org.onap.music.main.MusicCore; +@WebFilter(urlPatterns = { "/*" }) public class CadiAuthFilter extends CadiFilter { private static final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(CadiAuthFilter.class); @@ -47,64 +44,27 @@ public class CadiAuthFilter extends CadiFilter { public CadiAuthFilter(PropAccess access) throws ServletException { super(true, access); } - - public void init(FilterConfig filterConfig) throws ServletException { - super.init(filterConfig); - } - - private boolean matchPattern(String requestedPath, String includeUrl) { - includeUrl = includeUrl.substring(1); - String[] path = requestedPath.split("/"); - if (path.length > 1) { - String[] roleFunctionArray = includeUrl.split("/"); - boolean match = true; - for (int i = 0; i < roleFunctionArray.length; i++) { - if (match) { - if (!"*".equals(roleFunctionArray[i])) { - Pattern p = Pattern.compile(Pattern.quote(path[i]), Pattern.CASE_INSENSITIVE); - Matcher m = p.matcher(roleFunctionArray[i]); - match = m.matches(); - } else if (roleFunctionArray[i].equals("*")) { - match = true; - } - - } - } - if (match) - return match; - } else { - if (requestedPath.matches(includeUrl)) - return true; - else if ("*".equals(includeUrl)) - return true; - } - return false; + public CadiAuthFilter() throws ServletException { + super(); } - - public static List getAAFPermissions(HttpServletRequest request) { - CadiWrap wrapReq = (CadiWrap) request; - List perms = wrapReq.getPermissions(wrapReq.getUserPrincipal()); - List aafPermsList = new ArrayList<>(); - for (Permission perm : perms) { - AAFPermission aafPerm = (AAFPermission) perm; - aafPermsList.add(aafPerm); - logger.info(aafPerm.toString()); - logger.info(aafPerm.getType()); - } - return aafPermsList; - } - - public static List getAAFPermissions(ServletRequest request) { - CadiWrap wrapReq = (CadiWrap) request; - List perms = wrapReq.getPermissions(wrapReq.getUserPrincipal()); - List aafPermsList = new ArrayList<>(); - for (Permission perm : perms) { - AAFPermission aafPerm = (AAFPermission) perm; - aafPermsList.add(aafPerm); - } - return aafPermsList; + @Override + public void init(FilterConfig filterConfig) throws ServletException { + super.init(filterConfig); } + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + logger.info(EELFLoggerDelegate.applicationLogger, "Request is entering cadifilter"); + + long startTime = System.currentTimeMillis(); + request.setAttribute("startTime", startTime); + + super.doFilter(request, response, chain); + + //Commented by saumya (sp931a) on 04/11/19 for auth filter + //chain.doFilter(request, response); + } } \ No newline at end of file diff --git a/src/main/java/org/onap/music/authentication/MusicAAFAuthentication.java b/src/main/java/org/onap/music/authentication/MusicAAFAuthentication.java deleted file mode 100644 index a84bdd9b..00000000 --- a/src/main/java/org/onap/music/authentication/MusicAAFAuthentication.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * ============LICENSE_START========================================== - * org.onap.music - * =================================================================== - * Copyright (c) 2017 AT&T Intellectual Property - * =================================================================== - * Modifications Copyright (c) 2019 Samsung - * =================================================================== - * 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.authentication; - -import java.util.HashMap; -import java.util.Map; - -import javax.ws.rs.core.MediaType; - -import org.apache.commons.jcs.access.CacheAccess; -import org.onap.music.datastore.PreparedQueryObject; -import org.onap.music.eelf.logging.EELFLoggerDelegate; -import org.onap.music.eelf.logging.format.AppMessages; -import org.onap.music.eelf.logging.format.ErrorSeverity; -import org.onap.music.eelf.logging.format.ErrorTypes; -import org.onap.music.exceptions.MusicServiceException; -import org.onap.music.authentication.MusicAuthenticator.Operation; -import org.onap.music.main.MusicCore; -import org.onap.music.main.MusicUtil; - -import com.datastax.driver.core.DataType; -import com.datastax.driver.core.Row; -import com.sun.jersey.api.client.Client; -import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.WebResource; - -public class MusicAAFAuthentication implements MusicAuthenticator { - - private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicAAFAuthentication.class); - - @Override - public boolean authenticateAdmin(String authorization) { - logger.info(EELFLoggerDelegate.applicationLogger, "MusicCore.authenticateAdmin: "); - String userId = MusicUtil.extractBasicAuthentication(authorization).get(MusicUtil.USERID); - CacheAccess adminCache = CachingUtil.getAdminUserCache(); - if (authorization == null) { - logger.error(EELFLoggerDelegate.errorLogger, "Authorization cannot be empty..."); - return false; - } - if (adminCache.get(authorization) != null && adminCache.get(authorization).equals(userId)) { - logger.info(EELFLoggerDelegate.applicationLogger, "MusicCore.authenticateAdmin: Validated against admincache.. "); - return true; - } - else { - Client client = Client.create(); - String aafUrl = MusicUtil.getAafAdminUrl(); - if (aafUrl==null) { - logger.error(EELFLoggerDelegate.errorLogger, "Admin url is not set, please set in properties"); - return false; - } - - WebResource webResource = client.resource( - MusicUtil.getAafAdminUrl().concat(userId).concat("/").concat(MusicUtil.getAdminAafRole())); - - ClientResponse response = webResource.accept(MediaType.APPLICATION_JSON) - .header("Authorization", authorization).get(ClientResponse.class); - if (response.getStatus() == 200) { - CachingUtil.updateAdminUserCache(authorization, userId); - return true; - } - } - return false; - } - - @Override - public boolean authenticateUser(String namespace, String authorization, String keyspace, - String aid, Operation operation) { - logger.info(EELFLoggerDelegate.applicationLogger,"Inside User Authentication......."); - Map userCredentials = MusicUtil.extractBasicAuthentication(authorization); - String userId = userCredentials.get(MusicUtil.USERID); - String password = userCredentials.get(MusicUtil.PASSWORD); - - Map resultMap = new HashMap<>(); - String uuid = null; - if(! MusicUtil.getIsCadi()) { - resultMap = CachingUtil.validateRequest(namespace, userId, password, keyspace, aid, - operation); - if (!resultMap.isEmpty()) - return false; - String isAAFApp = null; - try { - isAAFApp= CachingUtil.isAAFApplication(namespace); - } catch(MusicServiceException e) { - logger.error(e.getErrorMessage(), e); - resultMap.put("Exception", e.getMessage()); - return false; - } - if(isAAFApp == null) { - resultMap.put("Exception", "Namespace: "+namespace+" doesn't exist. Please make sure ns(appName)" - + " is correct and Application is onboarded."); - return false; - } - boolean isAAF = Boolean.parseBoolean(isAAFApp); - if (userId == null || password == null) { - logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); - logger.error(EELFLoggerDelegate.errorLogger,"UserId/Password or more required headers is missing."); - resultMap.put("Exception", - "UserId and Password are mandatory for the operation " + operation); - return false; - } - if(!isAAF && !(operation==Operation.CREATE_KEYSPACE)) { - resultMap = CachingUtil.authenticateAIDUser(namespace, userId, password, keyspace); - if (!resultMap.isEmpty()) - return false; - - } - if (isAAF && namespace != null && userId != null && password != null) { - boolean isValid = true; - try { - isValid = CachingUtil.authenticateAAFUser(namespace, userId, password, keyspace); - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger,"Error while aaf authentication for user:" + userId); - logger.error(EELFLoggerDelegate.errorLogger,"Error: "+ e.getMessage(), e); - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); - logger.error(EELFLoggerDelegate.errorLogger,"Got exception while AAF authentication for namespace " + namespace); - resultMap.put("Exception", e.getMessage()); - } - if (!isValid) { - logger.error(EELFLoggerDelegate.errorLogger,"User not authenticated...", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); - resultMap.put("Exception", "User not authenticated..."); - } - if (!resultMap.isEmpty()) - return false; - - } - } else { - - String cachedKS = CachingUtil.getKSFromCadiCache(userId); - if(cachedKS != null && !cachedKS.equals(keyspace)) { - resultMap.put("Exception", "User not authenticated to access this keyspace..."); - return false; - } - } - - if (operation==Operation.CREATE_KEYSPACE) { - try { - logger.info(EELFLoggerDelegate.applicationLogger,"AID is not provided. Creating new UUID for keyspace."); - PreparedQueryObject pQuery = new PreparedQueryObject(); - pQuery.appendQueryString( - "select uuid from admin.keyspace_master where application_name=? and username=? and keyspace_name=? allow filtering"); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), namespace)); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), - MusicUtil.DEFAULTKEYSPACENAME)); - Row rs = MusicCore.get(pQuery).one(); - uuid = rs.getUUID("uuid").toString(); - resultMap.put("uuid", "existing"); - } catch (Exception e) { - logger.error(EELFLoggerDelegate.applicationLogger,"No UUID found in DB. So creating new UUID.", e); - uuid = MusicUtil.generateUUID(); - resultMap.put("uuid", "new"); - } - resultMap.put("aid", uuid); - CachingUtil.updateCadiCache(userId, keyspace); - } - return true; - } - -} diff --git a/src/main/java/org/onap/music/authentication/MusicAuthenticator.java b/src/main/java/org/onap/music/authentication/MusicAuthenticator.java deleted file mode 100644 index 78f76ab1..00000000 --- a/src/main/java/org/onap/music/authentication/MusicAuthenticator.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * ============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.authentication; - -public interface MusicAuthenticator { - public enum Operation{ - CREATE_KEYSPACE, - DROP_KEYSPACE, - CREATE_TABLE, - CREATE_INDEX, - INSERT_INTO_TABLE, - UPDATE_TABLE, - DELETE_FROM_TABLE, - DROP_TABLE, - SELECT_CRITICAL, - SELECT, - CREATE_LOCKREF, - ACQUIRE_LOCK, - CURRENT_LOCK, - DELETE_LOCK - } - - /** - * Authenticate a user account - * @param namespace - user's namespace - * @param authorization - basicAuth representation of username/password - * @param keyspace - keyspace user is trying to access - * @param aid - aid that identifies the user - * @param operation - operation that user is trying to do - * @return true if user has access - */ - public boolean authenticateUser(String namespace, String authorization, - String keyspace, String aid, Operation operation); - - /** - * Authenticate an administrative account - * @param authorization - basicAuth representation of username/password - * @return true if user has admin privileges - */ - public boolean authenticateAdmin(String authorization); - -} diff --git a/src/main/java/org/onap/music/authentication/MusicAuthorizationFilter.java b/src/main/java/org/onap/music/authentication/MusicAuthorizationFilter.java new file mode 100644 index 00000000..b1db1083 --- /dev/null +++ b/src/main/java/org/onap/music/authentication/MusicAuthorizationFilter.java @@ -0,0 +1,170 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Modifications Copyright (c) 2019 Samsung + * =================================================================== + * 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.authentication; + +import java.io.IOException; +import java.util.Base64; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.PropertySource; + +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * This filter class does authorization from AAF + * + * @author sp931a + * + */ +@PropertySource(value = {"file:/opt/app/music/etc/music.properties"}) +public class MusicAuthorizationFilter implements Filter { + + @Value("${music.aaf.ns}") + private String musicNS; + + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicAuthorizationFilter.class); + + public MusicAuthorizationFilter() throws ServletException { + super(); + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { + + logger.debug(EELFLoggerDelegate.applicationLogger, + "In MusicAuthorizationFilter doFilter start() ::::::::::::::::::::::::"); + + 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(); + } else { + startTime = System.currentTimeMillis(); // this will set only incase the request attribute not found + } + + try { + isAuthAllowed = AuthUtil.isAccessAllowed(servletRequest, musicNS); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.applicationLogger, + "Error while checking authorization :::" + e.getMessage()); + } + + long endTime = System.currentTimeMillis(); + + //startTime set in CadiAuthFilter doFilter + logger.debug(EELFLoggerDelegate.applicationLogger, + "Time took for authentication & authorization : " + + (endTime - startTime) + " milliseconds"); + + if (!isAuthAllowed) { + logger.debug(EELFLoggerDelegate.applicationLogger, + "Unauthorized Access"); + AuthorizationError authError = new AuthorizationError(); + authError.setResponseCode(HttpServletResponse.SC_UNAUTHORIZED); + authError.setResponseMessage("Unauthorized Access - Please make sure you are " + + "onboarded and have proper access to MUSIC. "); + + byte[] responseToSend = restResponseBytes(authError); + httpResponse.setHeader("Content-Type", "application/json"); + + httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + servletResponse.getOutputStream().write(responseToSend); + return; + } else { + filterChain.doFilter(servletRequest, servletResponse); + } + } + logger.debug(EELFLoggerDelegate.applicationLogger, + "In MusicAuthorizationFilter doFilter exit() ::::::::::::::::::::::::"); + } + + private byte[] restResponseBytes(AuthorizationError eErrorResponse) throws IOException { + String serialized = new ObjectMapper().writeValueAsString(eErrorResponse); + return serialized.getBytes(); + } + + private Map getHeadersInfo(HttpServletRequest request) { + + Map map = new HashMap(); + + Enumeration headerNames = request.getHeaderNames(); + while (headerNames.hasMoreElements()) { + String key = (String) headerNames.nextElement(); + String value = request.getHeader(key); + map.put(key, value); + } + + return map; + } + + private static String getUserNamefromRequest(HttpServletRequest httpRequest) { + String authHeader = httpRequest.getHeader("Authorization"); + String username = null; + if (authHeader != null) { + String[] split = authHeader.split("\\s+"); + if (split.length > 0) { + String basic = split[0]; + + if ("Basic".equalsIgnoreCase(basic)) { + byte[] decodedBytes = Base64.getDecoder().decode(split[1]); + String decodedString = new String(decodedBytes); + int p = decodedString.indexOf(":"); + if (p != -1) { + username = decodedString.substring(0, p); + } + } + } + } + return username; + } +} diff --git a/src/main/java/org/onap/music/conductor/conditionals/RestMusicConditionalAPI.java b/src/main/java/org/onap/music/conductor/conditionals/RestMusicConditionalAPI.java index 4a56825a..7372fc46 100644 --- a/src/main/java/org/onap/music/conductor/conditionals/RestMusicConditionalAPI.java +++ b/src/main/java/org/onap/music/conductor/conditionals/RestMusicConditionalAPI.java @@ -40,7 +40,6 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.ResponseBuilder; import javax.ws.rs.core.Response.Status; -import org.codehaus.jettison.json.JSONObject; import org.onap.music.datastore.MusicDataStoreHandle; import org.onap.music.datastore.PreparedQueryObject; import org.onap.music.eelf.logging.EELFLoggerDelegate; @@ -51,10 +50,6 @@ import org.onap.music.main.MusicUtil; import org.onap.music.main.ResultType; import org.onap.music.main.ReturnType; import org.onap.music.response.jsonobjects.JsonResponse; -import org.onap.music.rest.RestMusicAdminAPI; -import org.onap.music.authentication.MusicAAFAuthentication; -import org.onap.music.authentication.MusicAuthenticator; -import org.onap.music.authentication.MusicAuthenticator.Operation; import org.onap.music.conductor.*; import com.datastax.driver.core.DataType; @@ -65,38 +60,37 @@ import io.swagger.annotations.ApiParam; @Path("/v2/conditional") @Api(value = "Conditional Api", hidden = true) - public class RestMusicConditionalAPI { - private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicAdminAPI.class); +public class RestMusicConditionalAPI { + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicConditionalAPI.class); private static final String XMINORVERSION = "X-minorVersion"; private static final String XPATCHVERSION = "X-patchVersion"; private static final String NS = "ns"; private static final String VERSION = "v2"; - private MusicAuthenticator authenticator = new MusicAAFAuthentication(); - @POST @Path("/insert/keyspaces/{keyspace}/tables/{tablename}") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response insertConditional( - @ApiParam(value = "Major Version", required = true) @PathParam("version") String version, - @ApiParam(value = "Minor Version", required = false) @HeaderParam(XMINORVERSION) String minorVersion, - @ApiParam(value = "Patch Version", required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, - @ApiParam(value = "Application namespace", required = true) @HeaderParam(NS) String ns, - @ApiParam(value = "Authorization", required = true) @HeaderParam("Authorization") String authorization, - @ApiParam(value = "Keyspace Name", required = true) @PathParam("keyspace") String keyspace, - @ApiParam(value = "Table Name", required = true) @PathParam("tablename") String tablename, - JsonConditional jsonObj) throws Exception { - ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); - - if (!authenticator.authenticateUser(ns, authorization, keyspace, aid, Operation.INSERT_INTO_TABLE)) { - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check username, password and make sure your app is onboarded") - .toMap()).build(); - } - + @ApiParam(value = "Major Version", required = true) + @PathParam("version") String version, + @ApiParam(value = "Minor Version", required = false) + @HeaderParam(XMINORVERSION) String minorVersion, + @ApiParam(value = "Patch Version", required = false) + @HeaderParam(XPATCHVERSION) String patchVersion, + @ApiParam(value = "AID", required = true) + @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", required = true) + @HeaderParam(NS) String ns, + @ApiParam(value = "Authorization", required = true) + @HeaderParam("Authorization") String authorization, + @ApiParam(value = "Keyspace Name", required = true) + @PathParam("keyspace") String keyspace, + @ApiParam(value = "Table Name", required = true) + @PathParam("tablename") String tablename, + JsonConditional jsonObj) throws Exception { + ResponseBuilder response = + MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); String primaryKey = jsonObj.getPrimaryKey(); String primaryKeyValue = jsonObj.getPrimaryKeyValue(); String casscadeColumnName = jsonObj.getCasscadeColumnName(); @@ -104,15 +98,14 @@ import io.swagger.annotations.ApiParam; Map casscadeColumnData = jsonObj.getCasscadeColumnData(); Map> conditions = jsonObj.getConditions(); - if (primaryKey == null || primaryKeyValue == null || casscadeColumnName == null || tableValues.isEmpty() - || casscadeColumnData.isEmpty() || conditions.isEmpty()) { + if (primaryKey == null || primaryKeyValue == null || casscadeColumnName == null + || tableValues.isEmpty() || casscadeColumnData.isEmpty() || conditions.isEmpty()) { logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGINFO, ErrorSeverity.CRITICAL, - ErrorTypes.AUTHENTICATIONERROR); + ErrorTypes.AUTHENTICATIONERROR); return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE) - .setError(String.valueOf("One or more input values missing")).toMap()).build(); - + .setError(String.valueOf("One or more input values missing")).toMap()).build(); } - + Map authMap = null; Map valuesMap = new LinkedHashMap<>(); for (Map.Entry entry : tableValues.entrySet()) { valuesMap.put(entry.getKey(), entry.getValue()); @@ -123,10 +116,11 @@ import io.swagger.annotations.ApiParam; status.put("nonexists", conditions.get("nonexists").get("status")); ReturnType out = null; - out = MusicConditional.conditionalInsert(keyspace, tablename, casscadeColumnName, casscadeColumnData, - primaryKeyValue, valuesMap, status); - return response.status(Status.OK).entity(new JsonResponse(out.getResult()).setMessage(out.getMessage()).toMap()) - .build(); + out = MusicConditional.conditionalInsert(keyspace, tablename, + casscadeColumnName, casscadeColumnData,primaryKeyValue, valuesMap, status); + return response.status(Status.OK).entity(new JsonResponse( + out.getResult()).setMessage(out.getMessage()).toMap()) + .build(); } @@ -136,24 +130,25 @@ import io.swagger.annotations.ApiParam; @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response updateConditional( - @ApiParam(value = "Major Version", required = true) @PathParam("version") String version, - @ApiParam(value = "Minor Version", required = false) @HeaderParam(XMINORVERSION) String minorVersion, - @ApiParam(value = "Patch Version", required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, - @ApiParam(value = "Application namespace", required = true) @HeaderParam(NS) String ns, - @ApiParam(value = "Authorization", required = true) @HeaderParam("Authorization") String authorization, - @ApiParam(value = "Major Version", required = true) @PathParam("keyspace") String keyspace, - @ApiParam(value = "Major Version", required = true) @PathParam("tablename") String tablename, - JsonConditional upObj) throws Exception { + @ApiParam(value = "Major Version", required = true) + @PathParam("version") String version, + @ApiParam(value = "Minor Version", required = false) + @HeaderParam(XMINORVERSION) String minorVersion, + @ApiParam(value = "Patch Version", required = false) + @HeaderParam(XPATCHVERSION) String patchVersion, + @ApiParam(value = "AID", required = true) + @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", required = true) + @HeaderParam(NS) String ns, + @ApiParam(value = "Authorization", required = true) + @HeaderParam("Authorization") String authorization, + @ApiParam(value = "Major Version", required = true) + @PathParam("keyspace") String keyspace, + @ApiParam(value = "Major Version", required = true) + @PathParam("tablename") String tablename, + JsonConditional upObj) throws Exception { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); - if (!authenticator.authenticateUser(ns, authorization, keyspace, aid, Operation.INSERT_INTO_TABLE)) { - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check username, password and make sure your app is onboarded") - .toMap()).build(); - } - String primaryKey = upObj.getPrimaryKey(); String primaryKeyValue = upObj.getPrimaryKeyValue(); String casscadeColumnName = upObj.getCasscadeColumnName(); @@ -161,7 +156,7 @@ import io.swagger.annotations.ApiParam; Map tableValues = upObj.getTableValues(); if (primaryKey == null || primaryKeyValue == null || casscadeColumnName == null - || casscadeColumnData.isEmpty()) { + || casscadeColumnData.isEmpty()) { logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGINFO, ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR); return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE) @@ -169,28 +164,35 @@ import io.swagger.annotations.ApiParam; } - String planId = casscadeColumnData.get("key").toString(); - Map casscadeColumnValueMap = (Map) casscadeColumnData.get("value"); + Map casscadeColumnValueMap = + (Map) casscadeColumnData.get("value"); TableMetadata tableInfo = null; tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename); DataType primaryIdType = tableInfo.getPrimaryKey().get(0).getType(); String primaryId = tableInfo.getPrimaryKey().get(0).getName(); PreparedQueryObject select = new PreparedQueryObject(); - select.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " where " + primaryId + " = ?"); + select.appendQueryString("SELECT * FROM " + keyspace + "." + + tablename + " where " + primaryId + " = ?"); select.addValue(MusicUtil.convertToActualDataType(primaryIdType, primaryKeyValue)); - PreparedQueryObject upsert = MusicConditional.extractQuery(tableValues, tableInfo, tablename, keyspace, primaryKey, primaryKeyValue, null, null); + PreparedQueryObject upsert = + MusicConditional.extractQuery(tableValues, tableInfo, tablename, + keyspace, primaryKey, primaryKeyValue, null, null); Map queryBank = new HashMap<>(); queryBank.put(MusicUtil.SELECT, select); queryBank.put(MusicUtil.UPSERT, upsert); - ReturnType result = MusicConditional.update(queryBank, keyspace, tablename, primaryKey,primaryKeyValue,planId,casscadeColumnName,casscadeColumnValueMap); + String planId = casscadeColumnData.get("key").toString(); + ReturnType result = MusicConditional.update(queryBank, keyspace, tablename, + primaryKey,primaryKeyValue,planId,casscadeColumnName,casscadeColumnValueMap); if (result.getResult() == ResultType.SUCCESS) { return response.status(Status.OK) - .entity(new JsonResponse(result.getResult()).setMessage(result.getMessage()).toMap()).build(); + .entity(new JsonResponse(result.getResult()) + .setMessage(result.getMessage()).toMap()).build(); } return response.status(Status.BAD_REQUEST) - .entity(new JsonResponse(result.getResult()).setMessage(result.getMessage()).toMap()).build(); + .entity(new JsonResponse(result.getResult()) + .setMessage(result.getMessage()).toMap()).build(); } diff --git a/src/main/java/org/onap/music/datastore/Condition.java b/src/main/java/org/onap/music/datastore/Condition.java index 11998ab5..6587748e 100644 --- a/src/main/java/org/onap/music/datastore/Condition.java +++ b/src/main/java/org/onap/music/datastore/Condition.java @@ -30,8 +30,8 @@ import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.Row; public class Condition { - Map conditions; - PreparedQueryObject selectQueryForTheRow; + private Map conditions; + private PreparedQueryObject selectQueryForTheRow; public Condition(Map conditions, PreparedQueryObject selectQueryForTheRow) { this.conditions = conditions; diff --git a/src/main/java/org/onap/music/datastore/MusicDataStore.java b/src/main/java/org/onap/music/datastore/MusicDataStore.java index 2b88b4a8..c771d80a 100755 --- a/src/main/java/org/onap/music/datastore/MusicDataStore.java +++ b/src/main/java/org/onap/music/datastore/MusicDataStore.java @@ -36,7 +36,6 @@ import java.util.Iterator; import java.util.Map; import org.apache.commons.jcs.access.CacheAccess; -import org.onap.music.authentication.CachingUtil; import org.onap.music.eelf.logging.EELFLoggerDelegate; import org.onap.music.eelf.logging.format.AppMessages; import org.onap.music.eelf.logging.format.ErrorSeverity; diff --git a/src/main/java/org/onap/music/datastore/MusicDataStoreHandle.java b/src/main/java/org/onap/music/datastore/MusicDataStoreHandle.java index b4412bf6..d546a016 100644 --- a/src/main/java/org/onap/music/datastore/MusicDataStoreHandle.java +++ b/src/main/java/org/onap/music/datastore/MusicDataStoreHandle.java @@ -42,7 +42,7 @@ public class MusicDataStoreHandle { throw new IllegalStateException("Utility class"); } - public static MusicDataStore mDstoreHandle = null; + private static MusicDataStore mDstoreHandle = null; private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicDataStoreHandle.class); /** diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/JsonDelete.java b/src/main/java/org/onap/music/datastore/jsonobjects/JsonDelete.java index b98a391d..b9b82e08 100644 --- a/src/main/java/org/onap/music/datastore/jsonobjects/JsonDelete.java +++ b/src/main/java/org/onap/music/datastore/jsonobjects/JsonDelete.java @@ -39,7 +39,8 @@ public class JsonDelete { private List columns = null; private Map consistencyInfo; private Map conditions; - String ttl, timestamp; + private String ttl; + private String timestamp; @ApiModelProperty(value = "Conditions") 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 06a76f57..edb30857 100644 --- a/src/main/java/org/onap/music/datastore/jsonobjects/JsonLeasedLock.java +++ b/src/main/java/org/onap/music/datastore/jsonobjects/JsonLeasedLock.java @@ -30,8 +30,8 @@ import io.swagger.annotations.ApiModelProperty; @ApiModel(value = "JsonTable", description = "model for leased lock") @JsonIgnoreProperties(ignoreUnknown = true) public class JsonLeasedLock { - long leasePeriod; - String notifyUrl; + private long leasePeriod; + private String notifyUrl; @ApiModelProperty(value = "Lease period") public long getLeasePeriod() { diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/JsonLock.java b/src/main/java/org/onap/music/datastore/jsonobjects/JsonLock.java new file mode 100644 index 00000000..88e1c3f3 --- /dev/null +++ b/src/main/java/org/onap/music/datastore/jsonobjects/JsonLock.java @@ -0,0 +1,45 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.datastore.jsonobjects; + +import org.onap.music.lockingservice.cassandra.LockType; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel(value = "JsonTable", description = "model for leased lock") +@JsonIgnoreProperties(ignoreUnknown = true) +public class JsonLock { + private LockType locktype; + + @ApiModelProperty(value = "Type of music lock") + public LockType getLocktype() { + return this.locktype; + } + + public void setLockType(LockType locktype) { + this.locktype = 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 52e27be1..df6cc265 100644 --- a/src/main/java/org/onap/music/eelf/healthcheck/MusicHealthCheck.java +++ b/src/main/java/org/onap/music/eelf/healthcheck/MusicHealthCheck.java @@ -67,7 +67,7 @@ public class MusicHealthCheck { try { result = getAdminKeySpace(consistency, randomUUID); } catch (MusicServiceException e1) { - logger.error(EELFLoggerDelegate.errorLogger, e1, AppMessages.UNKNOWNERROR, ErrorSeverity.ERROR, ErrorTypes.UNKNOWN); + logger.error(EELFLoggerDelegate.errorLogger, e1, AppMessages.UNKNOWNERROR, ErrorSeverity.ERROR, ErrorTypes.UNKNOWN); } } else { logger.error("Error", e); diff --git a/src/main/java/org/onap/music/eelf/logging/MusicContainerFilter.java b/src/main/java/org/onap/music/eelf/logging/MusicContainerFilter.java new file mode 100644 index 00000000..23f29595 --- /dev/null +++ b/src/main/java/org/onap/music/eelf/logging/MusicContainerFilter.java @@ -0,0 +1,70 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.eelf.logging; + +import java.io.IOException; + +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; + +import org.springframework.stereotype.Component; + + +/** + * This filter filter/modifies outbound http responses just before sending back to client. + * + * @author sp931a + * + */ +@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"); + } + } + +} diff --git a/src/main/java/org/onap/music/eelf/logging/MusicLoggingServletFilter.java b/src/main/java/org/onap/music/eelf/logging/MusicLoggingServletFilter.java new file mode 100644 index 00000000..cb688c54 --- /dev/null +++ b/src/main/java/org/onap/music/eelf/logging/MusicLoggingServletFilter.java @@ -0,0 +1,205 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.eelf.logging; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.onap.music.authentication.AuthorizationError; +import org.onap.music.main.MusicUtil; + +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * + * This is the first filter in the chain to be executed before cadi + * authentication. The priority has been set in MusicApplication + * through filter registration bean + * + * The responsibility of this filter is to validate header values as per + * contract and write it to MDC and http response header back. + * + * + * @author sp931a + * + */ + +public class MusicLoggingServletFilter implements Filter { + + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicLoggingServletFilter.class); + // client transaction id, specific to client system, set in properties + public static final String CONVERSATION_ID = MusicUtil.getConversationIdPrefix() + "ConversationId"; + + // can be used as correlation-id in case of callback, also this can be passed to + // other services for tracking. + public static final String MESSAGE_ID = MusicUtil.getMessageIdPrefix() + "MessageId"; + + // client id would be the unique client source-system-id, i;e VALET or CONDUCTOR + // etc + public static final String CLIENT_ID = MusicUtil.getClientIdPrefix() + "ClientId"; + + // unique transaction of the source system + private static final String TRANSACTION_ID = MusicUtil.getTransIdPrefix() + "Transaction-Id"; + + public MusicLoggingServletFilter() throws ServletException { + super(); + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + 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()"); + + HttpServletRequest httpRequest = null; + HttpServletResponse httpResponse = null; + Map headerMap = null; + Map upperCaseHeaderMap = null; + + if (null != request && null != response) { + httpRequest = (HttpServletRequest) request; + httpResponse = (HttpServletResponse) response; + + headerMap = getHeadersInfo(httpRequest); + + // The custom header values automatically converted into lower case, not sure + // why ? So i had to covert all keys to upper case + // The response header back to client will have all custom header values as + // upper case. + upperCaseHeaderMap = headerMap.entrySet().stream() + .collect(Collectors.toMap(entry -> entry.getKey().toUpperCase(), entry -> entry.getValue())); + // Enable/disable keys are present in /opt/app/music/etc/music.properties + + if (Boolean.valueOf(MusicUtil.getTransIdRequired()) + && !upperCaseHeaderMap.containsKey(TRANSACTION_ID.toUpperCase())) { + populateError(httpResponse, "Transaction id '" + TRANSACTION_ID + + "' required on http header"); + return; + } else { + populateMDCAndResponseHeader(upperCaseHeaderMap, TRANSACTION_ID, "transactionId", + Boolean.valueOf(MusicUtil.getTransIdRequired()), httpResponse); + } + + if (Boolean.valueOf(MusicUtil.getConversationIdRequired()) + && !upperCaseHeaderMap.containsKey(CONVERSATION_ID.toUpperCase())) { + populateError(httpResponse, "Conversation Id '" + CONVERSATION_ID + + "' required on http header"); + return; + } else { + populateMDCAndResponseHeader(upperCaseHeaderMap, CONVERSATION_ID, "conversationId", + Boolean.valueOf(MusicUtil.getConversationIdRequired()), httpResponse); + } + + if (Boolean.valueOf(MusicUtil.getMessageIdRequired()) + && !upperCaseHeaderMap.containsKey(MESSAGE_ID.toUpperCase())) { + populateError(httpResponse, "Message Id '" + MESSAGE_ID + + "' required on http header"); + return; + } else { + populateMDCAndResponseHeader(upperCaseHeaderMap, MESSAGE_ID, "messageId", + Boolean.valueOf(MusicUtil.getMessageIdRequired()), httpResponse); + } + + if (Boolean.valueOf(MusicUtil.getClientIdRequired()) + && !upperCaseHeaderMap.containsKey(CLIENT_ID.toUpperCase())) { + populateError(httpResponse, "Client Id '" + CLIENT_ID + + "' required on http header"); + return; + } else { + populateMDCAndResponseHeader(upperCaseHeaderMap, CLIENT_ID, "clientId", + Boolean.valueOf(MusicUtil.getClientIdRequired()), httpResponse); + } + + } + + logger.info(EELFLoggerDelegate.applicationLogger, + "In MusicLogginServletFilter doFilter. Header values validated sucessfully"); + + chain.doFilter(request, response); + } + + private void populateError(HttpServletResponse httpResponse, String errMsg) throws IOException { + AuthorizationError authError = new AuthorizationError(); + authError.setResponseCode(HttpServletResponse.SC_BAD_REQUEST); + authError.setResponseMessage(errMsg); + + byte[] responseToSend = restResponseBytes(authError); + httpResponse.setHeader("Content-Type", "application/json"); + + // ideally the http response code should be 200, as this is a biz validation + // failure. For now, keeping it consistent with other places. + httpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST); + httpResponse.getOutputStream().write(responseToSend); + } + + private void populateMDCAndResponseHeader(Map headerMap, String idKey, String mdcKey, + boolean isRequired, HttpServletResponse httpResponse) throws ServletException, IOException { + + idKey = idKey.trim().toUpperCase(); + + // 1. setting the keys & value in MDC for future use 2.setting the values in + // http response header back to client. + if (isRequired && (headerMap.containsKey(idKey))) { + EELFLoggerDelegate.mdcPut(mdcKey, headerMap.get(idKey)); + httpResponse.addHeader(idKey, headerMap.get(idKey)); + } else { + // do nothing + } + } + + private Map getHeadersInfo(HttpServletRequest request) { + + Map map = new HashMap(); + + Enumeration headerNames = request.getHeaderNames(); + while (headerNames.hasMoreElements()) { + String key = (String) headerNames.nextElement(); + String value = request.getHeader(key); + map.put(key, value); + } + + return map; + } + + private byte[] restResponseBytes(AuthorizationError eErrorResponse) throws IOException { + String serialized = new ObjectMapper().writeValueAsString(eErrorResponse); + return serialized.getBytes(); + } +} 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 7ff6a4d5..3c3f7160 100644 --- a/src/main/java/org/onap/music/lockingservice/cassandra/CassaLockStore.java +++ b/src/main/java/org/onap/music/lockingservice/cassandra/CassaLockStore.java @@ -45,19 +45,8 @@ public class CassaLockStore { private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(CassaLockStore.class); private static String table_prepend_name = "lockQ_"; + private MusicDataStore dsHandle; - public class LockObject{ - public String lockRef; - public String createTime; - public String acquireTime; - public LockObject(String lockRef, String createTime, String acquireTime) { - this.lockRef = lockRef; - this.acquireTime = acquireTime; - this.createTime = createTime; - - } - } - MusicDataStore dsHandle; public CassaLockStore() { dsHandle = new MusicDataStore(); } @@ -65,7 +54,50 @@ public class CassaLockStore { public CassaLockStore(MusicDataStore dsHandle) { this.dsHandle=dsHandle; } - + public class LockObject{ + private boolean isLockOwner; + private String lockRef; + private String createTime; + private String acquireTime; + private LockType locktype; + public LockObject(boolean isLockOwner, String lockRef, String createTime, String acquireTime, LockType locktype) { + this.setIsLockOwner(isLockOwner); + this.setLockRef(lockRef); + this.setAcquireTime(acquireTime); + this.setCreateTime(createTime); + this.setLocktype(locktype); + } + public boolean getIsLockOwner() { + return isLockOwner; + } + public void setIsLockOwner(boolean isLockOwner) { + this.isLockOwner = isLockOwner; + } + public String getAcquireTime() { + return acquireTime; + } + public void setAcquireTime(String acquireTime) { + this.acquireTime = acquireTime; + } + public String getCreateTime() { + return createTime; + } + public void setCreateTime(String createTime) { + this.createTime = createTime; + } + public String getLockRef() { + return lockRef; + } + public void setLockRef(String lockRef) { + this.lockRef = lockRef; + } + public LockType getLocktype() { + return locktype; + } + public void setLocktype(LockType locktype) { + this.locktype = locktype; + } + } /** * @@ -81,7 +113,8 @@ public class CassaLockStore { "Create lock queue/table for " + keyspace+"."+table); table = table_prepend_name+table; String tabQuery = "CREATE TABLE IF NOT EXISTS "+keyspace+"."+table - + " ( key text, lockReference bigint, createTime text, acquireTime text, guard bigint static, PRIMARY KEY ((key), lockReference) ) " + + " ( key text, lockReference bigint, createTime text, acquireTime text, guard bigint static, " + + "writeLock boolean, PRIMARY KEY ((key), lockReference) ) " + "WITH CLUSTERING ORDER BY (lockReference ASC);"; PreparedQueryObject queryObject = new PreparedQueryObject(); @@ -100,16 +133,16 @@ public class CassaLockStore { * @throws MusicServiceException * @throws MusicQueryException */ - public String genLockRefandEnQueue(String keyspace, String table, String lockName) throws MusicServiceException, MusicQueryException, MusicLockingException { - return genLockRefandEnQueue(keyspace, table, lockName, 0); + public String genLockRefandEnQueue(String keyspace, String table, String lockName, LockType locktype) throws MusicServiceException, MusicQueryException, MusicLockingException { + return genLockRefandEnQueue(keyspace, table, lockName, locktype, 0); } - private String genLockRefandEnQueue(String keyspace, String table, String lockName, int count) throws MusicServiceException, MusicQueryException, MusicLockingException { + private String genLockRefandEnQueue(String keyspace, String table, String lockName, LockType locktype, int count) throws MusicServiceException, MusicQueryException, MusicLockingException { logger.info(EELFLoggerDelegate.applicationLogger, - "Create lock reference for " + keyspace + "." + table + "." + lockName); + "Create " + locktype + " lock reference for " + keyspace + "." + table + "." + lockName); String lockTable =""; lockTable = table_prepend_name+table; - + PreparedQueryObject queryObject = new PreparedQueryObject(); @@ -137,7 +170,7 @@ public class CassaLockStore { " UPDATE " + keyspace + "." + lockTable + " SET guard=? WHERE key=? IF guard = " + (prevGuard == 0 ? "NULL" : "?") +";" + " INSERT INTO " + keyspace + "." + lockTable + - "(key, lockReference, createTime, acquireTime) VALUES (?,?,?,?) IF NOT EXISTS; APPLY BATCH;"; + "(key, lockReference, createTime, acquireTime, writeLock) VALUES (?,?,?,?,?) IF NOT EXISTS; APPLY BATCH;"; queryObject.addValue(lockRef); queryObject.addValue(lockName); @@ -148,23 +181,25 @@ public class CassaLockStore { queryObject.addValue(lockRef); queryObject.addValue(String.valueOf(lockEpochMillis)); queryObject.addValue("0"); + queryObject.addValue(locktype==LockType.WRITE ? true : false ); queryObject.appendQueryString(insQuery); boolean pResult = dsHandle.executePut(queryObject, "critical"); - if (!pResult) {//couldn't create lock ref, retry + if (!pResult) {// couldn't create lock ref, retry count++; - if (count>MusicUtil.getRetryCount()) { + if (count > MusicUtil.getRetryCount()) { logger.warn(EELFLoggerDelegate.applicationLogger, "Unable to create lock reference"); throw new MusicLockingException("Unable to create lock reference"); } - return genLockRefandEnQueue(keyspace, table, lockName, count); + return genLockRefandEnQueue(keyspace, table, lockName, locktype, count); } return "$" + keyspace + "." + table + "." + lockName + "$" + String.valueOf(lockRef); } - + /** * Returns a result set containing the list of clients waiting for a particular lock + * * @param keyspace * @param table * @param key @@ -175,22 +210,23 @@ public class CassaLockStore { public List getLockQueue(String keyspace, String table, String key) throws MusicServiceException, MusicQueryException { logger.info(EELFLoggerDelegate.applicationLogger, - "Getting the queue for " + keyspace+"."+table+"."+key); - table = table_prepend_name+table; + "Getting the queue for " + keyspace + "." + table + "." + key); + table = table_prepend_name + table; String selectQuery = "select * from " + keyspace + "." + table + " where key='" + key + "';"; PreparedQueryObject queryObject = new PreparedQueryObject(); queryObject.appendQueryString(selectQuery); ResultSet rs = dsHandle.executeOneConsistencyGet(queryObject); ArrayList lockQueue = new ArrayList<>(); - for (Row row: rs) { + for (Row row : rs) { lockQueue.add(Long.toString(row.getLong("lockReference"))); } return lockQueue; } - - + + /** * Returns a result set containing the list of clients waiting for a particular lock + * * @param keyspace * @param table * @param key @@ -201,90 +237,212 @@ public class CassaLockStore { public long getLockQueueSize(String keyspace, String table, String key) throws MusicServiceException, MusicQueryException { logger.info(EELFLoggerDelegate.applicationLogger, - "Getting the queue size for " + keyspace+"."+table+"."+key); - table = table_prepend_name+table; + "Getting the queue size for " + keyspace + "." + table + "." + key); + table = table_prepend_name + table; String selectQuery = "select count(*) from " + keyspace + "." + table + " where key='" + key + "';"; PreparedQueryObject queryObject = new PreparedQueryObject(); queryObject.appendQueryString(selectQuery); - ResultSet rs = dsHandle.executeOneConsistencyGet(queryObject); - return rs.one().getLong("count"); - } + ResultSet rs = dsHandle.executeOneConsistencyGet(queryObject); + return rs.one().getLong("count"); + } /** * This method returns the top of lock table/queue for the key. + * * @param keyspace of the application. * @param table of the application. * @param key is the primary key of the application table - * @return the UUID lock reference. Returns null if there is no owner or the lock doesn't exist + * @return the UUID lock reference. Returns LockObject.isLockOwner=false if there is no owner or the + * lock doesn't exist * @throws MusicServiceException * @throws MusicQueryException */ - public LockObject peekLockQueue(String keyspace, String table, String key) throws MusicServiceException, MusicQueryException{ + public LockObject peekLockQueue(String keyspace, String table, String key) + throws MusicServiceException, MusicQueryException { logger.info(EELFLoggerDelegate.applicationLogger, - "Peek in lock table for " + keyspace+"."+table+"."+key); - table = table_prepend_name+table; - String selectQuery = "select * from "+keyspace+"."+table+" where key='"+key+"' LIMIT 1;"; + "Peek in lock table for " + keyspace + "." + table + "." + key); + table = table_prepend_name + table; + String selectQuery = "select * from " + keyspace + "." + table + " where key='" + key + "' LIMIT 1;"; PreparedQueryObject queryObject = new PreparedQueryObject(); queryObject.appendQueryString(selectQuery); ResultSet results = dsHandle.executeOneConsistencyGet(queryObject); Row row = results.one(); - if (row==null || row.isNull("lockReference")) { + if (row == null || row.isNull("lockReference")) { + return new LockObject(false, null, null, null, null); + } + String lockReference = "" + row.getLong("lockReference"); + String createTime = row.getString("createTime"); + String acquireTime = row.getString("acquireTime"); + LockType locktype = row.getBool("writeLock") ? LockType.WRITE : LockType.READ; + + return new LockObject(true, lockReference, createTime, acquireTime, locktype); + } + + public List getCurrentLockHolders(String keyspace, String table, String key) + throws MusicServiceException, MusicQueryException { + logger.info(EELFLoggerDelegate.applicationLogger, + "Getting lockholders in lock table for " + keyspace + "." + table + "." + key); + table = table_prepend_name + table; + String selectQuery = "select * from " + keyspace + "." + table + " where key=?;"; + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString(selectQuery); + queryObject.addValue(key); + ResultSet rs = dsHandle.executeOneConsistencyGet(queryObject); + + List lockHolders = new ArrayList<>(); + boolean topOfQueue = true; + for (Row row : rs) { + String lockReference = "" + row.getLong("lockReference"); + if (row.getBool("writeLock")) { + if (topOfQueue) { + lockHolders.add(lockReference); + break; + } else { + break; + } + } + // read lock + lockHolders.add(lockReference); + + topOfQueue = false; + } + return lockHolders; + } + + /** + * Determine if the lock is a valid current lock holder. + * + * @param keyspace + * @param table + * @param key + * @param lockRef + * @return true if lockRef is a lock owner of key + * @throws MusicServiceException + * @throws MusicQueryException + */ + public boolean isLockOwner(String keyspace, String table, String key, String lockRef) + throws MusicServiceException, MusicQueryException { + logger.info(EELFLoggerDelegate.applicationLogger, + "Checking in lock table for " + keyspace + "." + table + "." + key); + table = table_prepend_name + table; + String selectQuery = + "select * from " + keyspace + "." + table + " where key=?;"; + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString(selectQuery); + queryObject.addValue(key); + ResultSet rs = dsHandle.executeOneConsistencyGet(queryObject); + + boolean topOfQueue = true; + for (Row row : rs) { + String lockReference = "" + row.getLong("lockReference"); + if (row.getBool("writeLock")) { + if (topOfQueue && lockRef.equals(lockReference)) { + return true; + } else { + return false; + } + } + if (lockRef.equals(lockReference)) { + return true; + } + topOfQueue = false; + } + logger.info(EELFLoggerDelegate.applicationLogger, "Could not find " + lockRef + + " in the lock queue. It has expired and no longer exists."); + return false; + } + + /** + * Determine if the lock is a valid current lock holder. + * + * @param keyspace + * @param table + * @param key + * @param lockRef + * @return true if lockRef is a lock owner of key + * @throws MusicServiceException + * @throws MusicQueryException + */ + public LockObject getLockInfo(String keyspace, String table, String key, String lockRef) + throws MusicServiceException, MusicQueryException { + logger.info(EELFLoggerDelegate.applicationLogger, + "Checking in lock table for " + keyspace + "." + table + "." + key); + String lockQ_table = table_prepend_name + table; + String selectQuery = + "select * from " + keyspace + "." + lockQ_table + " where key=? and lockReference=?;"; + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString(selectQuery); + queryObject.addValue(key); + queryObject.addValue(Long.parseLong(lockRef)); + ResultSet rs = dsHandle.executeOneConsistencyGet(queryObject); + Row row = rs.one(); + if (row == null || row.isNull("lockReference")) { return null; } + String lockReference = "" + row.getLong("lockReference"); String createTime = row.getString("createTime"); String acquireTime = row.getString("acquireTime"); + LockType locktype = row.getBool("writeLock") ? LockType.WRITE : LockType.READ; + boolean isLockOwner = isLockOwner(keyspace, table, key, lockRef); - return new LockObject(lockReference, createTime,acquireTime); + return new LockObject(isLockOwner, lockReference, createTime, acquireTime, locktype); } - - + + + /** - * This method removes the lock ref from the lock table/queue for the key. - * @param keyspace of the application. - * @param table of the application. + * This method removes the lock ref from the lock table/queue for the key. + * + * @param keyspace of the application. + * @param table of the application. * @param key is the primary key of the application table * @param lockReference the lock reference that needs to be dequeued. * @throws MusicServiceException * @throws MusicQueryException - * @throws MusicLockingException - */ - public void deQueueLockRef(String keyspace, String table, String key, String lockReference, int n) throws MusicServiceException, MusicQueryException, MusicLockingException{ - String prependTable = table_prepend_name+table; + * @throws MusicLockingException + */ + public void deQueueLockRef(String keyspace, String table, String key, String lockReference, int n) + throws MusicServiceException, MusicQueryException, MusicLockingException { + String prependTable = table_prepend_name + table; PreparedQueryObject queryObject = new PreparedQueryObject(); - Long lockReferenceL = Long.parseLong(lockReference.substring(lockReference.lastIndexOf("$")+1)); - String deleteQuery = "delete from "+keyspace+"."+prependTable+" where key='"+key+"' AND lockReference ="+lockReferenceL+" IF EXISTS;"; + Long lockReferenceL = Long.parseLong(lockReference.substring(lockReference.lastIndexOf("$") + 1)); + String deleteQuery = "delete from " + keyspace + "." + prependTable + " where key='" + key + + "' AND lockReference =" + lockReferenceL + " IF EXISTS;"; queryObject.appendQueryString(deleteQuery); logger.info(EELFLoggerDelegate.applicationLogger, "Removing lock for key: "+key+ " and reference: "+lockReference); try { - dsHandle.executePut(queryObject, "critical"); - logger.info(EELFLoggerDelegate.applicationLogger, "Lock removed for key: "+key+ " and reference: "+lockReference); - }catch(MusicServiceException ex) { - logger.error(logger, ex.getMessage(),ex); - logger.error(EELFLoggerDelegate.applicationLogger,"Exception while deQueueLockRef for lockname: " + key + " reference:" +lockReference); - if(n>1) { + dsHandle.executePut(queryObject, "critical"); + logger.info(EELFLoggerDelegate.applicationLogger, + "Lock removed for key: " + key + " and reference: " + lockReference); + } catch (MusicServiceException ex) { + logger.error(logger, ex.getMessage(), ex); + logger.error(EELFLoggerDelegate.applicationLogger, + "Exception while deQueueLockRef for lockname: " + key + " reference:" + lockReference); + if (n > 1) { logger.info(EELFLoggerDelegate.applicationLogger, "Trying again..."); - deQueueLockRef(keyspace, table, key, lockReference, n-1); - } - else { - logger.error(EELFLoggerDelegate.applicationLogger,"deQueueLockRef failed for lockname: " + key + " reference:" +lockReference); - logger.error(logger, ex.getMessage(),ex); - throw new MusicLockingException("Error while deQueueLockRef: "+ex.getMessage()); + deQueueLockRef(keyspace, table, key, lockReference, n - 1); + } else { + logger.error(EELFLoggerDelegate.applicationLogger, + "deQueueLockRef failed for lockname: " + key + " reference:" + lockReference); + logger.error(logger, ex.getMessage(), ex); + throw new MusicLockingException("Error while deQueueLockRef: " + ex.getMessage()); } } } - - public void updateLockAcquireTime(String keyspace, String table, String key, String lockReference) throws MusicServiceException, MusicQueryException{ - table = table_prepend_name+table; + + public void updateLockAcquireTime(String keyspace, String table, String key, String lockReference) + throws MusicServiceException, MusicQueryException { + table = table_prepend_name + table; PreparedQueryObject queryObject = new PreparedQueryObject(); Long lockReferenceL = Long.parseLong(lockReference); - String updateQuery = "update "+keyspace+"."+table+" set acquireTime='"+ System.currentTimeMillis()+"' where key='"+key+"' AND lockReference = "+lockReferenceL+" IF EXISTS;"; + String updateQuery = "update " + keyspace + "." + table + " set acquireTime='" + System.currentTimeMillis() + + "' where key='" + key + "' AND lockReference = " + lockReferenceL + " IF EXISTS;"; queryObject.appendQueryString(updateQuery); - dsHandle.executePut(queryObject, "eventual"); + dsHandle.executePut(queryObject, "eventual"); - } - + } } diff --git a/src/main/java/org/onap/music/lockingservice/cassandra/LockType.java b/src/main/java/org/onap/music/lockingservice/cassandra/LockType.java new file mode 100644 index 00000000..139d5f3f --- /dev/null +++ b/src/main/java/org/onap/music/lockingservice/cassandra/LockType.java @@ -0,0 +1,30 @@ +/* + * ============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.lockingservice.cassandra; + + +public enum LockType { + READ, WRITE; +} + diff --git a/src/main/java/org/onap/music/lockingservice/cassandra/MusicLockState.java b/src/main/java/org/onap/music/lockingservice/cassandra/MusicLockState.java index 8f3c0d6d..00187dc8 100644 --- a/src/main/java/org/onap/music/lockingservice/cassandra/MusicLockState.java +++ b/src/main/java/org/onap/music/lockingservice/cassandra/MusicLockState.java @@ -44,11 +44,10 @@ public class MusicLockState implements Serializable { };// captures the state of the lock private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicLockState.class); - LockStatus lockStatus; - boolean needToSyncQuorum = false; - String lockHolder; - long leasePeriod = Long.MAX_VALUE, leaseStartTime = -1; - + private LockStatus lockStatus; + private boolean needToSyncQuorum = false; + private String lockHolder; + private long leasePeriod = Long.MAX_VALUE, leaseStartTime = -1; private String errorMessage = null; public MusicLockState(String errorMessage) { diff --git a/src/main/java/org/onap/music/main/MusicCore.java b/src/main/java/org/onap/music/main/MusicCore.java index df718379..324f4681 100644 --- a/src/main/java/org/onap/music/main/MusicCore.java +++ b/src/main/java/org/onap/music/main/MusicCore.java @@ -24,7 +24,6 @@ package org.onap.music.main; import java.util.List; import java.util.Map; - import org.onap.music.datastore.Condition; import org.onap.music.datastore.PreparedQueryObject; import org.onap.music.eelf.logging.EELFLoggerDelegate; @@ -32,105 +31,126 @@ import org.onap.music.exceptions.MusicLockingException; import org.onap.music.exceptions.MusicQueryException; import org.onap.music.exceptions.MusicServiceException; import org.onap.music.lockingservice.cassandra.CassaLockStore; +import org.onap.music.lockingservice.cassandra.LockType; import org.onap.music.lockingservice.cassandra.MusicLockState; import org.onap.music.service.MusicCoreService; import org.onap.music.service.impl.MusicCassaCore; - import com.datastax.driver.core.ResultSet; public class MusicCore { private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicCore.class); - private static boolean unitTestRun=true; - + private static boolean unitTestRun = true; + private static MusicCoreService musicCore = MusicUtil.getMusicCoreService(); public static CassaLockStore mLockHandle; - - + + /** * Acquire lock + * * @param fullyQualifiedKey DO NOT RELY ON THIS KEY WORKING. INCLUDE THE KEY IN THE LOCKID. * @param lockId - the full lock id (key + lockRef) * @return - * @throws MusicLockingException + * @throws MusicLockingException * @throws MusicQueryException * @throws MusicServiceException */ - public static ReturnType acquireLock(String fullyQualifiedKey, String lockId) - throws MusicLockingException, MusicQueryException, MusicServiceException { + public static ReturnType acquireLock(String fullyQualifiedKey, String lockId) + throws MusicLockingException, MusicQueryException, MusicServiceException { return musicCore.acquireLock(fullyQualifiedKey, lockId); } - - public static ReturnType acquireLockWithLease(String key, String lockId, long leasePeriod) - throws MusicLockingException, MusicQueryException, MusicServiceException { + + public static ReturnType acquireLockWithLease(String key, String lockId, long leasePeriod) + throws MusicLockingException, MusicQueryException, MusicServiceException { return musicCore.acquireLockWithLease(key, lockId, leasePeriod); } - + public static String createLockReference(String fullyQualifiedKey) throws MusicLockingException { return musicCore.createLockReference(fullyQualifiedKey); } - - public static ResultType createTable(String keyspace, String table, PreparedQueryObject tableQueryObject, - String consistency) throws MusicServiceException { + + public static String createLockReference(String fullyQualifiedKey, LockType locktype) throws MusicLockingException { + return musicCore.createLockReference(fullyQualifiedKey, locktype); + } + + public static ResultType createTable(String keyspace, String table, PreparedQueryObject tableQueryObject, + String consistency) throws MusicServiceException { return musicCore.createTable(keyspace, table, tableQueryObject, consistency); } - + public static ResultSet quorumGet(PreparedQueryObject query) { - return musicCore.quorumGet(query); + return musicCore.quorumGet(query); } - + + /** + * Gets the top of queue for fullyQualifiedKey + * + * @param fullyQualifiedKey + * @return + */ public static String whoseTurnIsIt(String fullyQualifiedKey) { return musicCore.whoseTurnIsIt(fullyQualifiedKey); } - + + /** + * Gets the current lockholder(s) for fullyQualifiedKey + * + * @param fullyQualifiedKey + * @return + */ + public static List getCurrentLockHolders(String fullyQualifiedKey) { + return musicCore.getCurrentLockHolders(fullyQualifiedKey); + } + public static void destroyLockRef(String lockId) throws MusicLockingException { musicCore.destroyLockRef(lockId); } - + public static ReturnType eventualPut(PreparedQueryObject queryObject) { return musicCore.eventualPut(queryObject); } - - public static ReturnType eventualPut_nb(PreparedQueryObject queryObject,String keyspace, - String tablename,String primaryKey) { + + public static ReturnType eventualPut_nb(PreparedQueryObject queryObject, String keyspace, String tablename, + String primaryKey) { return musicCore.eventualPut_nb(queryObject, keyspace, tablename, primaryKey); } - + public static ReturnType criticalPut(String keyspace, String table, String primaryKeyValue, PreparedQueryObject queryObject, String lockReference, Condition conditionInfo) { return musicCore.criticalPut(keyspace, table, primaryKeyValue, queryObject, lockReference, conditionInfo); } - - public static ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) - throws MusicServiceException { + + public static ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) + throws MusicServiceException { return musicCore.nonKeyRelatedPut(queryObject, consistency); } - - public static ResultSet get(PreparedQueryObject queryObject) throws MusicServiceException{ + + public static ResultSet get(PreparedQueryObject queryObject) throws MusicServiceException { return musicCore.get(queryObject); } - + public static ResultSet criticalGet(String keyspace, String table, String primaryKeyValue, PreparedQueryObject queryObject, String lockReference) throws MusicServiceException { - return musicCore.criticalGet(keyspace, table, primaryKeyValue, queryObject,lockReference); + return musicCore.criticalGet(keyspace, table, primaryKeyValue, queryObject, lockReference); } - + public static ReturnType atomicPut(String keyspaceName, String tableName, String primaryKey, - PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException, - MusicQueryException,MusicServiceException { + PreparedQueryObject queryObject, Condition conditionInfo) + throws MusicLockingException, MusicQueryException, MusicServiceException { return musicCore.atomicPut(keyspaceName, tableName, primaryKey, queryObject, conditionInfo); } - + public static ResultSet atomicGet(String keyspaceName, String tableName, String primaryKey, PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException, MusicQueryException { return musicCore.atomicGet(keyspaceName, tableName, primaryKey, queryObject); } - + public static List getLockQueue(String fullyQualifiedKey) throws MusicServiceException, MusicQueryException, MusicLockingException { return musicCore.getLockQueue(fullyQualifiedKey); } - + public static long getLockQueueSize(String fullyQualifiedKey) throws MusicServiceException, MusicQueryException, MusicLockingException { return musicCore.getLockQueueSize(fullyQualifiedKey); @@ -139,12 +159,12 @@ public class MusicCore { public static void deleteLock(String lockName) throws MusicLockingException { musicCore.deleteLock(lockName); } - - public static ReturnType atomicPutWithDeleteLock(String keyspaceName, String tableName, - String primaryKey, PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException { + + public static ReturnType atomicPutWithDeleteLock(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException { return musicCore.atomicPutWithDeleteLock(keyspaceName, tableName, primaryKey, queryObject, conditionInfo); } - + public static ResultSet atomicGetWithDeleteLock(String keyspaceName, String tableName, String primaryKey, PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException { return musicCore.atomicGetWithDeleteLock(keyspaceName, tableName, primaryKey, queryObject); @@ -157,6 +177,5 @@ public class MusicCore { public static MusicLockState releaseLock(String lockId, boolean voluntaryRelease) throws MusicLockingException { return musicCore.releaseLock(lockId, voluntaryRelease); } - } diff --git a/src/main/java/org/onap/music/main/MusicUtil.java b/src/main/java/org/onap/music/main/MusicUtil.java index da5da239..2ad7117b 100755 --- a/src/main/java/org/onap/music/main/MusicUtil.java +++ b/src/main/java/org/onap/music/main/MusicUtil.java @@ -74,6 +74,7 @@ import com.sun.jersey.core.util.Base64; public class MusicUtil { private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicUtil.class); + // Consistancy Constants public static final String ATOMIC = "atomic"; public static final String EVENTUAL = "eventual"; public static final String CRITICAL = "critical"; @@ -82,55 +83,54 @@ public class MusicUtil { public static final String QUORUM = "quorum"; public static final String ONE = "one"; public static final String ATOMICDELETELOCK = "atomic_delete_lock"; - public static final String DEFAULTKEYSPACENAME = "TBD"; + + // Header Constants private static final String XLATESTVERSION = "X-latestVersion"; private static final String XMINORVERSION = "X-minorVersion"; private static final String XPATCHVERSION = "X-patchVersion"; + public static final String AUTHORIZATION = "Authorization"; + + // CQL Constants public static final String SELECT = "select"; public static final String INSERT = "insert"; public static final String UPDATE = "update"; public static final String UPSERT = "upsert"; public static final String USERID = "userId"; - public static final String PASSWORD = "password"; + public static final String PASSWORD = ""; public static final String CASSANDRA = "cassandra"; - public static final String AUTHORIZATION = "Authorization"; - private static final String LOCALHOST = "localhost"; private static final String PROPERTIES_FILE = "/opt/app/music/etc/music.properties"; + public static final String DEFAULTKEYSPACENAME = "TBD"; - private static int myId = 0; - private static ArrayList allIds = new ArrayList<>(); - private static String publicIp = ""; - private static ArrayList allPublicIps = new ArrayList<>(); - private static String myZkHost = LOCALHOST; 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; + private static int retryCount = 3; private static int cacheObjectMaxLife = -1; private static String lockUsing = MusicUtil.CASSANDRA; private static boolean isCadi = false; private static boolean isKeyspaceActive = false; - private static boolean debug = true; private static String version = "0.0.0"; private static String build = ""; - private static String musicRestIp = LOCALHOST; + private static String musicPropertiesFilePath = PROPERTIES_FILE; - private static long defaultLockLeasePeriod = 6000; - private static int retryCount = 3; 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"}; + "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[] cosistencyLevel = new String[] { "ALL","EACH_QUORUM","QUORUM","LOCAL_QUORUM","ONE","TWO", "THREE","LOCAL_ONE","ANY","SERIAL","LOCAL_SERIAL"}; private static final Map consistencyName = new HashMap<>(); - static { consistencyName.put("ONE",ConsistencyLevel.ONE); consistencyName.put("TWO",ConsistencyLevel.TWO); @@ -143,23 +143,27 @@ public class MusicUtil { consistencyName.put("LOCAL_ONE",ConsistencyLevel.LOCAL_ONE); consistencyName.put("LOCAL_SERIAL",ConsistencyLevel.LOCAL_SERIAL); } - private static String cassName = "cassandra"; private static String cassPwd; private static String aafEndpointUrl = null; - public static ConcurrentMap zkNodeMap = new ConcurrentHashMap<>(); 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"; - - public static final long MusicEternityEpochMillis = 1533081600000L; // Wednesday, August 1, 2018 12:00:00 AM + 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"; public static String getLockUsing() { return lockUsing; @@ -266,69 +270,6 @@ public class MusicUtil { MusicUtil.aafEndpointUrl = aafEndpointUrl; } - /** - * - * @return - */ - public static int getMyId() { - return myId; - } - - /** - * - * @param myId - */ - public static void setMyId(int myId) { - MusicUtil.myId = myId; - } - - /** - * - * @return - */ - public static List getAllIds() { - return allIds; - } - - /** - * - * @param allIds - */ - public static void setAllIds(List allIds) { - MusicUtil.allIds = (ArrayList) allIds; - } - - /** - * - * @return - */ - public static String getPublicIp() { - return publicIp; - } - - /** - * - * @param publicIp - */ - public static void setPublicIp(String publicIp) { - MusicUtil.publicIp = publicIp; - } - - /** - * - * @return - */ - public static List getAllPublicIps() { - return allPublicIps; - } - - /** - * - * @param allPublicIps - */ - public static void setAllPublicIps(List allPublicIps) { - MusicUtil.allPublicIps = (ArrayList) allPublicIps; - } /** * Returns An array of property names that should be in the Properties @@ -337,25 +278,7 @@ public class MusicUtil { * @return */ public static String[] getPropkeys() { - return propKeys; - } - - /** - * Get MusicRestIp - default = localhost property file value - music.rest.ip - * - * @return - */ - public static String getMusicRestIp() { - return musicRestIp; - } - - /** - * Set MusicRestIp - * - * @param musicRestIp - */ - public static void setMusicRestIp(String musicRestIp) { - MusicUtil.musicRestIp = musicRestIp; + return propKeys.clone(); } /** @@ -897,5 +820,134 @@ public class MusicUtil { return uuid; } + private static String checkPrefix(String prefix){ + if (prefix == null || "".equals(prefix) || prefix.endsWith("-")) { + return prefix; + } else { + return prefix + "-"; + } + } + + /** + * @return the transIdPrefix + */ + public static String getTransIdPrefix() { + return transIdPrefix; + } + + /** + * @param transIdPrefix the transIdPrefix to set + */ + public static void setTransIdPrefix(String transIdPrefix) { + MusicUtil.transIdPrefix = checkPrefix(transIdPrefix); + } + + /** + * @return the conversationIdPrefix + */ + public static String getConversationIdPrefix() { + return conversationIdPrefix; + } + + /** + * @param conversationIdPrefix the conversationIdPrefix to set + */ + public static void setConversationIdPrefix(String conversationIdPrefix) { + MusicUtil.conversationIdPrefix = checkPrefix(conversationIdPrefix); + } + + /** + * @return the clientIdPrefix + */ + public static String getClientIdPrefix() { + return clientIdPrefix; + } + + /** + * @param clientIdPrefix the clientIdPrefix to set + */ + public static void setClientIdPrefix(String clientIdPrefix) { + MusicUtil.clientIdPrefix = checkPrefix(clientIdPrefix); + } + + /** + * @return the messageIdPrefix + */ + public static String getMessageIdPrefix() { + return messageIdPrefix; + } + + /** + * @param messageIdPrefix the messageIdPrefix to set + */ + public static void setMessageIdPrefix(String messageIdPrefix) { + MusicUtil.messageIdPrefix = checkPrefix(messageIdPrefix); + } + + /** + * @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; + } + + + } diff --git a/src/main/java/org/onap/music/main/PropertiesLoader.java b/src/main/java/org/onap/music/main/PropertiesLoader.java index af4e14e3..c20ce5c5 100644 --- a/src/main/java/org/onap/music/main/PropertiesLoader.java +++ b/src/main/java/org/onap/music/main/PropertiesLoader.java @@ -52,27 +52,12 @@ public class PropertiesLoader implements InitializingBean { @Value("${build}") public String build; - @Value("${music.rest.ip}") - public String musicRestIp; - @Value("${music.properties}") public String musicProperties; @Value("${lock.lease.period}") public String lockLeasePeriod; - @Value("${public.ip}") - public String publicIp; - - @Value("${my.id}") - public String myId; - - @Value("${all.ids}") - public String allIds; - - @Value("${all.public.ips}") - public String allPublicIps; - @Value("${cassandra.user}") public String cassandraUser; @@ -115,6 +100,30 @@ public class PropertiesLoader implements InitializingBean { @Value("${retry.count}") public String rertryCount; + @Value("${transId.header.prefix}") + private String transIdPrefix; + + @Value("${conversation.header.prefix}") + private String conversationIdPrefix; + + @Value("${clientId.header.prefix}") + private String clientIdPrefix; + + @Value("${messageId.header.prefix}") + private String messageIdPrefix; + + @Value("${transId.header.required}") + private String transIdRequired; + + @Value("${conversation.header.required}") + private String conversationIdRequired; + + @Value("${clientId.header.required}") + private String clientIdRequired; + + @Value("${messageId.header.required}") + private String messageIdRequired; + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(PropertiesLoader.class); @Bean @@ -145,19 +154,6 @@ public class PropertiesLoader implements InitializingBean { if (adminUsername != null && !adminUsername.equals("${admin.username}")) { MusicUtil.setAdminId(adminUsername); } - if (allIds != null && !allIds.equals("${all.ids}")) { - String[] ids = allIds.split(":"); - MusicUtil.setAllIds(new ArrayList(Arrays.asList(ids))); - } - if (allPublicIps != null && !allPublicIps.equals("${all.public.ips}")) { - String[] ips = allPublicIps.split(":"); - if (ips.length == 1) { - // Future use - } else if (ips.length > 1) { - MusicUtil.setAllPublicIps( - new ArrayList(Arrays.asList(ips))); - } - } if (cassandraPort != null && !cassandraPort.equals("${cassandra.port}")) { MusicUtil.setCassandraPort(Integer.parseInt(cassandraPort)); } @@ -182,24 +178,15 @@ public class PropertiesLoader implements InitializingBean { if (musicProperties != null && !musicProperties.equals("${music.properties}")) { MusicUtil.setMusicPropertiesFilePath(musicProperties); } - if (musicRestIp != null && !musicRestIp.equals("${music.rest.ip}")) { - MusicUtil.setMusicRestIp(musicRestIp); - } if (cassandraHost != null && !cassandraHost.equals("${cassandra.host}")) { MusicUtil.setMyCassaHost(cassandraHost); } - if (myId != null && !myId.equals("${my.id}")) { - MusicUtil.setMyId(Integer.parseInt(myId)); - } 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 (allPublicIps != null && !allPublicIps.equals("${public.ip}")) { - MusicUtil.setPublicIp(allPublicIps); - } if (version != null && !version.equals("${version}")) { MusicUtil.setVersion(version); } @@ -215,6 +202,39 @@ public class PropertiesLoader implements InitializingBean { if (isKeyspaceActive != null && !isKeyspaceActive.equals("${keyspace.active}")) { MusicUtil.setKeyspaceActive(Boolean.parseBoolean(isKeyspaceActive)); } + + + if(transIdPrefix!=null) { + MusicUtil.setTransIdPrefix(transIdPrefix); + } + + if(conversationIdPrefix!=null) { + MusicUtil.setConversationIdPrefix(conversationIdPrefix); + } + + if(clientIdPrefix!=null) { + MusicUtil.setClientIdPrefix(clientIdPrefix); + } + + if(messageIdPrefix!=null) { + MusicUtil.setMessageIdPrefix(messageIdPrefix); + } + + if(transIdRequired!=null) { + MusicUtil.setTransIdRequired(transIdRequired); + } + + if(conversationIdRequired!=null) { + MusicUtil.setConversationIdRequired(conversationIdRequired); + } + + if(clientIdRequired!=null) { + MusicUtil.setClientIdRequired(clientIdRequired); + } + + if(messageIdRequired!=null) { + MusicUtil.setMessageIdRequired(messageIdRequired); + } } 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 66fec9c2..2c419e18 100644 --- a/src/main/java/org/onap/music/response/jsonobjects/JsonResponse.java +++ b/src/main/java/org/onap/music/response/jsonobjects/JsonResponse.java @@ -22,7 +22,9 @@ package org.onap.music.response.jsonobjects; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.onap.music.lockingservice.cassandra.MusicLockState.LockStatus; @@ -52,7 +54,7 @@ public class JsonResponse { /* Locking fields */ private String lock; private LockStatus lockStatus; - private String lockHolder; + private List lockHolders; private String lockLease; @@ -209,8 +211,8 @@ public class JsonResponse { * @return the lockHolder */ @ApiModelProperty(value = "Holder of the Lock") - public String getLockHolder() { - return lockHolder; + public List getLockHolder() { + return lockHolders; } /** @@ -218,10 +220,15 @@ public class JsonResponse { * @param lockHolder */ public JsonResponse setLockHolder(String lockHolder) { - this.lockHolder = lockHolder; + this.lockHolders = new ArrayList(); + this.lockHolders.add(lockHolder); return this; } + public JsonResponse setLockHolder(List lockHolders) { + this.lockHolders = lockHolders; + return this; + } /** @@ -274,8 +281,13 @@ public class JsonResponse { if (lockStatus != null) { lockMap.put("lock-status", lockStatus); } - if (lockHolder != null) { - lockMap.put("lock-holder", lockHolder); + if (lockHolders != null && !lockHolders.isEmpty()) { + if (lockHolders.size()==1) { + //for backwards compatability + lockMap.put("lock-holder", lockHolders.get(0)); + } else { + lockMap.put("lock-holder", lockHolders); + } } if (lockLease != null) { lockMap.put("lock-lease", lockLease); @@ -293,7 +305,7 @@ public class JsonResponse { public String toString() { return "JsonLockResponse [status=" + status + ", error=" + error + ", message=" + message + ", lock=" + lock + ", lockStatus=" + lockStatus + ", lockHolder=" - + lockHolder + "]"; + + lockHolders + "]"; } } diff --git a/src/main/java/org/onap/music/rest/RestMusicAdminAPI.java b/src/main/java/org/onap/music/rest/RestMusicAdminAPI.java deleted file mode 100755 index 664747f6..00000000 --- a/src/main/java/org/onap/music/rest/RestMusicAdminAPI.java +++ /dev/null @@ -1,635 +0,0 @@ -/* - * ============LICENSE_START========================================== - * org.onap.music - * =================================================================== - * Copyright (c) 2017 AT&T Intellectual Property - * =================================================================== - * Modifications Copyright (C) 2018 IBM. - * Modifications Copyright (c) 2019 Samsung - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ============LICENSE_END============================================= - * ==================================================================== - */ - -package org.onap.music.rest; - - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import javax.ws.rs.Consumes; -import javax.ws.rs.DELETE; -import javax.ws.rs.GET; -import javax.ws.rs.HeaderParam; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.ResponseBuilder; -import javax.ws.rs.core.Response.Status; - -import org.mindrot.jbcrypt.BCrypt; -import org.onap.music.authentication.CachingUtil; -import org.onap.music.authentication.MusicAAFAuthentication; -import org.onap.music.authentication.MusicAuthenticator; -import org.onap.music.datastore.MusicDataStoreHandle; -import org.onap.music.datastore.PreparedQueryObject; -import org.onap.music.datastore.jsonobjects.JsonOnboard; -import org.onap.music.datastore.jsonobjects.MusicResponse; -import org.onap.music.eelf.logging.EELFLoggerDelegate; -import org.onap.music.eelf.logging.format.AppMessages; -import org.onap.music.eelf.logging.format.ErrorSeverity; -import org.onap.music.eelf.logging.format.ErrorTypes; -import org.onap.music.exceptions.MusicServiceException; -import org.onap.music.main.MusicCore; -import org.onap.music.main.MusicUtil; -import org.onap.music.main.ResultType; -import org.onap.music.response.jsonobjects.JsonResponse; -import org.springframework.beans.factory.config.YamlProcessor.ResolutionMethod; - -import com.datastax.driver.core.DataType; -import com.datastax.driver.core.KeyspaceMetadata; -import com.datastax.driver.core.ResultSet; -import com.datastax.driver.core.Row; -import com.datastax.driver.core.TableMetadata; -import com.sun.xml.bind.v2.TODO; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; -//import java.util.Base64.Encoder; -//import java.util.Base64.Decoder; - -@Path("/v2/admin") -@Api(value = "Admin Api", hidden = true) -public class RestMusicAdminAPI { - private static EELFLoggerDelegate logger = - EELFLoggerDelegate.getLogger(RestMusicAdminAPI.class); - // Set to true in env like ONAP. Where access to creating and dropping keyspaces exist. - private static final boolean KEYSPACE_ACTIVE = false; - - private MusicAuthenticator authenticator = new MusicAAFAuthentication(); - - /* - * API to onboard an application with MUSIC. This is the mandatory first step. - * - */ - @POST - @Path("/onboardAppWithMusic") - @ApiOperation(value = "Onboard application", response = String.class) - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - public Response onboardAppWithMusic(JsonOnboard jsonObj, - @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization) throws Exception { - logger.info(EELFLoggerDelegate.errorLogger, "oboarding app"); - ResponseBuilder response = - Response.noContent().header("X-latestVersion", MusicUtil.getVersion()); - if (!authenticator.authenticateAdmin(authorization)) { - logger.error(EELFLoggerDelegate.errorLogger, "Unauthorized: Please check admin username,password and try again", AppMessages.AUTHENTICATIONERROR, ErrorSeverity.CRITICAL, - ErrorTypes.AUTHENTICATIONERROR); - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check admin username,password and try again").toMap()) - .build(); - } - - Map resultMap = new HashMap<>(); - String appName = jsonObj.getAppname(); - String userId = jsonObj.getUserId(); - String password = jsonObj.getPassword(); - String keyspace_name = jsonObj.getKeyspace(); - - if (appName == null || userId == null || password == null || keyspace_name == null) { - logger.error(EELFLoggerDelegate.errorLogger, "Unauthorized: Please check the request parameters. Some of the required values appName(ns), userId, password, isAAF are missing.", AppMessages.MISSINGINFO, - ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR); - resultMap.put("Exception", - "Unauthorized: Please check the request parameters. Some of the required values appName(ns), userId, password, isAAF are missing."); - return response.status(Status.BAD_REQUEST).entity(resultMap).build(); - } - - PreparedQueryObject pQuery = new PreparedQueryObject(); - - pQuery.appendQueryString( - "select uuid from admin.keyspace_master where application_name = ? and keyspace_name = ? allow filtering"); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), keyspace_name)); - ResultSet rs = MusicCore.get(pQuery); - if (!rs.all().isEmpty()) { - logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.INCORRECTDATA, ErrorSeverity.CRITICAL, - ErrorTypes.GENERALSERVICEERROR); - response.status(Status.BAD_REQUEST); - return response.entity(new JsonResponse(ResultType.FAILURE) - .setError("Application " + appName + " has already been onboarded. Please contact admin.").toMap()) - .build(); - } - - pQuery = new PreparedQueryObject(); - String uuid = MusicUtil.generateUUID(); - pQuery.appendQueryString( - "INSERT INTO admin.keyspace_master (uuid, keyspace_name, application_name, is_api, " - + "password, username, is_aaf) VALUES (?,?,?,?,?,?,?)"); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(),keyspace_name)); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "False")); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), BCrypt.hashpw(password, BCrypt.gensalt()))); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "true")); - - String returnStr = MusicCore.eventualPut(pQuery).toString(); - if (returnStr.contains("Failure")) { - logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); - response.status(Status.BAD_REQUEST); - return response.entity(new JsonResponse(ResultType.FAILURE).setError("Oops. Something wrong with onboarding process. " - + "Please retry later or contact admin.").toMap()).build(); - } - //CachingUtil.updateisAAFCache(appName, isAAF); - resultMap.put("Success", "Your application " + appName + " has been onboarded with MUSIC."); - resultMap.put("Generated AID", uuid); - return response.status(Status.OK).entity(resultMap).build(); - } - - - @POST - @Path("/search") - @ApiOperation(value = "Search Onboard application", response = String.class) - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - public Response getOnboardedInfoSearch(JsonOnboard jsonObj, - @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization) throws Exception { - ResponseBuilder response = Response.noContent().header("X-latestVersion", MusicUtil.getVersion()); - - if (!authenticator.authenticateAdmin(authorization)) { - logger.error(EELFLoggerDelegate.errorLogger, "Unauthorized: Please check admin username,password and try again", AppMessages.AUTHENTICATIONERROR, ErrorSeverity.CRITICAL, - ErrorTypes.AUTHENTICATIONERROR); - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check admin username,password and try again").toMap()) - .build(); - } - - Map resultMap = new HashMap<>(); - String appName = jsonObj.getAppname(); - String uuid = jsonObj.getAid(); - String isAAF = jsonObj.getIsAAF(); - if (appName == null && uuid == null && isAAF == null) { - logger.error(EELFLoggerDelegate.errorLogger, "Unauthorized: Please check the request parameters. Enter atleast one of the following parameters: appName(ns), aid, isAAF.", AppMessages.MISSINGINFO, - ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR); - resultMap.put("Exception", - "Unauthorized: Please check the request parameters. Enter atleast one of the following parameters: appName(ns), aid, isAAF."); - return response.status(Status.BAD_REQUEST).entity(resultMap).build(); - } - - PreparedQueryObject pQuery = new PreparedQueryObject(); - String cql = "select uuid, keyspace_name from admin.keyspace_master where "; - if (appName != null) - cql = cql + "application_name = ? AND "; - if (uuid != null) - cql = cql + "uuid = ? AND "; - if (isAAF != null) - cql = cql + "is_aaf = ?"; - - if (cql.endsWith("AND ")) - cql = cql.trim().substring(0, cql.length() - 4); - logger.info("Query in callback is: " + cql); - cql = cql + " allow filtering"; - pQuery.appendQueryString(cql); - if (appName != null) - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); - if (uuid != null) - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); - if (isAAF != null) - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), - Boolean.parseBoolean(isAAF))); - ResultSet rs = MusicCore.get(pQuery); - Iterator it = rs.iterator(); - while (it.hasNext()) { - Row row = it.next(); - resultMap.put(row.getUUID("uuid").toString(), row.getString("keyspace_name")); - } - if (resultMap.isEmpty()) { - if (uuid != null) { - logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); - response.status(Status.BAD_REQUEST); - return response.entity(new JsonResponse(ResultType.FAILURE).setError("Please make sure Aid is correct and application is onboarded.").toMap()).build(); - - } else { - logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); - response.status(Status.BAD_REQUEST); - return response.entity(new JsonResponse(ResultType.FAILURE).setError("Application is not onboarded. Please make sure all the information is correct.").toMap()).build(); - } - } - return response.status(Status.OK).entity(resultMap).build(); - } - - - @DELETE - @Path("/onboardAppWithMusic") - @ApiOperation(value = "Delete Onboard application", response = String.class) - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - public Response deleteOnboardApp(JsonOnboard jsonObj, - @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization) throws Exception { - ResponseBuilder response = Response.noContent().header("X-latestVersion", MusicUtil.getVersion()); - - if (!authenticator.authenticateAdmin(authorization)) { - logger.error(EELFLoggerDelegate.errorLogger, "Unauthorized: Please check admin username,password and try again", AppMessages.AUTHENTICATIONERROR, ErrorSeverity.CRITICAL, - ErrorTypes.AUTHENTICATIONERROR); - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check admin username,password and try again").toMap()) - .build(); - } - - Map resultMap = new HashMap<>(); - String appName = jsonObj.getAppname(); - String aid = jsonObj.getAid(); - PreparedQueryObject pQuery = new PreparedQueryObject(); - String consistency = MusicUtil.EVENTUAL; - if (appName == null && aid == null) { - logger.error(EELFLoggerDelegate.errorLogger, - "Please make sure either appName(ns) or Aid is present", AppMessages.MISSINGINFO, - ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); - resultMap.put("Exception", "Please make sure either appName(ns) or Aid is present"); - return response.status(Status.BAD_REQUEST).entity(resultMap).build(); - } - if (aid != null) { - if (MusicUtil.isKeyspaceActive()) { - pQuery.appendQueryString( - "SELECT keyspace_name FROM admin.keyspace_master WHERE uuid = ?"); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), - UUID.fromString(aid))); - Row row = MusicCore.get(pQuery).one(); - if (row != null) { - String ks = row.getString("keyspace_name"); - if (!ks.equals(MusicUtil.DEFAULTKEYSPACENAME)) { - PreparedQueryObject queryObject = new PreparedQueryObject(); - queryObject.appendQueryString("DROP KEYSPACE IF EXISTS " + ks + ";"); - MusicCore.nonKeyRelatedPut(queryObject, consistency); - } - } - } - pQuery = new PreparedQueryObject(); - pQuery.appendQueryString("delete from admin.keyspace_master where uuid = ? IF EXISTS"); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), - UUID.fromString(aid))); - ResultType result = MusicCore.nonKeyRelatedPut(pQuery, consistency); - if (result == ResultType.SUCCESS) { - resultMap.put("Success", "Your application has been deleted successfully"); - } else { - resultMap.put("Exception", - "Oops. Something went wrong. Please make sure Aid is correct or Application is onboarded"); - logger.error(EELFLoggerDelegate.errorLogger, - "Oops. Something went wrong. Please make sure Aid is correct or Application is onboarded", - AppMessages.INCORRECTDATA, - ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); - return response.status(Status.BAD_REQUEST).entity(resultMap).build(); - - } - return response.status(Status.OK).entity(resultMap).build(); - } - - pQuery.appendQueryString( - "select uuid from admin.keyspace_master where application_name = ? allow filtering"); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); - ResultSet rs = MusicCore.get(pQuery); - List rows = rs.all(); - String uuid = null; - if (rows.isEmpty()) { - resultMap.put("Exception", - "Application not found. Please make sure Application exists."); - logger.error(EELFLoggerDelegate.errorLogger, "Application not found. Please make sure Application exists.", AppMessages.INCORRECTDATA, - ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); - return response.status(Status.BAD_REQUEST).entity(resultMap).build(); - } else if (rows.size() == 1) { - uuid = rows.get(0).getUUID("uuid").toString(); - pQuery = new PreparedQueryObject(); - pQuery.appendQueryString( - "SELECT keyspace_name FROM admin.keyspace_master WHERE uuid = ?"); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), - UUID.fromString(uuid))); - Row row = MusicCore.get(pQuery).one(); - String ks = row.getString("keyspace_name"); - if (!ks.equals(MusicUtil.DEFAULTKEYSPACENAME)) { - PreparedQueryObject queryObject = new PreparedQueryObject(); - queryObject.appendQueryString("DROP KEYSPACE " + ks + ";"); - MusicCore.nonKeyRelatedPut(queryObject, consistency); - } - - pQuery = new PreparedQueryObject(); - pQuery.appendQueryString("delete from admin.keyspace_master where uuid = ?"); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), - UUID.fromString(uuid))); - MusicCore.eventualPut(pQuery); - resultMap.put("Success", "Your application " + appName + " has been deleted."); - return response.status(Status.OK).entity(resultMap).build(); - } else { - resultMap.put("Failure", - "More than one Aid exists for this application, so please provide Aid."); - logger.error(EELFLoggerDelegate.errorLogger, "More than one Aid exists for this application, so please provide Aid.", AppMessages.MULTIPLERECORDS, - ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); - return response.status(Status.BAD_REQUEST).entity(resultMap).build(); - } - } - - - @PUT - @Path("/onboardAppWithMusic") - @ApiOperation(value = "Update Onboard application", response = String.class) - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - public Response updateOnboardApp(JsonOnboard jsonObj, - @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization) throws Exception { - ResponseBuilder response = Response.noContent().header("X-latestVersion", MusicUtil.getVersion()); - if (!authenticator.authenticateAdmin(authorization)) { - logger.error(EELFLoggerDelegate.errorLogger, "Unauthorized: Please check admin username,password and try again", AppMessages.AUTHENTICATIONERROR, ErrorSeverity.CRITICAL, - ErrorTypes.AUTHENTICATIONERROR); - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check admin username,password and try again").toMap()) - .build(); - } - - Map resultMap = new HashMap<>(); - String aid = jsonObj.getAid(); - String appName = jsonObj.getAppname(); - String userId = jsonObj.getUserId(); - String cassandraKeyspace=jsonObj.getKeyspace(); - String consistency = "eventual"; - PreparedQueryObject pQuery; - - if (aid == null) { - resultMap.put("Exception", "Please make sure Aid is present"); - logger.error(EELFLoggerDelegate.errorLogger, "Please make sure Aid is present", AppMessages.MISSINGDATA, - ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); - return response.status(Status.BAD_REQUEST).entity(resultMap).build(); - } - - if (appName == null || userId == null || cassandraKeyspace == null) { - resultMap.put("Exception", - "No parameters found to update. Please update atleast one parameter."); - logger.error(EELFLoggerDelegate.errorLogger, "No parameters found to update. Please update atleast one parameter.", AppMessages.MISSINGDATA, - ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); - return response.status(Status.BAD_REQUEST).entity(resultMap).build(); - } - - if (appName != null) { - pQuery = new PreparedQueryObject(); - pQuery.appendQueryString( - "select uuid from admin.keyspace_master where application_name = ? allow filtering"); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); - ResultSet rs = MusicCore.get(pQuery); - if (rs.all().isEmpty()) { - resultMap.put("Exception", "Application " + appName - + " not found. Please contact admin."); - logger.error(EELFLoggerDelegate.errorLogger, "Application " + appName+"not found. Please contact admin.", AppMessages.ALREADYEXIST, - ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); - return response.status(Status.BAD_REQUEST).entity(resultMap).build(); - } - } - - pQuery = new PreparedQueryObject(); - StringBuilder preCql = new StringBuilder("UPDATE admin.keyspace_master SET "); - if (appName != null) - preCql.append(" application_name = ?,"); - if (userId != null) - preCql.append(" username = ?,"); - if (cassandraKeyspace != null) - preCql.append(" keyspace_name = ?,"); - preCql.deleteCharAt(preCql.length() - 1); - preCql.append(" WHERE uuid = ? IF EXISTS"); - pQuery.appendQueryString(preCql.toString()); - if (appName != null) - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); - if (userId != null) - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); - if (cassandraKeyspace != null) - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), cassandraKeyspace)); - - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), UUID.fromString(aid))); - ResultType result = MusicCore.nonKeyRelatedPut(pQuery, consistency); - - if (result == ResultType.SUCCESS) { - resultMap.put("Success", "Your application has been updated successfully"); - } else { - resultMap.put("Exception", - "Oops. Something went wrong. Please make sure Aid is correct and application is onboarded"); - logger.error(EELFLoggerDelegate.errorLogger, "Oops. Something went wrong. Please make sure Aid is correct and application is onboarded", AppMessages.INCORRECTDATA, - ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); - return response.status(Status.BAD_REQUEST).entity(resultMap).build(); - } - - return response.status(Status.OK).entity(resultMap).build(); - } - - - - //Dashboard related calls - //TODO Make return object Response. - - @GET - @Path("/getall") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public MusicResponse getall(@ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization) throws MusicServiceException{ - MusicResponse response = new MusicResponse(); - if (!authenticator.authenticateAdmin(authorization)) { - logger.info(EELFLoggerDelegate.errorLogger, "Unauthorized: Please check admin username,password and try again", AppMessages.AUTHENTICATIONERROR, ErrorSeverity.CRITICAL, - ErrorTypes.AUTHENTICATIONERROR); - response.setResposne("fail", "Auth failed for admin"); - return response; - } - - PreparedQueryObject queryObject = new PreparedQueryObject(); - queryObject.appendQueryString("SELECT * FROM " + "admin" + "." + "keyspace_master" + ";"); - try { - ResultSet results = MusicCore.get(queryObject); - for(Row row : results) { - Application app = new Application(); - app.setApplication_name(row.getString("application_name")); - app.setIs_aaf(row.getBool("is_aaf")); - app.setIs_api(row.getBool("is_api")); - app.setUsername(row.getString("username")); - app.setKeyspace_name(row.getString("keyspace_name")); - app.setUuid(row.getUUID("uuid").toString()); - response.addAppToList(app); - } - }catch(Exception ex) { - response.setResposne("fail", ex.getMessage()); - } - return response; - - } - - - @DELETE - @Path("/delete") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public MusicResponse delete(@ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "uuid", required = true) @HeaderParam("uuid") String uuid) throws Exception { - MusicResponse response = new MusicResponse(); - if (!authenticator.authenticateAdmin(authorization)) { - logger.info(EELFLoggerDelegate.errorLogger, "Unauthorized: Please check admin username,password and try again", AppMessages.AUTHENTICATIONERROR, ErrorSeverity.CRITICAL, - ErrorTypes.AUTHENTICATIONERROR); - response.setResposne("fail", "Auth failed for admin"); - return response; - } - PreparedQueryObject queryObject = new PreparedQueryObject(); - queryObject.appendQueryString("delete from admin.keyspace_master where uuid=?"); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(),uuid)); - ResultType result; - try { - result = MusicCore.nonKeyRelatedPut(queryObject, "eventual"); - response.setResposne("success", "Application deleted successfully. Please contact ops team to delete keyspace"); - }catch(Exception ex) { - logger.error(EELFLoggerDelegate.errorLogger, ex); - response.setResposne("fail", ex.getMessage()); - return response; - } - return response; - } - - @POST - @Path("/onboard") - @ApiOperation(value = "Onboard application", response = String.class) - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - public MusicResponse onboard(JsonOnboard jsonObj, - @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization) throws Exception { - logger.info(EELFLoggerDelegate.errorLogger, "oboarding app"); - MusicResponse response = new MusicResponse(); - if (!authenticator.authenticateAdmin(authorization)) { - logger.info(EELFLoggerDelegate.errorLogger, "Unauthorized: Please check admin username,password and try again", AppMessages.AUTHENTICATIONERROR, ErrorSeverity.CRITICAL, - ErrorTypes.AUTHENTICATIONERROR); - response.setResposne("fail", "auth error"); - } - PreparedQueryObject pQurey = new PreparedQueryObject(); - pQurey.appendQueryString("Describe keyspace + ?"); - pQurey.addValue(MusicUtil.convertToActualDataType(DataType.text(),jsonObj.getKeyspace())); - KeyspaceMetadata keyspaceInfo = null; - //authenticator.checkOnbaordUserAccess(jsonObj.getUserId(), jsonObj.getAppname()); - try { - keyspaceInfo = MusicDataStoreHandle.returnkeyspaceMetadata(jsonObj.getKeyspace()); - }catch (Exception e) { - logger.info(EELFLoggerDelegate.applicationLogger,"Application onbaord failed for "+ jsonObj.getKeyspace()); - - } - if(keyspaceInfo == null) { - logger.info(EELFLoggerDelegate.applicationLogger,"Keyspace does not exist, contact music support to create a keyspace and onbaord again"); - response.setResposne("fail", "Keyspace does not exist, contact music support to create a keyspace and onboard again"); - return response; - } - Response result = null; - try { - result = onboardAppWithMusic(jsonObj, authorization); - if(result.getStatus()!= 200) { - response.setResposne("fail", result.getEntity().toString()); - }else { - response.setResposne("success", "Onboard Success"); - } - }catch(Exception ex) { - response.setResposne("fail", ex.getMessage()); - return response; - - } - return response; - } - - @POST - @Path("/disable") - @ApiOperation(value = "Onboard application", response = String.class) - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - public MusicResponse disableApplicationAccess(@ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - @ApiParam(value = "uuid", required = true) @HeaderParam("uuid") String uuid) throws Exception { - logger.info(EELFLoggerDelegate.errorLogger, "oboarding app"); - MusicResponse response = new MusicResponse(); - if (!authenticator.authenticateAdmin(authorization)) { - logger.info(EELFLoggerDelegate.errorLogger, "Unauthorized: Please check admin username,password and try again", AppMessages.AUTHENTICATIONERROR, ErrorSeverity.CRITICAL, - ErrorTypes.AUTHENTICATIONERROR); - response.setResposne("fail", "Authorization failed for music admin"); - } - PreparedQueryObject queryObject = new PreparedQueryObject(); - queryObject.appendQueryString("SELECT * from admin.keyspace_master where uuid = ?"); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); - Row row = MusicDataStoreHandle.getDSHandle().executeGet(queryObject, "eventual").one(); - boolean toggleAccess = row.getBool("is_api"); - queryObject = null; - queryObject = new PreparedQueryObject(); - queryObject.appendQueryString("UPDATE admin.keyspace_master SET is_api = ? WHERE uuid = ?"); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), !toggleAccess)); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); - try { - MusicDataStoreHandle.getDSHandle().executePut(queryObject, "eventual"); - response.setResposne("success","Access toggle success"); - }catch(Exception ex) { - response.setResposne("fail", ex.getMessage()); - } - - return response; - } - - @POST - @Path("/editApplication") - @ApiOperation(value = "Onboard application", response = String.class) - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - public MusicResponse editApplication(JsonOnboard jsonObj, - @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization) throws Exception { - logger.info(EELFLoggerDelegate.errorLogger, "oboarding app"); - MusicResponse response = new MusicResponse(); - if (!authenticator.authenticateAdmin(authorization)) { - logger.info(EELFLoggerDelegate.errorLogger, "Unauthorized: Please check admin username,password and try again", AppMessages.AUTHENTICATIONERROR, ErrorSeverity.CRITICAL, - ErrorTypes.AUTHENTICATIONERROR); - response.setResposne("fail", "auth error"); - } - KeyspaceMetadata keyspaceInfo = null; - try { - keyspaceInfo = MusicDataStoreHandle.returnkeyspaceMetadata(jsonObj.getKeyspace()); - }catch (Exception e) { - logger.info(EELFLoggerDelegate.applicationLogger,"Application Update failed for "+ jsonObj.getKeyspace()); - - } - if(keyspaceInfo == null) { - logger.info(EELFLoggerDelegate.applicationLogger,"Keyspace does not exist, contact music support to create a keyspace and onbaord again"); - response.setResposne("fail", "Keyspace does not exist, contact music support to create a keyspace and update again"); - return response; - } - - try { - Response res = updateOnboardApp(jsonObj, authorization); - if(res.getStatus() != 200) { - response.setResposne("fail", res.getEntity().toString()); - }else - response.setResposne("success", "Update success"); - }catch(Exception ex){ - logger.info(EELFLoggerDelegate.errorLogger,"Exception while updating application"); - logger.info(EELFLoggerDelegate.errorLogger,ex.getMessage()); - response.setResposne("fail", ex.getMessage()); - - } - return response; - } - - -} diff --git a/src/main/java/org/onap/music/rest/RestMusicDataAPI.java b/src/main/java/org/onap/music/rest/RestMusicDataAPI.java index 5fa955e1..09898c79 100755 --- a/src/main/java/org/onap/music/rest/RestMusicDataAPI.java +++ b/src/main/java/org/onap/music/rest/RestMusicDataAPI.java @@ -47,11 +47,6 @@ import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.UriInfo; import org.apache.commons.lang3.StringUtils; -import org.mindrot.jbcrypt.BCrypt; -import org.onap.music.authentication.CachingUtil; -import org.onap.music.authentication.MusicAAFAuthentication; -import org.onap.music.authentication.MusicAuthenticator; -import org.onap.music.authentication.MusicAuthenticator.Operation; import org.onap.music.datastore.PreparedQueryObject; import org.onap.music.datastore.jsonobjects.JsonDelete; import org.onap.music.datastore.jsonobjects.JsonInsert; @@ -75,7 +70,6 @@ import org.onap.music.response.jsonobjects.JsonResponse; import com.datastax.driver.core.DataType; import com.datastax.driver.core.ResultSet; -import com.datastax.driver.core.Row; import com.datastax.driver.core.TableMetadata; import io.swagger.annotations.Api; @@ -117,9 +111,6 @@ public class RestMusicDataAPI { private static final String XPATCHVERSION = "X-patchVersion"; private static final String NS = "ns"; private static final String VERSION = "v2"; - private MusicAuthenticator authenticator = new MusicAAFAuthentication(); - // Set to true in env like ONAP. Where access to creating and dropping keyspaces exist. - private static final boolean KEYSPACE_ACTIVE = false; private class RowIdentifier { public String primarKeyValue; @@ -163,40 +154,22 @@ public class RestMusicDataAPI { ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) "); logger.info(EELFLoggerDelegate.applicationLogger,"In Create Keyspace " + keyspaceName); - if ( MusicUtil.isKeyspaceActive() ) { + if (MusicUtil.isKeyspaceActive() ) { logger.info(EELFLoggerDelegate.applicationLogger,"Creating Keyspace " + keyspaceName); - Map userCredentials = MusicUtil.extractBasicAuthentication(authorization); - String userId = userCredentials.get(MusicUtil.USERID); - String password = userCredentials.get(MusicUtil.PASSWORD); - Map authMap = CachingUtil.verifyOnboarding(ns, userId, password); - if (!authMap.isEmpty()) { - logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR); - response.status(Status.UNAUTHORIZED); - return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build(); - } - - if (!authenticator.authenticateUser(ns, authorization, keyspaceName, aid, Operation.CREATE_KEYSPACE)) { - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check username, password and make sure your app is onboarded") - .toMap()).build(); - } - - String consistency = MusicUtil.EVENTUAL;// for now this needs only - // eventual consistency - + if(kspObject == null || kspObject.getReplicationInfo() == null) { response.status(Status.BAD_REQUEST); return response.entity(new JsonResponse(ResultType.FAILURE).setError(ResultType.BODYMISSING.getResult()).toMap()).build(); } + + String consistency = MusicUtil.EVENTUAL;// for now this needs only eventual consistency + PreparedQueryObject queryObject = new PreparedQueryObject(); if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && kspObject.getConsistencyInfo().get("consistency") != null) { - if (MusicUtil.isValidConsistency(kspObject.getConsistencyInfo().get("consistency"))) { - queryObject.setConsistency(kspObject.getConsistencyInfo().get("consistency")); - } else { - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR) - .setError("Invalid Consistency type").toMap()).build(); - } + if(MusicUtil.isValidConsistency(kspObject.getConsistencyInfo().get("consistency"))) + queryObject.setConsistency(kspObject.getConsistencyInfo().get("consistency")); + else + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build(); } long start = System.currentTimeMillis(); Map replicationInfo = kspObject.getReplicationInfo(); @@ -230,44 +203,6 @@ public class RestMusicDataAPI { return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("err:" + ex.getMessage()).toMap()).build(); } - try { - queryObject = new PreparedQueryObject(); - queryObject.appendQueryString("CREATE ROLE IF NOT EXISTS '" + userId - + "' WITH PASSWORD = '" + password + "' AND LOGIN = true;"); - MusicCore.nonKeyRelatedPut(queryObject, consistency); - queryObject = new PreparedQueryObject(); - queryObject.appendQueryString("GRANT ALL PERMISSIONS on KEYSPACE " + keyspaceName - + " to '" + userId + "'"); - queryObject.appendQueryString(";"); - MusicCore.nonKeyRelatedPut(queryObject, consistency); - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR,ErrorSeverity - .WARN, ErrorTypes.MUSICSERVICEERROR, e); - } - - try { - boolean isAAF = Boolean.valueOf(CachingUtil.isAAFApplication(ns)); - String hashedpwd = BCrypt.hashpw(password, BCrypt.gensalt()); - queryObject = new PreparedQueryObject(); - queryObject.appendQueryString( - "INSERT into admin.keyspace_master (uuid, keyspace_name, application_name, is_api, " - + "password, username, is_aaf) values (?,?,?,?,?,?,?)"); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), aid)); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), keyspaceName)); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), ns)); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "True")); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), hashedpwd)); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF)); - CachingUtil.updateMusicCache(keyspaceName, ns); - CachingUtil.updateMusicValidateCache(ns, userId, hashedpwd); - MusicCore.eventualPut(queryObject); - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR,ErrorSeverity - .WARN, ErrorTypes.MUSICSERVICEERROR, e); - return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); - } - return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Created").toMap()).build(); } else { String vError = "Keyspace Creation has been turned off. Contact DBA to create the keyspace or set keyspace.active to true."; @@ -305,43 +240,7 @@ public class RestMusicDataAPI { EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspaceName + " ) "); logger.info(EELFLoggerDelegate.applicationLogger,"In Drop Keyspace " + keyspaceName); if (MusicUtil.isKeyspaceActive()) { - if (!authenticator.authenticateUser(ns, authorization, keyspaceName, aid, Operation.DROP_KEYSPACE)) { - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check username, password and make sure your app is onboarded") - .toMap()).build(); - } String consistency = MusicUtil.EVENTUAL;// for now this needs only - // eventual - // consistency - String appName = CachingUtil.getAppName(keyspaceName); - String uuid = CachingUtil.getUuidFromMusicCache(keyspaceName); - PreparedQueryObject pQuery = new PreparedQueryObject(); - pQuery.appendQueryString( - "select count(*) as count from admin.keyspace_master where application_name=? allow filtering;"); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); - Row row = MusicCore.get(pQuery).one(); - long count = row.getLong(0); - - if (count == 0) { - logger.error(EELFLoggerDelegate.errorLogger,"Keyspace not found. Please make sure keyspace exists.", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Keyspace not found. Please make sure keyspace exists.").toMap()).build(); - // Admin Functions: - } else if (count == 1) { - pQuery = new PreparedQueryObject(); - pQuery.appendQueryString( - "UPDATE admin.keyspace_master SET keyspace_name=? where uuid = ?;"); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), - MusicUtil.DEFAULTKEYSPACENAME)); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); - MusicCore.nonKeyRelatedPut(pQuery, consistency); - } else { - pQuery = new PreparedQueryObject(); - pQuery.appendQueryString("delete from admin.keyspace_master where uuid = ?"); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); - MusicCore.nonKeyRelatedPut(pQuery, consistency); - } - PreparedQueryObject queryObject = new PreparedQueryObject(); queryObject.appendQueryString("DROP KEYSPACE " + keyspaceName + ";"); ResultType result = MusicCore.nonKeyRelatedPut(queryObject, consistency); @@ -398,12 +297,6 @@ public class RestMusicDataAPI { .toMap()).build(); } EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) "); - if (!authenticator.authenticateUser(ns, authorization, keyspace, aid, Operation.CREATE_TABLE)) { - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check username, password and make sure your app is onboarded") - .toMap()).build(); - } String consistency = MusicUtil.EVENTUAL; // for now this needs only eventual consistency String primaryKey = null; @@ -420,7 +313,7 @@ public class RestMusicDataAPI { Map fields = tableObj.getFields(); if (fields == null) { return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) - .setError("Create Table Error: No fields in request").toMap()).build(); + .setError("Create Table Error: No fields in request").toMap()).build(); } StringBuilder fieldsString = new StringBuilder("(vector_ts text,"); @@ -607,53 +500,46 @@ public class RestMusicDataAPI { @ApiOperation(value = "Create Index", response = String.class) @Produces(MediaType.APPLICATION_JSON) public Response createIndex( - @ApiParam(value = "Major Version",required = true) @PathParam("version") String version, - @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, - @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid, - @ApiParam(value = "Application namespace",required = 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, - @ApiParam(value = "Field Name",required = true) @PathParam("field") String fieldName, - @Context UriInfo info) throws Exception { + @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 = "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, + @ApiParam(value = "Field Name",required = true) @PathParam("field") String fieldName, + @Context UriInfo info) throws Exception { try { - ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); - if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty()) || (fieldName == null || fieldName.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(); - } - EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) "); - if (!authenticator.authenticateUser(ns, authorization, keyspace, aid, Operation.CREATE_INDEX)) { - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check username, password and make sure your app is onboarded") - .toMap()).build(); - } - - MultivaluedMap rowParams = info.getQueryParameters(); - String indexName = ""; - if (rowParams.getFirst("index_name") != null) - indexName = rowParams.getFirst("index_name"); - PreparedQueryObject query = new PreparedQueryObject(); - query.appendQueryString("Create index if not exists " + indexName + " on " + keyspace + "." - + tablename + " (" + fieldName + ");"); + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + if ((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty()) || (fieldName == null || fieldName.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(); + } + EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) "); + MultivaluedMap rowParams = info.getQueryParameters(); + String indexName = ""; + if (rowParams.getFirst("index_name") != null) + indexName = rowParams.getFirst("index_name"); + PreparedQueryObject query = new PreparedQueryObject(); + query.appendQueryString("Create index if not exists " + indexName + " on " + keyspace + "." + + tablename + " (" + fieldName + ");"); - ResultType result = ResultType.FAILURE; - try { - result = MusicCore.nonKeyRelatedPut(query, "eventual"); - } catch (MusicServiceException ex) { - logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity + ResultType result = ResultType.FAILURE; + try { + result = MusicCore.nonKeyRelatedPut(query, "eventual"); + } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity .CRITICAL, ErrorTypes.GENERALSERVICEERROR, ex); - response.status(Status.BAD_REQUEST); - return response.entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); - } - if ( result.equals(ResultType.SUCCESS) ) { - return response.status(Status.OK).entity(new JsonResponse(result).setMessage("Index Created on " + keyspace+"."+tablename+"."+fieldName).toMap()).build(); - } else { - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Unknown Error in create index.").toMap()).build(); - } + response.status(Status.BAD_REQUEST); + return response.entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); + } + if ( result.equals(ResultType.SUCCESS) ) { + return response.status(Status.OK).entity(new JsonResponse(result).setMessage("Index Created on " + keyspace+"."+tablename+"."+fieldName).toMap()).build(); + } else { + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Unknown Error in create index.").toMap()).build(); + } } finally { EELFLoggerDelegate.mdcRemove("keyspace"); } @@ -673,198 +559,185 @@ public class RestMusicDataAPI { @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response insertIntoTable( - @ApiParam(value = "Major Version",required = true) @PathParam("version") String version, - @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, - @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid, - @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns, - @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - JsonInsert insObj, - @ApiParam(value = "Keyspace Name", - required = true) @PathParam("keyspace") String keyspace, - @ApiParam(value = "Table Name", - required = true) @PathParam("tablename") String tablename) { - try { - ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); - 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(); - } - EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) "); - if (!authenticator.authenticateUser(ns, authorization, keyspace, aid, Operation.INSERT_INTO_TABLE)) { - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check username, password and make sure your app is onboarded") - .toMap()).build(); - } - - PreparedQueryObject queryObject = new PreparedQueryObject(); - TableMetadata tableInfo = null; + @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 = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, + JsonInsert insObj, + @ApiParam(value = "Keyspace Name", + required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Table Name", + required = true) @PathParam("tablename") String tablename) { try { - tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename); - if(tableInfo == null) { - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Table name doesn't exists. Please check the table name.").toMap()).build(); - } - } catch (MusicServiceException e) { - logger.error(EELFLoggerDelegate.errorLogger, e, AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); - } - String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName(); - StringBuilder fieldsString = new StringBuilder("(vector_ts,"); - String vectorTs = - String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis()); - StringBuilder valueString = new StringBuilder("(" + "?" + ","); - queryObject.addValue(vectorTs); - - Map valuesMap = insObj.getValues(); - if (valuesMap==null) { - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) - .setError("Nothing to insert. No values provided in request.").toMap()).build(); - } - int counter = 0; - String primaryKey = ""; - for (Map.Entry entry : valuesMap.entrySet()) { - fieldsString.append("" + entry.getKey()); - Object valueObj = entry.getValue(); - if (primaryKeyName.equals(entry.getKey())) { - primaryKey = entry.getValue() + ""; - primaryKey = primaryKey.replace("'", "''"); + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + 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(); } - DataType colType = null; + EELFLoggerDelegate.mdcPut("keyspace","(" + keyspace + ")"); + PreparedQueryObject queryObject = new PreparedQueryObject(); + TableMetadata tableInfo = null; try { - colType = tableInfo.getColumn(entry.getKey()).getType(); - } catch(NullPointerException ex) { - logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() +" Invalid column name : "+entry.getKey - (), AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR, ex); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap()).build(); + tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename); + if(tableInfo == null) { + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Table name doesn't exists. Please check the table name.").toMap()).build(); + } + } catch (MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger, e, AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); } - - Object formattedValue = null; - try { - formattedValue = MusicUtil.convertToActualDataType(colType, valueObj); - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger,e); - } - valueString.append("?"); - - queryObject.addValue(formattedValue); - - if (counter == valuesMap.size() - 1) { - fieldsString.append(")"); - valueString.append(")"); - } else { - fieldsString.append(","); - valueString.append(","); + String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName(); + StringBuilder fieldsString = new StringBuilder("(vector_ts,"); + String vectorTs = + String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis()); + StringBuilder valueString = new StringBuilder("(" + "?" + ","); + queryObject.addValue(vectorTs); + + Map valuesMap = insObj.getValues(); + if (valuesMap==null) { + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + .setError("Nothing to insert. No values provided in request.").toMap()).build(); } - counter = counter + 1; - } - - //blobs.. - Map objectMap = insObj.getObjectMap(); - if(objectMap != null) { - for (Map.Entry entry : objectMap.entrySet()) { - if(counter > 0) { - fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ","); - valueString.replace(valueString.length()-1, valueString.length(), ","); - } + int counter = 0; + String primaryKey = ""; + for (Map.Entry entry : valuesMap.entrySet()) { fieldsString.append("" + entry.getKey()); - byte[] valueObj = entry.getValue(); + Object valueObj = entry.getValue(); if (primaryKeyName.equals(entry.getKey())) { primaryKey = entry.getValue() + ""; primaryKey = primaryKey.replace("'", "''"); } + DataType colType = null; + try { + colType = tableInfo.getColumn(entry.getKey()).getType(); + } catch(NullPointerException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() +" Invalid column name : "+entry.getKey + (), AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR, ex); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap()).build(); + } - DataType colType = tableInfo.getColumn(entry.getKey()).getType(); - - ByteBuffer formattedValue = null; - - if(colType.toString().toLowerCase().contains("blob")) + Object formattedValue = null; + try { formattedValue = MusicUtil.convertToActualDataType(colType, valueObj); - + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e); + } valueString.append("?"); queryObject.addValue(formattedValue); - counter = counter + 1; - fieldsString.append(","); - valueString.append(","); - } - } - if(primaryKey == null || primaryKey.length() <= 0) { - logger.error(EELFLoggerDelegate.errorLogger, "Some required partition key parts are missing: "+primaryKeyName ); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Some required partition key parts are missing: "+primaryKeyName).toMap()).build(); - } + if (counter == valuesMap.size() - 1) { + fieldsString.append(")"); + valueString.append(")"); + } else { + fieldsString.append(","); + valueString.append(","); + } + counter = counter + 1; + } - fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ")"); - valueString.replace(valueString.length()-1, valueString.length(), ")"); + //blobs.. + Map objectMap = insObj.getObjectMap(); + if(objectMap != null) { + for (Map.Entry entry : objectMap.entrySet()) { + if(counter > 0) { + fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ","); + valueString.replace(valueString.length()-1, valueString.length(), ","); + } + fieldsString.append("" + entry.getKey()); + byte[] valueObj = entry.getValue(); + if (primaryKeyName.equals(entry.getKey())) { + primaryKey = entry.getValue() + ""; + primaryKey = primaryKey.replace("'", "''"); + } + DataType colType = tableInfo.getColumn(entry.getKey()).getType(); + ByteBuffer formattedValue = null; + if(colType.toString().toLowerCase().contains("blob")) { + formattedValue = MusicUtil.convertToActualDataType(colType, valueObj); + } + valueString.append("?"); + queryObject.addValue(formattedValue); + counter = counter + 1; + fieldsString.append(","); + valueString.append(","); + } + } - queryObject.appendQueryString("INSERT INTO " + keyspace + "." + tablename + " " - + fieldsString + " VALUES " + valueString); + if(primaryKey == null || primaryKey.length() <= 0) { + logger.error(EELFLoggerDelegate.errorLogger, "Some required partition key parts are missing: "+primaryKeyName ); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Some required partition key parts are missing: "+primaryKeyName).toMap()).build(); + } - String ttl = insObj.getTtl(); - String timestamp = insObj.getTimestamp(); + fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ")"); + valueString.replace(valueString.length()-1, valueString.length(), ")"); - if ((ttl != null) && (timestamp != null)) { - logger.info(EELFLoggerDelegate.applicationLogger, "both there"); - queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?"); - queryObject.addValue(Integer.parseInt(ttl)); - queryObject.addValue(Long.parseLong(timestamp)); - } + queryObject.appendQueryString("INSERT INTO " + keyspace + "." + tablename + " " + + fieldsString + " VALUES " + valueString); - if ((ttl != null) && (timestamp == null)) { - logger.info(EELFLoggerDelegate.applicationLogger, "ONLY TTL there"); - queryObject.appendQueryString(" USING TTL ?"); - queryObject.addValue(Integer.parseInt(ttl)); - } + String ttl = insObj.getTtl(); + String timestamp = insObj.getTimestamp(); - if ((ttl == null) && (timestamp != null)) { - logger.info(EELFLoggerDelegate.applicationLogger, "ONLY timestamp there"); - queryObject.appendQueryString(" USING TIMESTAMP ?"); - queryObject.addValue(Long.parseLong(timestamp)); - } + if ((ttl != null) && (timestamp != null)) { + logger.info(EELFLoggerDelegate.applicationLogger, "both there"); + queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?"); + queryObject.addValue(Integer.parseInt(ttl)); + queryObject.addValue(Long.parseLong(timestamp)); + } - queryObject.appendQueryString(";"); + if ((ttl != null) && (timestamp == null)) { + logger.info(EELFLoggerDelegate.applicationLogger, "ONLY TTL there"); + queryObject.appendQueryString(" USING TTL ?"); + queryObject.addValue(Integer.parseInt(ttl)); + } - ReturnType result = null; - String consistency = insObj.getConsistencyInfo().get("type"); - if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && insObj.getConsistencyInfo().get("consistency") != null) { - if(MusicUtil.isValidConsistency(insObj.getConsistencyInfo().get("consistency"))) - queryObject.setConsistency(insObj.getConsistencyInfo().get("consistency")); - else - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build(); - } - queryObject.setOperation("insert"); - try { - if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) { - result = MusicCore.eventualPut(queryObject); - } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { - String lockId = insObj.getConsistencyInfo().get("lockId"); - if(lockId == null) { - logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" - + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock " - + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build(); - } - result = MusicCore.criticalPut(keyspace, tablename, primaryKey, queryObject, lockId,null); - } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + if ((ttl == null) && (timestamp != null)) { + logger.info(EELFLoggerDelegate.applicationLogger, "ONLY timestamp there"); + queryObject.appendQueryString(" USING TIMESTAMP ?"); + queryObject.addValue(Long.parseLong(timestamp)); + } - result = MusicCore.atomicPut(keyspace, tablename, primaryKey, queryObject, null); + queryObject.appendQueryString(";"); + ReturnType result = null; + String consistency = insObj.getConsistencyInfo().get("type"); + if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && insObj.getConsistencyInfo().get("consistency") != null) { + if(MusicUtil.isValidConsistency(insObj.getConsistencyInfo().get("consistency"))) { + queryObject.setConsistency(insObj.getConsistencyInfo().get("consistency")); + } else { + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build(); + } } - } catch (Exception ex) { - logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity - .WARN, ErrorTypes.MUSICSERVICEERROR, ex); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); - } - - if (result==null) { - logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build(); - }else if(result.getResult() == ResultType.FAILURE) { - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result.getResult()).setError(result.getMessage()).toMap()).build(); - } - return response.status(Status.OK).entity(new JsonResponse(result.getResult()).setMessage("Insert Successful").toMap()).build(); + queryObject.setOperation("insert"); + try { + if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) { + result = MusicCore.eventualPut(queryObject); + } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + String lockId = insObj.getConsistencyInfo().get("lockId"); + if(lockId == null) { + logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" + + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock " + + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build(); + } + result = MusicCore.criticalPut(keyspace, tablename, primaryKey, queryObject, lockId,null); + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + result = MusicCore.atomicPut(keyspace, tablename, primaryKey, queryObject, null); + } + } catch (Exception ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity + .WARN, ErrorTypes.MUSICSERVICEERROR, ex); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); + } + if (result==null) { + logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build(); + }else if(result.getResult() == ResultType.FAILURE) { + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result.getResult()).setError(result.getMessage()).toMap()).build(); + } + return response.status(Status.OK).entity(new JsonResponse(result.getResult()).setMessage("Insert Successful").toMap()).build(); } finally { EELFLoggerDelegate.mdcRemove("keyspace"); } @@ -887,208 +760,203 @@ public class RestMusicDataAPI { @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response updateTable( - @ApiParam(value = "Major Version", - required = true) @PathParam("version") String version, - @ApiParam(value = "Minor Version", - required = false) @HeaderParam(XMINORVERSION) String minorVersion, - @ApiParam(value = "Patch Version", - required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid, - @ApiParam(value = "Application namespace", - required = true) @HeaderParam(NS) String ns, - @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - JsonUpdate updateObj, - @ApiParam(value = "Keyspace Name", - required = true) @PathParam("keyspace") String keyspace, - @ApiParam(value = "Table Name", - required = true) @PathParam("tablename") String tablename, - @Context UriInfo info) throws MusicQueryException, MusicServiceException { + @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 = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, + JsonUpdate updateObj, + @ApiParam(value = "Keyspace Name", + required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Table Name", + required = true) @PathParam("tablename") String tablename, + @Context UriInfo info) throws MusicQueryException, MusicServiceException { try { - ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); - if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){ - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + 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(); - } - EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) "); - if (!authenticator.authenticateUser(ns, authorization, keyspace, aid, Operation.UPDATE_TABLE)) { - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check username, password and make sure your app is onboarded") - .toMap()).build(); - } - - long startTime = System.currentTimeMillis(); - String operationId = UUID.randomUUID().toString(); // just for infoging - // purposes. - String consistency = updateObj.getConsistencyInfo().get("type"); + } + EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) "); + long startTime = System.currentTimeMillis(); + String operationId = UUID.randomUUID().toString(); // just for infoging + // purposes. + String consistency = updateObj.getConsistencyInfo().get("type"); - logger.info(EELFLoggerDelegate.applicationLogger, "--------------Music " + consistency - + " update-" + operationId + "-------------------------"); - // obtain the field value pairs of the update + logger.info(EELFLoggerDelegate.applicationLogger, "--------------Music " + consistency + + " update-" + operationId + "-------------------------"); + // obtain the field value pairs of the update - PreparedQueryObject queryObject = new PreparedQueryObject(); - Map valuesMap = updateObj.getValues(); + PreparedQueryObject queryObject = new PreparedQueryObject(); + Map valuesMap = updateObj.getValues(); - TableMetadata tableInfo; - try { - tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename); - } catch (MusicServiceException e) { - logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes - .GENERALSERVICEERROR, e); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); - } - if (tableInfo == null) { - logger.error(EELFLoggerDelegate.errorLogger,"Table information not found. Please check input for table name= "+tablename, AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) - .setError("Table information not found. Please check input for table name= " - + keyspace + "." + tablename).toMap()).build(); - } - String vectorTs = String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis()); - StringBuilder fieldValueString = new StringBuilder("vector_ts=?,"); - queryObject.addValue(vectorTs); - int counter = 0; - for (Map.Entry entry : valuesMap.entrySet()) { - Object valueObj = entry.getValue(); - DataType colType = null; + TableMetadata tableInfo; try { - colType = tableInfo.getColumn(entry.getKey()).getType(); - } catch(NullPointerException ex) { - logger.error(EELFLoggerDelegate.errorLogger, ex, "Invalid column name : "+entry.getKey(), ex); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap()).build(); + tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename); + } catch (MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes + .GENERALSERVICEERROR, e); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); } - Object valueString = null; - try { - valueString = MusicUtil.convertToActualDataType(colType, valueObj); - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger,e); + if (tableInfo == null) { + logger.error(EELFLoggerDelegate.errorLogger,"Table information not found. Please check input for table name= "+tablename, AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + .setError("Table information not found. Please check input for table name= " + + keyspace + "." + tablename).toMap()).build(); + } + String vectorTs = String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis()); + StringBuilder fieldValueString = new StringBuilder("vector_ts=?,"); + queryObject.addValue(vectorTs); + int counter = 0; + for (Map.Entry entry : valuesMap.entrySet()) { + Object valueObj = entry.getValue(); + DataType colType = null; + try { + colType = tableInfo.getColumn(entry.getKey()).getType(); + } catch(NullPointerException ex) { + logger.error(EELFLoggerDelegate.errorLogger, ex, "Invalid column name : "+entry.getKey(), ex); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap()).build(); + } + Object valueString = null; + try { + valueString = MusicUtil.convertToActualDataType(colType, valueObj); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e); + } + fieldValueString.append(entry.getKey() + "= ?"); + queryObject.addValue(valueString); + if (counter != valuesMap.size() - 1) { + fieldValueString.append(","); + } + counter = counter + 1; + } + String ttl = updateObj.getTtl(); + String timestamp = updateObj.getTimestamp(); + + queryObject.appendQueryString("UPDATE " + keyspace + "." + tablename + " "); + if ((ttl != null) && (timestamp != null)) { + logger.info("both there"); + queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?"); + queryObject.addValue(Integer.parseInt(ttl)); + queryObject.addValue(Long.parseLong(timestamp)); } - fieldValueString.append(entry.getKey() + "= ?"); - queryObject.addValue(valueString); - if (counter != valuesMap.size() - 1) - fieldValueString.append(","); - counter = counter + 1; - } - String ttl = updateObj.getTtl(); - String timestamp = updateObj.getTimestamp(); - - queryObject.appendQueryString("UPDATE " + keyspace + "." + tablename + " "); - if ((ttl != null) && (timestamp != null)) { - logger.info("both there"); - queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?"); - queryObject.addValue(Integer.parseInt(ttl)); - queryObject.addValue(Long.parseLong(timestamp)); - } - if ((ttl != null) && (timestamp == null)) { - logger.info("ONLY TTL there"); - queryObject.appendQueryString(" USING TTL ?"); - queryObject.addValue(Integer.parseInt(ttl)); - } + if ((ttl != null) && (timestamp == null)) { + logger.info("ONLY TTL there"); + queryObject.appendQueryString(" USING TTL ?"); + queryObject.addValue(Integer.parseInt(ttl)); + } - if ((ttl == null) && (timestamp != null)) { - logger.info("ONLY timestamp there"); - queryObject.appendQueryString(" USING TIMESTAMP ?"); - queryObject.addValue(Long.parseLong(timestamp)); - } - // get the row specifier - RowIdentifier rowId = null; - try { - rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject); - if(rowId == null || rowId.primarKeyValue.isEmpty()) { - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) - .setError("Mandatory WHERE clause is missing. Please check the input request.").toMap()).build(); + if ((ttl == null) && (timestamp != null)) { + logger.info("ONLY timestamp there"); + queryObject.appendQueryString(" USING TIMESTAMP ?"); + queryObject.addValue(Long.parseLong(timestamp)); + } + // get the row specifier + RowIdentifier rowId = null; + try { + rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject); + if(rowId == null || rowId.primarKeyValue.isEmpty()) { + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + .setError("Mandatory WHERE clause is missing. Please check the input request.").toMap()).build(); + } + } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes + .GENERALSERVICEERROR, ex); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); } - } catch (MusicServiceException ex) { - logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes - .GENERALSERVICEERROR, ex); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); - } - queryObject.appendQueryString( - " SET " + fieldValueString + " WHERE " + rowId.rowIdString + ";"); - - // get the conditional, if any - Condition conditionInfo; - if (updateObj.getConditions() == null) - conditionInfo = null; - else { - // to avoid parsing repeatedly, just send the select query to obtain row - PreparedQueryObject selectQuery = new PreparedQueryObject(); - selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE " - + rowId.rowIdString + ";"); - selectQuery.addValue(rowId.primarKeyValue); - conditionInfo = new Condition(updateObj.getConditions(), selectQuery); - } + queryObject.appendQueryString( + " SET " + fieldValueString + " WHERE " + rowId.rowIdString + ";"); - ReturnType operationResult = null; - long jsonParseCompletionTime = System.currentTimeMillis(); + // get the conditional, if any + Condition conditionInfo; + if (updateObj.getConditions() == null) { + conditionInfo = null; + } else { + // to avoid parsing repeatedly, just send the select query to obtain row + PreparedQueryObject selectQuery = new PreparedQueryObject(); + selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE " + + rowId.rowIdString + ";"); + selectQuery.addValue(rowId.primarKeyValue); + conditionInfo = new Condition(updateObj.getConditions(), selectQuery); + } - if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && updateObj.getConsistencyInfo().get("consistency") != null) { - if(MusicUtil.isValidConsistency(updateObj.getConsistencyInfo().get("consistency"))) - queryObject.setConsistency(updateObj.getConsistencyInfo().get("consistency")); - else - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build(); - } - queryObject.setOperation("update"); - if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) - operationResult = MusicCore.eventualPut(queryObject); - else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { - String lockId = updateObj.getConsistencyInfo().get("lockId"); - if(lockId == null) { - logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" - + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock " - + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build(); + ReturnType operationResult = null; + long jsonParseCompletionTime = System.currentTimeMillis(); + + if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && updateObj.getConsistencyInfo().get("consistency") != null) { + if(MusicUtil.isValidConsistency(updateObj.getConsistencyInfo().get("consistency"))) { + queryObject.setConsistency(updateObj.getConsistencyInfo().get("consistency")); + } else { + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build(); + } } - operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue, - queryObject, lockId, conditionInfo); - } else if (consistency.equalsIgnoreCase("atomic_delete_lock")) { - // this function is mainly for the benchmarks - try { - operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, - rowId.primarKeyValue, queryObject, conditionInfo); - } catch (MusicLockingException e) { - logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, - ErrorTypes.GENERALSERVICEERROR, e); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); + queryObject.setOperation("update"); + if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) { + operationResult = MusicCore.eventualPut(queryObject); + } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + String lockId = updateObj.getConsistencyInfo().get("lockId"); + if(lockId == null) { + logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" + + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock " + + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build(); + } + operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue, + queryObject, lockId, conditionInfo); + } else if (consistency.equalsIgnoreCase("atomic_delete_lock")) { + // this function is mainly for the benchmarks + try { + operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, + rowId.primarKeyValue, queryObject, conditionInfo); + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, + ErrorTypes.GENERALSERVICEERROR, e); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); + } + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + try { + operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue, + queryObject, conditionInfo); + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR, e); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); + } + } else if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) { + operationResult = MusicCore.eventualPut_nb(queryObject, keyspace, tablename, rowId.primarKeyValue); } - } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { - try { - operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue, - queryObject, conditionInfo); - } catch (MusicLockingException e) { - logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR, e); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); + long actualUpdateCompletionTime = System.currentTimeMillis(); + + long endTime = System.currentTimeMillis(); + String timingString = "Time taken in ms for Music " + consistency + " update-" + operationId + + ":" + "|total operation time:" + (endTime - startTime) + + "|json parsing time:" + (jsonParseCompletionTime - startTime) + + "|update time:" + (actualUpdateCompletionTime - jsonParseCompletionTime) + + "|"; + + if (operationResult != null && operationResult.getTimingInfo() != null) { + String lockManagementTime = operationResult.getTimingInfo(); + timingString = timingString + lockManagementTime; } - }else if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) { - operationResult = MusicCore.eventualPut_nb(queryObject, keyspace, tablename, rowId.primarKeyValue); - } - long actualUpdateCompletionTime = System.currentTimeMillis(); - - long endTime = System.currentTimeMillis(); - String timingString = "Time taken in ms for Music " + consistency + " update-" + operationId - + ":" + "|total operation time:" + (endTime - startTime) - + "|json parsing time:" + (jsonParseCompletionTime - startTime) - + "|update time:" + (actualUpdateCompletionTime - jsonParseCompletionTime) - + "|"; - - if (operationResult != null && operationResult.getTimingInfo() != null) { - String lockManagementTime = operationResult.getTimingInfo(); - timingString = timingString + lockManagementTime; - } - logger.info(EELFLoggerDelegate.applicationLogger, timingString); + logger.info(EELFLoggerDelegate.applicationLogger, timingString); - if (operationResult==null) { - logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build(); - } - if ( operationResult.getResult() == ResultType.SUCCESS ) { - return response.status(Status.OK).entity(new JsonResponse(operationResult.getResult()).setMessage(operationResult.getMessage()).toMap()).build(); - } else { - logger.error(EELFLoggerDelegate.errorLogger,operationResult.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(operationResult.getResult()).setError(operationResult.getMessage()).toMap()).build(); - } + if (operationResult==null) { + logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build(); + } + if ( operationResult.getResult() == ResultType.SUCCESS ) { + return response.status(Status.OK).entity(new JsonResponse(operationResult.getResult()).setMessage(operationResult.getMessage()).toMap()).build(); + } else { + logger.error(EELFLoggerDelegate.errorLogger,operationResult.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(operationResult.getResult()).setError(operationResult.getMessage()).toMap()).build(); + } } finally { EELFLoggerDelegate.mdcRemove("keyspace"); } @@ -1111,142 +979,134 @@ public class RestMusicDataAPI { @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response deleteFromTable( - @ApiParam(value = "Major Version", - required = true) @PathParam("version") String version, - @ApiParam(value = "Minor Version", - required = false) @HeaderParam(XMINORVERSION) String minorVersion, - @ApiParam(value = "Patch Version", - required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid, - @ApiParam(value = "Application namespace", - required = true) @HeaderParam(NS) String ns, - @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - JsonDelete delObj, - @ApiParam(value = "Keyspace Name", - required = true) @PathParam("keyspace") String keyspace, - @ApiParam(value = "Table Name", - required = true) @PathParam("tablename") String tablename, - @Context UriInfo info) throws MusicQueryException, MusicServiceException { + @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 = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, + JsonDelete delObj, + @ApiParam(value = "Keyspace Name", + required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Table Name", + required = true) @PathParam("tablename") String tablename, + @Context UriInfo info) throws MusicQueryException, MusicServiceException { try { - ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); - if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){ - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + 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(); - } - EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) "); - if (!authenticator.authenticateUser(ns, authorization, keyspace, aid, Operation.DELETE_FROM_TABLE)) { - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check username, password and make sure your app is onboarded") - .toMap()).build(); - } - - if(delObj == null) { - logger.error(EELFLoggerDelegate.errorLogger,"Required HTTP Request body is missing.", AppMessages.MISSINGDATA ,ErrorSeverity.WARN, ErrorTypes.DATAERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Required HTTP Request body is missing.").toMap()).build(); - } - PreparedQueryObject queryObject = new PreparedQueryObject(); - StringBuilder columnString = new StringBuilder(); - - int counter = 0; - List columnList = delObj.getColumns(); - if (columnList != null) { - for (String column : columnList) { - columnString.append(column); - if (counter != columnList.size() - 1) - columnString.append(","); - counter = counter + 1; } - } - - // get the row specifier - RowIdentifier rowId = null; - try { - rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject); - } catch (MusicServiceException ex) { - logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes - .GENERALSERVICEERROR, ex); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); - } - String rowSpec = rowId.rowIdString.toString(); + EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) "); + if(delObj == null) { + logger.error(EELFLoggerDelegate.errorLogger,"Required HTTP Request body is missing.", AppMessages.MISSINGDATA ,ErrorSeverity.WARN, ErrorTypes.DATAERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Required HTTP Request body is missing.").toMap()).build(); + } + PreparedQueryObject queryObject = new PreparedQueryObject(); + StringBuilder columnString = new StringBuilder(); - if ((columnList != null) && (!rowSpec.isEmpty())) { - queryObject.appendQueryString("DELETE " + columnString + " FROM " + keyspace + "." - + tablename + " WHERE " + rowSpec + ";"); - } + int counter = 0; + List columnList = delObj.getColumns(); + if (columnList != null) { + for (String column : columnList) { + columnString.append(column); + if (counter != columnList.size() - 1) + columnString.append(","); + counter = counter + 1; + } + } - if ((columnList == null) && (!rowSpec.isEmpty())) { - queryObject.appendQueryString("DELETE FROM " + keyspace + "." + tablename + " WHERE " - + rowSpec + ";"); - } + // get the row specifier + RowIdentifier rowId = null; + try { + rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject); + } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes + .GENERALSERVICEERROR, ex); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); + } + String rowSpec = rowId.rowIdString.toString(); - if ((columnList != null) && (rowSpec.isEmpty())) { - queryObject.appendQueryString( - "DELETE " + columnString + " FROM " + keyspace + "." + rowSpec + ";"); - } - // get the conditional, if any - Condition conditionInfo; - if (delObj.getConditions() == null) { - conditionInfo = null; - } else { - // to avoid parsing repeatedly, just send the select query to - // obtain row - PreparedQueryObject selectQuery = new PreparedQueryObject(); - selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE " - + rowId.rowIdString + ";"); - selectQuery.addValue(rowId.primarKeyValue); - conditionInfo = new Condition(delObj.getConditions(), selectQuery); - } + if ((columnList != null) && (!rowSpec.isEmpty())) { + queryObject.appendQueryString("DELETE " + columnString + " FROM " + keyspace + "." + + tablename + " WHERE " + rowSpec + ";"); + } - String consistency = delObj.getConsistencyInfo().get("type"); + if ((columnList == null) && (!rowSpec.isEmpty())) { + queryObject.appendQueryString("DELETE FROM " + keyspace + "." + tablename + " WHERE " + + rowSpec + ";"); + } + if ((columnList != null) && (rowSpec.isEmpty())) { + queryObject.appendQueryString( + "DELETE " + columnString + " FROM " + keyspace + "." + rowSpec + ";"); + } + // get the conditional, if any + Condition conditionInfo; + if (delObj.getConditions() == null) { + conditionInfo = null; + } else { + // to avoid parsing repeatedly, just send the select query to + // obtain row + PreparedQueryObject selectQuery = new PreparedQueryObject(); + selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE " + + rowId.rowIdString + ";"); + selectQuery.addValue(rowId.primarKeyValue); + conditionInfo = new Condition(delObj.getConditions(), selectQuery); + } - if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && delObj.getConsistencyInfo().get("consistency")!=null) { + String consistency = delObj.getConsistencyInfo().get("type"); - if(MusicUtil.isValidConsistency(delObj.getConsistencyInfo().get("consistency"))) - queryObject.setConsistency(delObj.getConsistencyInfo().get("consistency")); - else - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build(); - } - ReturnType operationResult = null; - queryObject.setOperation("delete"); - try { - if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) - operationResult = MusicCore.eventualPut(queryObject); - else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { - String lockId = delObj.getConsistencyInfo().get("lockId"); - if(lockId == null) { - logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" + if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && delObj.getConsistencyInfo().get("consistency")!=null) { + if(MusicUtil.isValidConsistency(delObj.getConsistencyInfo().get("consistency"))) { + queryObject.setConsistency(delObj.getConsistencyInfo().get("consistency")); + } else { + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR) + .setError("Invalid Consistency type").toMap()).build(); + } + } + ReturnType operationResult = null; + queryObject.setOperation("delete"); + try { + if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) + operationResult = MusicCore.eventualPut(queryObject); + else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + String lockId = delObj.getConsistencyInfo().get("lockId"); + if(lockId == null) { + logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock " + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock " + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build(); - } - operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue, - queryObject, lockId, conditionInfo); - } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + } + operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue, + queryObject, lockId, conditionInfo); + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue, - queryObject, conditionInfo); - } else if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) { - - operationResult = MusicCore.eventualPut_nb(queryObject, keyspace, tablename, rowId.primarKeyValue); + queryObject, conditionInfo); + } else if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) { + operationResult = MusicCore.eventualPut_nb(queryObject, keyspace, tablename, rowId.primarKeyValue); + } + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR, e); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + .setError("Unable to perform Delete operation. Exception from music").toMap()).build(); + } + if (operationResult==null) { + logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build(); + } + if (operationResult.getResult().equals(ResultType.SUCCESS)) { + return response.status(Status.OK).entity(new JsonResponse(operationResult.getResult()).setMessage(operationResult.getMessage()).toMap()).build(); + } else { + logger.error(EELFLoggerDelegate.errorLogger,operationResult.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(operationResult.getMessage()).toMap()).build(); } - } catch (MusicLockingException e) { - logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR, e); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) - .setError("Unable to perform Delete operation. Exception from music").toMap()).build(); - } - if (operationResult==null) { - logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build(); - } - if (operationResult.getResult().equals(ResultType.SUCCESS)) { - return response.status(Status.OK).entity(new JsonResponse(operationResult.getResult()).setMessage(operationResult.getMessage()).toMap()).build(); - } else { - logger.error(EELFLoggerDelegate.errorLogger,operationResult.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(operationResult.getMessage()).toMap()).build(); - } } finally { EELFLoggerDelegate.mdcRemove("keyspace"); } @@ -1264,46 +1124,38 @@ public class RestMusicDataAPI { @ApiOperation(value = "Drop Table", response = String.class) @Produces(MediaType.APPLICATION_JSON) public Response dropTable( - @ApiParam(value = "Major Version", - required = true) @PathParam("version") String version, - @ApiParam(value = "Minor Version", - required = false) @HeaderParam(XMINORVERSION) String minorVersion, - @ApiParam(value = "Patch Version", - required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid, - @ApiParam(value = "Application namespace", - required = 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) throws Exception { - try { - ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); - 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(); - } - EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) "); - if (!authenticator.authenticateUser(ns, authorization, keyspace, aid, Operation.DROP_TABLE)) { - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check username, password and make sure your app is onboarded") - .toMap()).build(); - } - - String consistency = "eventual";// for now this needs only eventual - // consistency - PreparedQueryObject query = new PreparedQueryObject(); - query.appendQueryString("DROP TABLE " + keyspace + "." + tablename + ";"); + @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 = "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) throws Exception { try { - return response.status(Status.OK).entity(new JsonResponse(MusicCore.nonKeyRelatedPut(query, consistency)).toMap()).build(); - } catch (MusicServiceException ex) { - logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes - .GENERALSERVICEERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); - } + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + 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(); + } + EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) "); + String consistency = "eventual";// for now this needs only eventual consistency + PreparedQueryObject query = new PreparedQueryObject(); + query.appendQueryString("DROP TABLE " + keyspace + "." + tablename + ";"); + try { + return response.status(Status.OK).entity(new JsonResponse(MusicCore.nonKeyRelatedPut(query, consistency)).toMap()).build(); + } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes + .GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); + } } finally { EELFLoggerDelegate.mdcRemove("keyspace"); } @@ -1323,76 +1175,66 @@ public class RestMusicDataAPI { @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response selectCritical( - @ApiParam(value = "Major Version", - required = true) @PathParam("version") String version, - @ApiParam(value = "Minor Version", - required = false) @HeaderParam(XMINORVERSION) String minorVersion, - @ApiParam(value = "Patch Version", - required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid, - @ApiParam(value = "Application namespace", - required = true) @HeaderParam(NS) String ns, - @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, - 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 { - try { - ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); - 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(); - } - EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) "); - if (!authenticator.authenticateUser(ns, authorization, keyspace, aid, Operation.SELECT_CRITICAL)) { - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check username, password and make sure your app is onboarded") - .toMap()).build(); - } - - String lockId = selObj.getConsistencyInfo().get("lockId"); - - PreparedQueryObject queryObject = new PreparedQueryObject(); - - RowIdentifier rowId = null; + @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 = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, + 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 { try { - rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject); - } catch (MusicServiceException ex) { - logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes - .GENERALSERVICEERROR, ex); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); - } - queryObject.appendQueryString( - "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowId.rowIdString + ";"); + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + 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(); + } + EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) "); + String lockId = selObj.getConsistencyInfo().get("lockId"); + PreparedQueryObject queryObject = new PreparedQueryObject(); + RowIdentifier rowId = null; + try { + rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject); + } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes + .GENERALSERVICEERROR, ex); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); + } + queryObject.appendQueryString( + "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowId.rowIdString + ";"); - ResultSet results = null; + ResultSet results = null; - 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(); + 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(); + } + results = MusicCore.criticalGet(keyspace, tablename, rowId.primarKeyValue, queryObject,lockId); + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + results = MusicCore.atomicGet(keyspace, tablename, rowId.primarKeyValue, queryObject); } - results = MusicCore.criticalGet(keyspace, tablename, rowId.primarKeyValue, queryObject,lockId); - } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { - results = MusicCore.atomicGet(keyspace, tablename, rowId.primarKeyValue, queryObject); - } - }catch(Exception ex) { - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); - } - - if(results!=null && results.getAvailableWithoutFetching() >0) { - return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build(); - } - return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setError("No data found").toMap()).build(); - + }catch(Exception ex) { + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); + } + + if(results!=null && results.getAvailableWithoutFetching() >0) { + return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build(); + } + return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setError("No data found").toMap()).build(); } finally { EELFLoggerDelegate.mdcRemove("keyspace"); } @@ -1411,62 +1253,54 @@ public class RestMusicDataAPI { @ApiOperation(value = "Select All or Select Specific", response = Map.class) @Produces(MediaType.APPLICATION_JSON) public Response select( - @ApiParam(value = "Major Version", - required = true) @PathParam("version") String version, - @ApiParam(value = "Minor Version", - required = false) @HeaderParam(XMINORVERSION) String minorVersion, - @ApiParam(value = "Patch Version", - required = false) @HeaderParam(XPATCHVERSION) String patchVersion, - @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid, - @ApiParam(value = "Application namespace", - required = 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, - @Context UriInfo info) throws Exception { + @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 = "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, + @Context UriInfo info) throws Exception { try { - ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); - 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(); - } - EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) "); - if (!authenticator.authenticateUser(ns, authorization, keyspace, aid, Operation.SELECT)) { - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check username, password and make sure your app is onboarded") - .toMap()).build(); - } - - PreparedQueryObject queryObject = new PreparedQueryObject(); + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + 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(); + } + EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspace + " ) "); + PreparedQueryObject queryObject = new PreparedQueryObject(); - if (info.getQueryParameters().isEmpty())// select all - queryObject.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + ";"); - else { - int limit = -1; // do not limit the number of results + if (info.getQueryParameters().isEmpty()) { // select all + queryObject.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + ";"); + } else { + int limit = -1; // do not limit the number of results + try { + queryObject = selectSpecificQuery(keyspace, tablename, info, limit); + } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, + ErrorTypes.GENERALSERVICEERROR, ex); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); + } + } try { - queryObject = selectSpecificQuery(keyspace, tablename, info, limit); + ResultSet results = MusicCore.get(queryObject); + if(results.getAvailableWithoutFetching() >0) { + return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build(); + } + return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).setError("No data found").toMap()).build(); } catch (MusicServiceException ex) { - logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, - ErrorTypes.GENERALSERVICEERROR, ex); + logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.ERROR, + ErrorTypes.MUSICSERVICEERROR, ex); return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); } - } - - try { - ResultSet results = MusicCore.get(queryObject); - if(results.getAvailableWithoutFetching() >0) { - return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build(); - } - return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).setError("No data found").toMap()).build(); - } catch (MusicServiceException ex) { - logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.ERROR, - ErrorTypes.MUSICSERVICEERROR, ex); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); - } } finally { EELFLoggerDelegate.mdcRemove("keyspace"); } @@ -1482,23 +1316,18 @@ public class RestMusicDataAPI { * @throws MusicServiceException */ public PreparedQueryObject selectSpecificQuery(String keyspace, - String tablename, UriInfo info, int limit) - throws MusicServiceException { - + String tablename, UriInfo info, int limit) + throws MusicServiceException { PreparedQueryObject queryObject = new PreparedQueryObject(); - StringBuilder rowIdString = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), - queryObject).rowIdString; - + StringBuilder rowIdString = getRowIdentifier(keyspace, + tablename,info.getQueryParameters(),queryObject).rowIdString; queryObject.appendQueryString( - "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowIdString); - + "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowIdString); if (limit != -1) { queryObject.appendQueryString(" LIMIT " + limit); } - queryObject.appendQueryString(";"); return queryObject; - } /** @@ -1511,18 +1340,18 @@ public class RestMusicDataAPI { * @throws MusicServiceException */ private RowIdentifier getRowIdentifier(String keyspace, String tablename, - MultivaluedMap rowParams, PreparedQueryObject queryObject) - throws MusicServiceException { + MultivaluedMap rowParams, PreparedQueryObject queryObject) + throws MusicServiceException { StringBuilder rowSpec = new StringBuilder(); int counter = 0; TableMetadata tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename); if (tableInfo == null) { logger.error(EELFLoggerDelegate.errorLogger, - "Table information not found. Please check input for table name= " - + keyspace + "." + tablename); + "Table information not found. Please check input for table name= " + + keyspace + "." + tablename); throw new MusicServiceException( - "Table information not found. Please check input for table name= " - + keyspace + "." + tablename); + "Table information not found. Please check input for table name= " + + keyspace + "." + tablename); } StringBuilder primaryKey = new StringBuilder(); for (MultivaluedMap.Entry> entry : rowParams.entrySet()) { @@ -1537,12 +1366,14 @@ public class RestMusicDataAPI { } catch (Exception e) { logger.error(EELFLoggerDelegate.errorLogger,e); } - if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey())) - primaryKey.append(indValue); + if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey())) { + primaryKey.append(indValue); + } rowSpec.append(keyName + "= ?"); queryObject.addValue(formattedValue); - if (counter != rowParams.size() - 1) + if (counter != rowParams.size() - 1) { rowSpec.append(" AND "); + } counter = counter + 1; } return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject); diff --git a/src/main/java/org/onap/music/rest/RestMusicLocksAPI.java b/src/main/java/org/onap/music/rest/RestMusicLocksAPI.java index 49b2d816..e27c08ee 100644 --- a/src/main/java/org/onap/music/rest/RestMusicLocksAPI.java +++ b/src/main/java/org/onap/music/rest/RestMusicLocksAPI.java @@ -4,8 +4,9 @@ * =================================================================== * Copyright (c) 2017 AT&T Intellectual Property * =================================================================== - * Modifications Copyright (c) 2019 Samsung + * * Modifications Copyright (c) 2019 Samsung * =================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -24,6 +25,7 @@ package org.onap.music.rest; +import java.util.List; import java.util.Map; import javax.ws.rs.Consumes; @@ -39,15 +41,14 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.ResponseBuilder; import javax.ws.rs.core.Response.Status; -import org.onap.music.authentication.MusicAAFAuthentication; -import org.onap.music.authentication.MusicAuthenticator; -import org.onap.music.authentication.MusicAuthenticator.Operation; import org.onap.music.datastore.jsonobjects.JsonLeasedLock; +import org.onap.music.datastore.jsonobjects.JsonLock; import org.onap.music.eelf.logging.EELFLoggerDelegate; import org.onap.music.eelf.logging.format.AppMessages; import org.onap.music.eelf.logging.format.ErrorSeverity; import org.onap.music.eelf.logging.format.ErrorTypes; import org.onap.music.exceptions.MusicLockingException; +import org.onap.music.lockingservice.cassandra.LockType; import org.onap.music.lockingservice.cassandra.MusicLockState; import org.onap.music.main.MusicCore; import org.onap.music.main.MusicUtil; @@ -69,8 +70,6 @@ public class RestMusicLocksAPI { private static final String XPATCHVERSION = "X-patchVersion"; private static final String VERSION = "v2"; - private MusicAuthenticator authenticator = new MusicAAFAuthentication(); - /** * Puts the requesting process in the q for this lock. The corresponding * node will be created if it did not already exist @@ -86,6 +85,7 @@ public class RestMusicLocksAPI { " The corresponding lock will be created if it did not already exist." + " Lock Name is the \"key\" of the form keyspaceName.tableName.rowId", response = Map.class) + @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response createLockReference( @ApiParam(value="Lock Name",required=true) @PathParam("lockname") String lockName, @@ -93,40 +93,37 @@ public class RestMusicLocksAPI { @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, + JsonLock lockObject, @ApiParam(value = "Application namespace", required = true) @HeaderParam("ns") String ns) throws Exception{ try { - ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); - Map resultMap = MusicCore.validateLock(lockName); - if (resultMap.containsKey("Error")) { - logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); - response.status(Status.BAD_REQUEST); - return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()).build(); - } - String keyspaceName = (String) resultMap.get("keyspace"); - EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) "); - - if (!authenticator.authenticateUser(ns, authorization, keyspaceName, aid, Operation.CREATE_LOCKREF)) { - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check username, password and make sure your app is onboarded") - .toMap()).build(); - } - - ResultType status = ResultType.SUCCESS; - String lockId; - try { - lockId= MusicCore.createLockReference(lockName); - } catch (MusicLockingException e) { - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); - } - - if (lockId == null) { - status = ResultType.FAILURE; - logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.LOCKINGERROR ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(status).setError("Lock Id is null").toMap()).build(); - } - return response.status(Status.OK).entity(new JsonResponse(status).setLock(lockId).toMap()).build(); + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + Map resultMap = MusicCore.validateLock(lockName); + if (resultMap.containsKey("Error")) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + response.status(Status.BAD_REQUEST); + return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()).build(); + } + String keyspaceName = (String) resultMap.get("keyspace"); + EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspaceName + " ) "); + + //default lock type is write, as this is always semantically safe + LockType locktype = LockType.WRITE; + if (lockObject!=null && lockObject.getLocktype()!=null) { + locktype = lockObject.getLocktype(); + } + String lockId; + try { + lockId= MusicCore.createLockReference(lockName, locktype); + } catch (MusicLockingException e) { + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); + } + + if (lockId == null) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.LOCKINGERROR ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Lock Id is null").toMap()).build(); + } + return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setLock(lockId).toMap()).build(); } finally { EELFLoggerDelegate.mdcRemove("keyspace"); } @@ -155,38 +152,30 @@ public class RestMusicLocksAPI { @ApiParam(value = "Application namespace", required = true) @HeaderParam("ns") String ns) throws Exception{ try { - ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); - Map resultMap = MusicCore.validateLock(lockId); - if (resultMap.containsKey("Error")) { - logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); - response.status(Status.BAD_REQUEST); - return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()).build(); - } - - String keyspaceName = (String) resultMap.get("keyspace"); - EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) "); - - if (!authenticator.authenticateUser(ns, authorization, keyspaceName, aid, Operation.ACQUIRE_LOCK)) { - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check username, password and make sure your app is onboarded") - .toMap()).build(); - } - - try { - String lockName = lockId.substring(lockId.indexOf('$')+1, lockId.lastIndexOf('$')); - ReturnType lockStatus = MusicCore.acquireLock(lockName,lockId); - if ( lockStatus.getResult().equals(ResultType.SUCCESS)) { - response.status(Status.OK); - } else { + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + Map resultMap = MusicCore.validateLock(lockId); + if (resultMap.containsKey("Error")) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); response.status(Status.BAD_REQUEST); + return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()).build(); + } + + String keyspaceName = (String) resultMap.get("keyspace"); + EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspaceName + " ) "); + try { + String lockName = lockId.substring(lockId.indexOf('$')+1, lockId.lastIndexOf('$')); + ReturnType lockStatus = MusicCore.acquireLock(lockName,lockId); + if ( lockStatus.getResult().equals(ResultType.SUCCESS)) { + response.status(Status.OK); + } else { + response.status(Status.BAD_REQUEST); + } + return response.entity(new JsonResponse(lockStatus.getResult()).setLock(lockId).setMessage(lockStatus.getMessage()).toMap()).build(); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,AppMessages.INVALIDLOCK + lockId, ErrorSeverity.CRITICAL, + ErrorTypes.LOCKINGERROR, e); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Unable to aquire lock").toMap()).build(); } - return response.entity(new JsonResponse(lockStatus.getResult()).setLock(lockId).setMessage(lockStatus.getMessage()).toMap()).build(); - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger,AppMessages.INVALIDLOCK + lockId, ErrorSeverity.CRITICAL, - ErrorTypes.LOCKINGERROR, e); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Unable to aquire lock").toMap()).build(); - } } finally { EELFLoggerDelegate.mdcRemove("keyspace"); } @@ -209,33 +198,25 @@ public class RestMusicLocksAPI { @ApiParam(value = "Application namespace", required = true) @HeaderParam("ns") String ns) throws Exception{ try { - ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); - Map resultMap = MusicCore.validateLock(lockId); - if (resultMap.containsKey("Error")) { - logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); - response.status(Status.BAD_REQUEST); - return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()).build(); - } - String keyspaceName = (String) resultMap.get("keyspace"); - EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) "); - resultMap.remove("keyspace"); - if (!authenticator.authenticateUser(ns, authorization, keyspaceName, aid, Operation.ACQUIRE_LOCK)) { - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check username, password and make sure your app is onboarded") - .toMap()).build(); - } - - String lockName = lockId.substring(lockId.indexOf('$')+1, lockId.lastIndexOf('$')); - ReturnType lockLeaseStatus = MusicCore.acquireLockWithLease(lockName, lockId, lockObj.getLeasePeriod()); - if ( lockLeaseStatus.getResult().equals(ResultType.SUCCESS)) { - response.status(Status.OK); - } else { - response.status(Status.BAD_REQUEST); - } - return response.entity(new JsonResponse(lockLeaseStatus.getResult()).setLock(lockName) - .setMessage(lockLeaseStatus.getMessage()) - .setLockLease(String.valueOf(lockObj.getLeasePeriod())).toMap()).build(); + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + Map resultMap = MusicCore.validateLock(lockId); + if (resultMap.containsKey("Error")) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + response.status(Status.BAD_REQUEST); + return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()).build(); + } + String keyspaceName = (String) resultMap.get("keyspace"); + EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspaceName + " ) "); + String lockName = lockId.substring(lockId.indexOf('$')+1, lockId.lastIndexOf('$')); + ReturnType lockLeaseStatus = MusicCore.acquireLockWithLease(lockName, lockId, lockObj.getLeasePeriod()); + if ( lockLeaseStatus.getResult().equals(ResultType.SUCCESS)) { + response.status(Status.OK); + } else { + response.status(Status.BAD_REQUEST); + } + return response.entity(new JsonResponse(lockLeaseStatus.getResult()).setLock(lockName) + .setMessage(lockLeaseStatus.getMessage()) + .setLockLease(String.valueOf(lockObj.getLeasePeriod())).toMap()).build(); } finally { EELFLoggerDelegate.mdcRemove("keyspace"); } @@ -244,11 +225,11 @@ public class RestMusicLocksAPI { @GET @Path("/enquire/{lockname}") - @ApiOperation(value = "Get Lock Holder", - notes = "Gets the current Lock Holder", + @ApiOperation(value = "Get the top of the lock queue", + notes = "Gets the current single lockholder at top of lock queue", response = Map.class) @Produces(MediaType.APPLICATION_JSON) - public Response currentLockHolder( + 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, @@ -257,39 +238,76 @@ public class RestMusicLocksAPI { @ApiParam(value = "Application namespace", required = true) @HeaderParam("ns") String ns) throws Exception{ try { - ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); - Map resultMap = MusicCore.validateLock(lockName); - if (resultMap.containsKey("Error")) { - logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); - response.status(Status.BAD_REQUEST); - return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()).build(); + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + Map resultMap = MusicCore.validateLock(lockName); + if (resultMap.containsKey("Error")) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + response.status(Status.BAD_REQUEST); + return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()).build(); + } + String keyspaceName = (String) resultMap.get("keyspace"); + EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspaceName + " ) "); + String who = MusicCore.whoseTurnIsIt(lockName); + ResultType status = ResultType.SUCCESS; + String error = ""; + if ( who == null ) { + status = ResultType.FAILURE; + error = "There was a problem getting the lock holder"; + logger.error(EELFLoggerDelegate.errorLogger,"There was a problem getting the lock holder", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).toMap()).build(); + } + return response.status(Status.OK).entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).toMap()).build(); + } finally { + EELFLoggerDelegate.mdcRemove("keyspace"); } + } - String keyspaceName = (String) resultMap.get("keyspace"); - EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) "); - resultMap.remove("keyspace"); - if (!authenticator.authenticateUser(ns, authorization, keyspaceName, aid, Operation.CURRENT_LOCK)) { - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check username, password and make sure your app is onboarded") - .toMap()).build(); - } - - String who = MusicCore.whoseTurnIsIt(lockName); - ResultType status = ResultType.SUCCESS; - String error = ""; - if ( who == null ) { - status = ResultType.FAILURE; - error = "There was a problem getting the lock holder"; - logger.error(EELFLoggerDelegate.errorLogger,"There was a problem getting the lock holder", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).toMap()).build(); - } - return response.status(Status.OK).entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).toMap()).build(); + @GET + @Path("/getCurrentLockHolders/{lockname}") + @ApiOperation(value = "Get Lock Holders", + notes = "Gets the current Lock Holders", + response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + public Response currentLockHolder(@ApiParam(value="Lock Name",required=true) @PathParam("lockname") String lockName, + @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, + @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, + @ApiParam(value = "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{ + try { + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + Map resultMap = MusicCore.validateLock(lockName); + if (resultMap.containsKey("Error")) { + logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.INCORRECTDATA, ErrorSeverity.CRITICAL, + ErrorTypes.GENERALSERVICEERROR); + response.status(Status.BAD_REQUEST); + return response.entity( + new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()) + .build(); + } + String keyspaceName = (String) resultMap.get("keyspace"); + List who = MusicCore.getCurrentLockHolders(lockName); + ResultType status = ResultType.SUCCESS; + String error = ""; + if (who == null) { + status = ResultType.FAILURE; + error = "There was a problem getting the lock holder"; + logger.error(EELFLoggerDelegate.errorLogger, "There was a problem getting the lock holder", + AppMessages.INCORRECTDATA, ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST) + .entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).toMap()) + .build(); + } + return response.status(Status.OK) + .entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).toMap()) + .build(); } finally { EELFLoggerDelegate.mdcRemove("keyspace"); } } - + + @GET @Path("/{lockname}") @ApiOperation(value = "Lock State", @@ -305,33 +323,25 @@ public class RestMusicLocksAPI { @ApiParam(value = "Application namespace", required = true) @HeaderParam("ns") String ns) throws Exception{ try { - ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); - Map resultMap = MusicCore.validateLock(lockName); - if (resultMap.containsKey("Error")) { - logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); - response.status(Status.BAD_REQUEST); - return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()).build(); - } - String keyspaceName = (String) resultMap.get("keyspace"); - EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) "); - resultMap.remove("keyspace"); - if (!authenticator.authenticateUser(ns, authorization, keyspaceName, aid, Operation.CURRENT_LOCK)) { - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check username, password and make sure your app is onboarded") - .toMap()).build(); - } - - String who = MusicCore.whoseTurnIsIt(lockName); - ResultType status = ResultType.SUCCESS; - String error = ""; - if ( who == null ) { - status = ResultType.FAILURE; - error = "There was a problem getting the lock holder"; - logger.error(EELFLoggerDelegate.errorLogger,"There was a problem getting the lock holder", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).toMap()).build(); - } - return response.status(Status.OK).entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).toMap()).build(); + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + Map resultMap = MusicCore.validateLock(lockName); + if (resultMap.containsKey("Error")) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + response.status(Status.BAD_REQUEST); + return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()).build(); + } + String keyspaceName = (String) resultMap.get("keyspace"); + EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) "); + String who = MusicCore.whoseTurnIsIt(lockName); + ResultType status = ResultType.SUCCESS; + String error = ""; + if ( who == null ) { + status = ResultType.FAILURE; + error = "There was a problem getting the lock holder"; + logger.error(EELFLoggerDelegate.errorLogger,"There was a problem getting the lock holder", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).toMap()).build(); + } + return response.status(Status.OK).entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).toMap()).build(); } finally { EELFLoggerDelegate.mdcRemove("keyspace"); } @@ -357,61 +367,52 @@ public class RestMusicLocksAPI { @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{ + required = true) @HeaderParam("ns") String ns) throws Exception{ try { - ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); - Map resultMap = MusicCore.validateLock(lockId); - if (resultMap.containsKey("Error")) { - logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); - response.status(Status.BAD_REQUEST); - return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()).build(); - } + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + Map resultMap = MusicCore.validateLock(lockId); + if (resultMap.containsKey("Error")) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + response.status(Status.BAD_REQUEST); + return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()).build(); + } - String keyspaceName = (String) resultMap.get("keyspace"); - EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) "); - resultMap.remove("keyspace"); - if (!authenticator.authenticateUser(ns, authorization, keyspaceName, aid, Operation.DELETE_LOCK)) { - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check username, password and make sure your app is onboarded") - .toMap()).build(); - } - - boolean voluntaryRelease = true; - MusicLockState mls = MusicCore.releaseLock(lockId,voluntaryRelease); - if(mls.getErrorMessage() != null) { - resultMap.put(ResultType.EXCEPTION.getResult(), mls.getErrorMessage()); - logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); - return response.status(Status.BAD_REQUEST).entity(resultMap).build(); - } - Map returnMap = null; - if (mls.getLockStatus() == MusicLockState.LockStatus.UNLOCKED) { - returnMap = new JsonResponse(ResultType.SUCCESS).setLock(lockId) - .setLockStatus(mls.getLockStatus()).toMap(); - response.status(Status.OK); - } - if (mls.getLockStatus() == MusicLockState.LockStatus.LOCKED) { - logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.LOCKINGERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); - returnMap = new JsonResponse(ResultType.FAILURE).setLock(lockId) - .setLockStatus(mls.getLockStatus()).toMap(); - response.status(Status.BAD_REQUEST); - } - return response.entity(returnMap).build(); + String keyspaceName = (String) resultMap.get("keyspace"); + EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) "); + boolean voluntaryRelease = true; + MusicLockState mls = MusicCore.releaseLock(lockId,voluntaryRelease); + if(mls.getErrorMessage() != null) { + resultMap.put(ResultType.EXCEPTION.getResult(), mls.getErrorMessage()); + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + return response.status(Status.BAD_REQUEST).entity(resultMap).build(); + } + Map returnMap = null; + if (mls.getLockStatus() == MusicLockState.LockStatus.UNLOCKED) { + returnMap = new JsonResponse(ResultType.SUCCESS).setLock(lockId) + .setLockStatus(mls.getLockStatus()).toMap(); + response.status(Status.OK); + } + if (mls.getLockStatus() == MusicLockState.LockStatus.LOCKED) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.LOCKINGERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + returnMap = new JsonResponse(ResultType.FAILURE).setLock(lockId) + .setLockStatus(mls.getLockStatus()).toMap(); + response.status(Status.BAD_REQUEST); + } + return response.entity(returnMap).build(); } finally { EELFLoggerDelegate.mdcRemove("keyspace"); } } /** - * @deprecated + * * @param lockName * @throws Exception */ @DELETE @Path("/delete/{lockname}") - @ApiOperation(value = "Delete Lock", response = Map.class, hidden = true, notes = "Deprecated") - @Produces(MediaType.APPLICATION_JSON) - @Deprecated + @ApiOperation(value = "Delete Lock", response = Map.class) + @Produces(MediaType.APPLICATION_JSON) public Response deleteLock(@PathParam("lockname") String lockName, @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, @@ -420,31 +421,23 @@ public class RestMusicLocksAPI { @ApiParam(value = "Application namespace", required = true) @HeaderParam("ns") String ns) throws Exception{ try { - ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); - Map resultMap = MusicCore.validateLock(lockName); - if (resultMap.containsKey("Error")) { - logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); - response.status(Status.BAD_REQUEST); - return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()).build(); - } + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + Map resultMap = MusicCore.validateLock(lockName); + if (resultMap.containsKey("Error")) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + response.status(Status.BAD_REQUEST); + return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()).build(); + } - String keyspaceName = (String) resultMap.get("keyspace"); - EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) "); - resultMap.remove("keyspace"); - if (!authenticator.authenticateUser(ns, authorization, keyspaceName, aid, Operation.DELETE_LOCK)) { - return response.status(Status.UNAUTHORIZED) - .entity(new JsonResponse(ResultType.FAILURE) - .setError("Unauthorized: Please check username, password and make sure your app is onboarded") - .toMap()).build(); - } - - try{ - MusicCore.deleteLock(lockName); - }catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger, e); - return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); - } - return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).toMap()).build(); + String keyspaceName = (String) resultMap.get("keyspace"); + EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspaceName + " ) "); + try{ + MusicCore.destroyLockRef(lockName); + }catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); + } + return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).toMap()).build(); } finally { EELFLoggerDelegate.mdcRemove("keyspace"); } diff --git a/src/main/java/org/onap/music/rest/RestMusicQAPI.java b/src/main/java/org/onap/music/rest/RestMusicQAPI.java index 3940c84a..768f1a44 100755 --- a/src/main/java/org/onap/music/rest/RestMusicQAPI.java +++ b/src/main/java/org/onap/music/rest/RestMusicQAPI.java @@ -312,7 +312,7 @@ public class RestMusicQAPI { JsonDelete delObj, @ApiParam(value = "Key Space", required = true) @PathParam("keyspace") String keyspace, @ApiParam(value = "Table Name", required = true) @PathParam("qname") String tablename, - @Context UriInfo info) throws MusicServiceException, MusicQueryException { + @Context UriInfo info) throws MusicServiceException, MusicQueryException { // added checking as per RestMusicDataAPI ResponseBuilder response = MusicUtil.buildVersionResponse(version, minorVersion, patchVersion); if (delObj == null) { @@ -348,11 +348,11 @@ public class RestMusicQAPI { @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, @ApiParam(value = "Key Space", required = true) @PathParam("keyspace") String keyspace, @ApiParam(value = "Table Name", required = true) @PathParam("qname") String tablename, - @Context UriInfo info) { + @Context UriInfo info) { int limit =1; //peek must return just the top row - Map auth = new HashMap<>(); - String userId =auth.get(MusicUtil.USERID); - String password =auth.get(MusicUtil.PASSWORD); + // Map auth = new HashMap<>(); + // String userId =auth.get(MusicUtil.USERID); + // String password =auth.get(MusicUtil.PASSWORD); ResponseBuilder response = MusicUtil.buildVersionResponse(version, minorVersion, patchVersion); PreparedQueryObject queryObject = new PreparedQueryObject(); @@ -377,7 +377,7 @@ public class RestMusicQAPI { .setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build(); } catch (MusicServiceException ex) { logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.UNKNOWNERROR, - ErrorSeverity.ERROR, ErrorTypes.MUSICSERVICEERROR, ex); + ErrorSeverity.ERROR, ErrorTypes.MUSICSERVICEERROR, ex); return response.status(Status.BAD_REQUEST) .entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()) .build(); diff --git a/src/main/java/org/onap/music/service/MusicCoreService.java b/src/main/java/org/onap/music/service/MusicCoreService.java index 61e4905e..a50e7c2a 100644 --- a/src/main/java/org/onap/music/service/MusicCoreService.java +++ b/src/main/java/org/onap/music/service/MusicCoreService.java @@ -29,6 +29,7 @@ import org.onap.music.datastore.PreparedQueryObject; import org.onap.music.exceptions.MusicLockingException; import org.onap.music.exceptions.MusicQueryException; import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.lockingservice.cassandra.LockType; import org.onap.music.lockingservice.cassandra.MusicLockState; import org.onap.music.main.ResultType; import org.onap.music.main.ReturnType; @@ -72,8 +73,22 @@ public interface MusicCoreService { // Core Music Locking Service Methods + /** + * Create a lock ref in the music lock store. + * Default is write as this is the safest semantically + * + * @param fullyQualifiedKey the key to create a lock on + * @see {@link #creatLockReference(String, LockType)} + */ public String createLockReference(String fullyQualifiedKey) throws MusicLockingException; // lock name + /** + * Create a lock ref in the music lock store + * @param fullyQualifiedKey the key to create a lock on + * @param locktype the type of lock create, see {@link LockType} + */ + public String createLockReference(String fullyQualifiedKey, LockType locktype) throws MusicLockingException; + public ReturnType acquireLockWithLease(String key, String lockReference, long leasePeriod) throws MusicLockingException, MusicQueryException, MusicServiceException; // key,lock id,time @@ -85,7 +100,19 @@ public interface MusicCoreService { public ResultSet quorumGet(PreparedQueryObject query); + /** + * Gets top of queue for fullyQualifiedKey + * @param fullyQualifiedKey + * @return + */ public String whoseTurnIsIt(String fullyQualifiedKey);// lock name + + /** + * Gets the current lockholder(s) for lockName + * @param lockName + * @return + */ + public List getCurrentLockHolders(String fullyQualifiedKey); public void destroyLockRef(String lockId) throws MusicLockingException; @@ -107,4 +134,5 @@ public interface MusicCoreService { public Map validateLock(String lockName); public MusicLockState releaseLock(String lockId, boolean voluntaryRelease) throws MusicLockingException; + } 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 ed5005c1..cf6f5ed3 100644 --- a/src/main/java/org/onap/music/service/impl/MusicCassaCore.java +++ b/src/main/java/org/onap/music/service/impl/MusicCassaCore.java @@ -43,6 +43,7 @@ import org.onap.music.exceptions.MusicQueryException; import org.onap.music.exceptions.MusicServiceException; import org.onap.music.lockingservice.cassandra.CassaLockStore; import org.onap.music.lockingservice.cassandra.CassaLockStore.LockObject; +import org.onap.music.lockingservice.cassandra.LockType; import org.onap.music.lockingservice.cassandra.MusicLockState; import org.onap.music.lockingservice.cassandra.MusicLockState.LockStatus; import org.onap.music.main.MusicUtil; @@ -93,9 +94,11 @@ public class MusicCassaCore implements MusicCoreService { return mLockHandle; } - - public String createLockReference(String fullyQualifiedKey) throws MusicLockingException { + return createLockReference(fullyQualifiedKey, LockType.WRITE); + } + + public String createLockReference(String fullyQualifiedKey, LockType locktype) throws MusicLockingException { String[] splitString = fullyQualifiedKey.split("\\."); String keyspace = splitString[0]; String table = splitString[1]; @@ -106,7 +109,7 @@ public class MusicCassaCore implements MusicCoreService { String lockReference = null; try { - lockReference = "" + getLockingServiceHandle().genLockRefandEnQueue(keyspace, table, lockName); + lockReference = "" + getLockingServiceHandle().genLockRefandEnQueue(keyspace, table, lockName, locktype); } catch (MusicLockingException | MusicServiceException | MusicQueryException e) { e.printStackTrace(); throw new MusicLockingException("Unable to create lock reference. " + e.getMessage()); @@ -120,58 +123,37 @@ public class MusicCassaCore implements MusicCoreService { } - public ReturnType acquireLockWithLease(String fullyQualifiedKey, String lockReference, long leasePeriod) throws MusicLockingException, MusicQueryException, MusicServiceException { - evictExpiredLockHolder(fullyQualifiedKey,leasePeriod); - return acquireLock(fullyQualifiedKey, lockReference); + public ReturnType acquireLockWithLease(String fullyQualifiedKey, String lockReference, long leasePeriod) + throws MusicLockingException, MusicQueryException, MusicServiceException { + evictExpiredLockHolder(fullyQualifiedKey,leasePeriod); + return acquireLock(fullyQualifiedKey, lockReference); } - private void evictExpiredLockHolder(String fullyQualifiedKey, long leasePeriod) throws MusicLockingException, MusicQueryException, MusicServiceException { - + private void evictExpiredLockHolder(String fullyQualifiedKey, long leasePeriod) + throws MusicLockingException, MusicQueryException, MusicServiceException { String[] splitString = fullyQualifiedKey.split("\\."); String keyspace = splitString[0]; String table = splitString[1]; String primaryKeyValue = splitString[2]; LockObject currentLockHolderObject = getLockingServiceHandle().peekLockQueue(keyspace, table, primaryKeyValue); - - if (currentLockHolderObject==null) { //no lock holder - return; - } - /* Release the lock of the previous holder if it has expired. if the update to the acquire time has not reached due to network delays, simply use the create time as the - * reference*/ - long referenceTime = Math.max(Long.parseLong(currentLockHolderObject.acquireTime), Long.parseLong(currentLockHolderObject.createTime)); - if((System.currentTimeMillis() - referenceTime) > leasePeriod) { - forciblyReleaseLock(fullyQualifiedKey, currentLockHolderObject.lockRef+""); - logger.info(EELFLoggerDelegate.applicationLogger, currentLockHolderObject.lockRef+" forcibly released"); - } - } - - private static ReturnType isTopOfLockStore(String keyspace, String table, String primaryKeyValue, String lockReference) throws MusicLockingException, MusicQueryException, MusicServiceException { - //return failure to lock holders too early or already evicted from the lock store - LockObject topOfLockStore = getLockingServiceHandle().peekLockQueue(keyspace, table, primaryKeyValue); - if (topOfLockStore==null) { - logger.info(EELFLoggerDelegate.applicationLogger, lockReference+" is not the lock holder yet"); - return new ReturnType(ResultType.FAILURE, "No lock holder!"); - } - - String topOfLockStoreS = topOfLockStore.lockRef; - long topOfLockStoreL = Long.parseLong(topOfLockStoreS); - long lockReferenceL = Long.parseLong(lockReference); - if(lockReferenceL > topOfLockStoreL) { - logger.info(EELFLoggerDelegate.applicationLogger, lockReference+" is not the lock holder yet"); - return new ReturnType(ResultType.FAILURE, lockReference+" is not the lock holder yet"); + if (!currentLockHolderObject.getIsLockOwner()) { // no lock holder + return; } - - if(lockReferenceL < topOfLockStoreL) { - logger.info(EELFLoggerDelegate.applicationLogger, lockReference+" is no longer/or was never in the lock store queue"); - return new ReturnType(ResultType.FAILURE, lockReference+" is no longer/or was never in the lock store queue"); + /* + * Release the lock of the previous holder if it has expired. if the update to the acquire time has + * not reached due to network delays, simply use the create time as the reference + */ + long referenceTime = Math.max(Long.parseLong(currentLockHolderObject.getAcquireTime()), + Long.parseLong(currentLockHolderObject.getCreateTime())); + if ((System.currentTimeMillis() - referenceTime) > leasePeriod) { + forciblyReleaseLock(fullyQualifiedKey, currentLockHolderObject.getLockRef() + ""); + logger.info(EELFLoggerDelegate.applicationLogger, currentLockHolderObject.getLockRef() + " forcibly released"); } - - return new ReturnType(ResultType.SUCCESS, lockReference+" is top of lock store"); } - public ReturnType acquireLock(String fullyQualifiedKey, String lockId) + public ReturnType acquireLock(String fullyQualifiedKey, String lockId) throws MusicLockingException, MusicQueryException, MusicServiceException { String[] splitString = lockId.split("\\."); String keyspace = splitString[0].substring(1);//remove '$' @@ -180,11 +162,12 @@ public class MusicCassaCore implements MusicCoreService { String localFullyQualifiedKey = lockId.substring(1, lockId.lastIndexOf("$")); String lockRef = lockId.substring(lockId.lastIndexOf("$")+1); //lockRef is "$" to end - ReturnType result = isTopOfLockStore(keyspace, table, primaryKeyValue, lockRef); - - if(result.getResult().equals(ResultType.FAILURE)) - return result;//not top of the lock store q + LockObject lockInfo = getLockingServiceHandle().getLockInfo(keyspace, table, primaryKeyValue, lockRef); + if (!lockInfo.getIsLockOwner()) { + return new ReturnType(ResultType.FAILURE, lockId + " is not a lock holder");//not top of the lock store q + } + //check to see if the value of the key has to be synced in case there was a forceful release String syncTable = keyspace+".unsyncedKeys_"+table; String query = "select * from "+syncTable+" where key='"+localFullyQualifiedKey+"';"; @@ -224,37 +207,37 @@ public class MusicCassaCore implements MusicCoreService { * * */ - public ResultType createTable(String keyspace, String table, PreparedQueryObject tableQueryObject, String consistency) throws MusicServiceException { - boolean result = false; - - try { - //create shadow locking table - result = getLockingServiceHandle().createLockQueue(keyspace, table); - if(result == false) - return ResultType.FAILURE; + public ResultType createTable(String keyspace, String table, PreparedQueryObject tableQueryObject, + String consistency) throws MusicServiceException { + boolean result = false; - result = false; + try { + // create shadow locking table + result = getLockingServiceHandle().createLockQueue(keyspace, table); + if (result == false) + return ResultType.FAILURE; - //create table to track unsynced_keys - table = "unsyncedKeys_"+table; + result = false; - String tabQuery = "CREATE TABLE IF NOT EXISTS "+keyspace+"."+table - + " ( key text,PRIMARY KEY (key) );"; - PreparedQueryObject queryObject = new PreparedQueryObject(); + // create table to track unsynced_keys + table = "unsyncedKeys_" + table; - queryObject.appendQueryString(tabQuery); - result = false; - result = MusicDataStoreHandle.getDSHandle().executePut(queryObject, "eventual"); + String tabQuery = + "CREATE TABLE IF NOT EXISTS " + keyspace + "." + table + " ( key text,PRIMARY KEY (key) );"; + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString(tabQuery); + result = false; + result = MusicDataStoreHandle.getDSHandle().executePut(queryObject, "eventual"); - //create actual table - result = MusicDataStoreHandle.getDSHandle().executePut(tableQueryObject, consistency); - } catch (MusicQueryException | MusicServiceException | MusicLockingException ex) { - logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity - .WARN, ErrorTypes.MUSICSERVICEERROR, ex); - throw new MusicServiceException(ex.getMessage()); - } - return result?ResultType.SUCCESS:ResultType.FAILURE; + // create actual table + result = MusicDataStoreHandle.getDSHandle().executePut(tableQueryObject, consistency); + } catch (MusicQueryException | MusicServiceException | MusicLockingException ex) { + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), AppMessages.UNKNOWNERROR, ErrorSeverity.WARN, + ErrorTypes.MUSICSERVICEERROR); + throw new MusicServiceException(ex.getMessage()); + } + return result ? ResultType.SUCCESS : ResultType.FAILURE; } private static void syncQuorum(String keyspace, String table, String primaryKeyValue) throws Exception { @@ -276,7 +259,6 @@ public class MusicCassaCore implements MusicCoreService { selectQuery.addValue(cqlFormattedPrimaryKeyValue); MusicUtil.writeBackToQuorum(selectQuery, primaryKeyName, updateQuery, keyspace, table, cqlFormattedPrimaryKeyValue); - } /** @@ -284,39 +266,45 @@ public class MusicCassaCore implements MusicCoreService { * @param query * @return ResultSet */ - public ResultSet quorumGet(PreparedQueryObject query) { + public ResultSet quorumGet(PreparedQueryObject query) { ResultSet results = null; try { results = MusicDataStoreHandle.getDSHandle().executeQuorumConsistencyGet(query); } catch (MusicServiceException | MusicQueryException e) { - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity - .MAJOR, ErrorTypes.GENERALSERVICEERROR, e); + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR, + ErrorSeverity.MAJOR, ErrorTypes.GENERALSERVICEERROR, e); } return results; - } - /** - * - * @param fullyQualifiedKey lockName - * @return - */ - public String whoseTurnIsIt(String fullyQualifiedKey) { + public String whoseTurnIsIt(String fullyQualifiedKey) { String[] splitString = fullyQualifiedKey.split("\\."); String keyspace = splitString[0]; String table = splitString[1]; String primaryKeyValue = splitString[2]; try { LockObject lockOwner = getLockingServiceHandle().peekLockQueue(keyspace, table, primaryKeyValue); - if (lockOwner==null) { + if (!lockOwner.getIsLockOwner()) { return "No lock holder!"; } - return "$" + fullyQualifiedKey + "$" - + getLockingServiceHandle().peekLockQueue(keyspace, table, primaryKeyValue).lockRef; + return "$" + fullyQualifiedKey + "$" + lockOwner.getLockRef(); } catch (MusicLockingException | MusicServiceException | MusicQueryException e) { - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKINGERROR+fullyQualifiedKey - ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR, e); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), AppMessages.LOCKINGERROR + fullyQualifiedKey, + ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + } + return null; + } + + public List getCurrentLockHolders(String fullyQualifiedKey) { + String[] splitString = fullyQualifiedKey.split("\\."); + String keyspace = splitString[0]; + String table = splitString[1]; + String primaryKeyValue = splitString[2]; + try { + return getLockingServiceHandle().getCurrentLockHolders(keyspace, table, primaryKeyValue); + } catch (MusicLockingException | MusicServiceException | MusicQueryException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKINGERROR+fullyQualifiedKey ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); } return null; } @@ -351,7 +339,7 @@ public class MusicCassaCore implements MusicCoreService { logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to destroy lock reference:" + (end - start) + " ms"); } - public MusicLockState destroyLockRef(String fullyQualifiedKey, String lockReference) throws MusicLockingException { + public MusicLockState destroyLockRef(String fullyQualifiedKey, String lockReference) throws MusicLockingException { long start = System.currentTimeMillis(); String[] splitString = fullyQualifiedKey.split("\\."); String keyspace = splitString[0]; @@ -380,24 +368,25 @@ public class MusicCassaCore implements MusicCoreService { } } - public MusicLockState voluntaryReleaseLock(String fullyQualifiedKey, String lockReference) throws MusicLockingException { + public MusicLockState voluntaryReleaseLock(String fullyQualifiedKey, String lockReference) + throws MusicLockingException { MusicLockState result = null; try { - result = destroyLockRef(fullyQualifiedKey, lockReference); + result = destroyLockRef(fullyQualifiedKey, lockReference); + } catch (Exception ex) { + logger.info(EELFLoggerDelegate.applicationLogger, + "Exception in voluntaryReleaseLock() for " + fullyQualifiedKey + "ref: " + lockReference); + throw new MusicLockingException(ex.getMessage()); } - catch(Exception ex) { - logger.info(EELFLoggerDelegate.applicationLogger,"Exception in voluntaryReleaseLock() for "+ fullyQualifiedKey + "ref: " + lockReference); - throw new MusicLockingException(ex.getMessage()); - } return result; } - public MusicLockState forciblyReleaseLock(String fullyQualifiedKey, String lockReference) throws MusicLockingException { + public MusicLockState forciblyReleaseLock(String fullyQualifiedKey, String lockReference) throws MusicLockingException { String[] splitString = fullyQualifiedKey.split("\\."); String keyspace = splitString[0]; String table = splitString[1]; - //leave a signal that this key could potentially be unsynchronized + //leave a signal that this key could potentially be unsynchronized String syncTable = keyspace+".unsyncedKeys_"+table; PreparedQueryObject queryObject = new PreparedQueryObject(); String values = "(?)"; @@ -505,29 +494,33 @@ public class MusicCassaCore implements MusicCoreService { * @param lockId * @return */ - public ReturnType criticalPut(String keyspace, String table, String primaryKeyValue, - PreparedQueryObject queryObject, String lockId, Condition conditionInfo) { + public ReturnType criticalPut(String keyspace, String table, String primaryKeyValue, + PreparedQueryObject queryObject, String lockId, Condition conditionInfo) { long start = System.currentTimeMillis(); try { - ReturnType result = isTopOfLockStore(keyspace, table, primaryKeyValue, - lockId.substring(lockId.lastIndexOf("$")+1)); - if(result.getResult().equals(ResultType.FAILURE)) - return result;//not top of the lock store q + LockObject lockObject = getLockingServiceHandle().getLockInfo(keyspace, table, primaryKeyValue, + lockId.substring(lockId.lastIndexOf("$") + 1)); - if (conditionInfo != null) - try { - if (conditionInfo.testCondition() == false) - return new ReturnType(ResultType.FAILURE, - "Lock acquired but the condition is not true"); - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger, e); + 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, - "Exception thrown while checking the condition, check its sanctity:\n" - + e.getMessage()); + "Attempting to do write operation, but " + lockId + " is a write lock"); + } + + if (conditionInfo != null) { + try { + if (conditionInfo.testCondition() == false) + return new ReturnType(ResultType.FAILURE, "Lock acquired but the condition is not true"); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e); + return new ReturnType(ResultType.FAILURE, + "Exception thrown while checking the condition, check its sanctity:\n" + e.getMessage()); + } } String query = queryObject.getQuery(); long timeOfWrite = System.currentTimeMillis(); - long lockOrdinal = Long.parseLong(lockId.substring(lockId.lastIndexOf("$")+1)); + long lockOrdinal = Long.parseLong(lockId.substring(lockId.lastIndexOf("$") + 1)); long ts = MusicUtil.v2sTimeStampInMicroseconds(lockOrdinal, timeOfWrite); // TODO: use Statement instead of modifying query if (!queryObject.getQuery().contains("USING TIMESTAMP")) { @@ -562,7 +555,7 @@ public class MusicCassaCore implements MusicCoreService { * * */ - public ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) throws MusicServiceException { + public ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) throws MusicServiceException { // this is mainly for some functions like keyspace creation etc which does not // really need the bells and whistles of Music locking. boolean result = false; @@ -583,12 +576,12 @@ public class MusicCassaCore implements MusicCoreService { * @return ResultSet * @throws MusicServiceException */ - public ResultSet get(PreparedQueryObject queryObject) throws MusicServiceException { + public ResultSet get(PreparedQueryObject queryObject) throws MusicServiceException { ResultSet results = null; try { results = MusicDataStoreHandle.getDSHandle().executeOneConsistencyGet(queryObject); } catch (MusicQueryException | MusicServiceException e) { - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), e); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), e); throw new MusicServiceException(e.getMessage()); } return results; @@ -605,16 +598,17 @@ public class MusicCassaCore implements MusicCoreService { * @param lockId lock ID to check if the resource is free to perform the operation. * @return ResultSet */ - public ResultSet criticalGet(String keyspace, String table, String primaryKeyValue, + public ResultSet criticalGet(String keyspace, String table, String primaryKeyValue, PreparedQueryObject queryObject, String lockId) throws MusicServiceException { ResultSet results = null; try { - ReturnType result = isTopOfLockStore(keyspace, table, primaryKeyValue, - lockId.substring(lockId.lastIndexOf("$")+1)); - if(result.getResult().equals(ResultType.FAILURE)) - return null;//not top of the lock store q - results = MusicDataStoreHandle.getDSHandle().executeQuorumConsistencyGet(queryObject); + LockObject lockObject = getLockingServiceHandle().getLockInfo(keyspace, table, primaryKeyValue, + lockId.substring(lockId.lastIndexOf("$") + 1)); + 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 .WARN, ErrorTypes.MUSICSERVICEERROR, e); @@ -634,56 +628,61 @@ public class MusicCassaCore implements MusicCoreService { * @throws MusicServiceException * @throws MusicQueryException */ - public ReturnType atomicPut(String keyspaceName, String tableName, String primaryKey, - PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException, MusicQueryException, MusicServiceException { + public ReturnType atomicPut(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject, Condition conditionInfo) + throws MusicLockingException, MusicQueryException, MusicServiceException { long start = System.currentTimeMillis(); String fullyQualifiedKey = keyspaceName + "." + tableName + "." + primaryKey; - String lockId = createLockReference(fullyQualifiedKey); + String lockId = createLockReference(fullyQualifiedKey, LockType.WRITE); long lockCreationTime = System.currentTimeMillis(); ReturnType lockAcqResult = null; - logger.info(EELFLoggerDelegate.applicationLogger,"***Acquiring lock for atomicPut() query : " + queryObject.getQuery() + " : "+ primaryKey); - logger.info(EELFLoggerDelegate.applicationLogger,"***Acquiring lock for atomicPut() values: " + queryObject.getValues().toString()); - if(conditionInfo!=null) - logger.info(EELFLoggerDelegate.applicationLogger,"***Acquiring lock for atomicPut() conditions: " + conditionInfo.toString()); - try { - lockAcqResult = acquireLockWithLease(fullyQualifiedKey, lockId,MusicUtil.getDefaultLockLeasePeriod()); - }catch(MusicLockingException ex) { - logger.error(EELFLoggerDelegate.errorLogger,"Exception while acquireLockWithLease() in atomic put for key: "+primaryKey); - logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage()); - throw new MusicServiceException("Cannot perform atomic put for key: "+primaryKey+ " : "+ ex.getMessage()); + logger.info(EELFLoggerDelegate.applicationLogger, + "***Acquiring lock for atomicPut() query : " + queryObject.getQuery() + " : " + primaryKey); + logger.info(EELFLoggerDelegate.applicationLogger, + "***Acquiring lock for atomicPut() values: " + queryObject.getValues().toString()); + if (conditionInfo != null) { + logger.info(EELFLoggerDelegate.applicationLogger, + "***Acquiring lock for atomicPut() conditions: " + conditionInfo.toString()); + } + try { + lockAcqResult = acquireLockWithLease(fullyQualifiedKey, lockId, MusicUtil.getDefaultLockLeasePeriod()); + } catch (MusicLockingException ex) { + logger.error(EELFLoggerDelegate.errorLogger, + "Exception while acquireLockWithLease() in atomic put for key: " + primaryKey); + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage()); + throw new MusicServiceException( + "Cannot perform atomic put for key: " + primaryKey + " : " + ex.getMessage()); } long lockAcqTime = System.currentTimeMillis(); /* - * if (!lockAcqResult.getResult().equals(ResultType.SUCCESS)) { - * logger.info(EELFLoggerDelegate. + * if (!lockAcqResult.getResult().equals(ResultType.SUCCESS)) { logger.info(EELFLoggerDelegate. * applicationLogger,"unable to acquire lock, id " + lockId); * voluntaryReleaseLock(fullyQualifiedKey,lockId); return lockAcqResult; } */ - logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId); + logger.info(EELFLoggerDelegate.applicationLogger, "acquired lock with id " + lockId); String lockRef = lockId.substring(lockId.lastIndexOf("$")); - ReturnType criticalPutResult = null ; - if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) { - criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey, queryObject, lockRef, - conditionInfo); - long criticalPutTime = System.currentTimeMillis(); - long lockDeleteTime = System.currentTimeMillis(); - String timingInfo = "|lock creation time:" + (lockCreationTime - start) + "|lock accquire time:" - + (lockAcqTime - lockCreationTime) + "|critical put time:" + (criticalPutTime - lockAcqTime) - + "|lock delete time:" + (lockDeleteTime - criticalPutTime) + "|"; - criticalPutResult.setTimingInfo(timingInfo); - }else { - logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId); - criticalPutResult = lockAcqResult; - } - try { + ReturnType criticalPutResult = null; + if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) { + criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey, queryObject, lockRef, conditionInfo); + long criticalPutTime = System.currentTimeMillis(); + long lockDeleteTime = System.currentTimeMillis(); + String timingInfo = "|lock creation time:" + (lockCreationTime - start) + "|lock accquire time:" + + (lockAcqTime - lockCreationTime) + "|critical put time:" + (criticalPutTime - lockAcqTime) + + "|lock delete time:" + (lockDeleteTime - criticalPutTime) + "|"; + criticalPutResult.setTimingInfo(timingInfo); + } else { + logger.info(EELFLoggerDelegate.applicationLogger, "unable to acquire lock, id " + lockId); + criticalPutResult = lockAcqResult; + } + try { voluntaryReleaseLock(fullyQualifiedKey, lockId); - } catch (MusicLockingException ex) { - logger.info(EELFLoggerDelegate.applicationLogger,"Exception occured while deleting lock after atomic put for key: "+primaryKey); - criticalPutResult.setMessage(criticalPutResult.getMessage()+ "Lock release failed"); - } + logger.info(EELFLoggerDelegate.applicationLogger, + "Exception occured while deleting lock after atomic put for key: " + primaryKey); + criticalPutResult.setMessage(criticalPutResult.getMessage() + "Lock release failed"); + } return criticalPutResult; } @@ -701,36 +700,38 @@ public class MusicCassaCore implements MusicCoreService { * @throws MusicLockingException * @throws MusicQueryException */ - public ResultSet atomicGet(String keyspaceName, String tableName, String primaryKey, - PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException, MusicQueryException { + public ResultSet atomicGet(String keyspaceName, String tableName, String primaryKey, + PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException, MusicQueryException { String fullyQualifiedKey = keyspaceName + "." + tableName + "." + primaryKey; - String lockId = createLockReference(fullyQualifiedKey); + String lockId = createLockReference(fullyQualifiedKey, LockType.READ); long leasePeriod = MusicUtil.getDefaultLockLeasePeriod(); ReturnType lockAcqResult = null; - ResultSet result =null; - logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring lock for atomicGet() : " + queryObject.getQuery()); + ResultSet result = null; + logger.info(EELFLoggerDelegate.applicationLogger, "Acquiring lock for atomicGet() : " + queryObject.getQuery()); try { - lockAcqResult = acquireLockWithLease(fullyQualifiedKey, lockId,MusicUtil.getDefaultLockLeasePeriod()); - }catch(MusicLockingException ex) { - logger.error(EELFLoggerDelegate.errorLogger,"Exception while acquireLockWithLease() in atomic get for key: "+primaryKey); - logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage()); - throw new MusicServiceException("Cannot perform atomic get for key: "+primaryKey+ " : "+ ex.getMessage()); + lockAcqResult = acquireLockWithLease(fullyQualifiedKey, lockId, MusicUtil.getDefaultLockLeasePeriod()); + } catch (MusicLockingException ex) { + logger.error(EELFLoggerDelegate.errorLogger, + "Exception while acquireLockWithLease() in atomic get for key: " + primaryKey); + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage()); + throw new MusicServiceException( + "Cannot perform atomic get for key: " + primaryKey + " : " + ex.getMessage()); } if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) { - logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId); + logger.info(EELFLoggerDelegate.applicationLogger, "acquired lock with id " + lockId); String lockRef = lockId.substring(lockId.lastIndexOf("$")); result = criticalGet(keyspaceName, tableName, primaryKey, queryObject, lockRef); } else { - logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId); - + logger.info(EELFLoggerDelegate.applicationLogger, "unable to acquire lock, id " + lockId); } try { - voluntaryReleaseLock(fullyQualifiedKey,lockId); - }catch(MusicLockingException ex) { - logger.info(EELFLoggerDelegate.applicationLogger,"Exception occured while deleting lock after atomic put for key: "+primaryKey); + voluntaryReleaseLock(fullyQualifiedKey, lockId); + } catch (MusicLockingException ex) { + logger.info(EELFLoggerDelegate.applicationLogger, + "Exception occured while deleting lock after atomic put for key: " + primaryKey); throw new MusicLockingException(ex.getMessage()); } - + return result; } diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index 4f9c4358..69d59ca3 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -40,7 +40,7 @@ - + diff --git a/src/test/java/org/onap/music/unittests/JsonResponseTest.java b/src/test/java/org/onap/music/unittests/JsonResponseTest.java index 88fddf4e..20ac1562 100644 --- a/src/test/java/org/onap/music/unittests/JsonResponseTest.java +++ b/src/test/java/org/onap/music/unittests/JsonResponseTest.java @@ -26,7 +26,9 @@ package org.onap.music.unittests; import static org.junit.Assert.*; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.junit.Test; import org.onap.music.lockingservice.cassandra.MusicLockState.LockStatus; @@ -125,4 +127,19 @@ public class JsonResponseTest { assertTrue(result.toString() instanceof String); } + + @Test + public void testLockHolders() { + result = new JsonResponse(ResultType.SUCCESS).setLock("lockName").setLockHolder("lockholder1"); + Map lockMap = (Map) result.toMap().get("lock"); + // assure that this is string for backwards compatibility + assertEquals("lockholder1", lockMap.get("lock-holder")); + + List lockholders = new ArrayList<>(); + lockholders.add("lockholder1"); + lockholders.add("lockholder2"); + result.setLockHolder(lockholders); + lockMap = (Map) result.toMap().get("lock"); + assertEquals(lockMap.get("lock-holder"), lockholders); + } } diff --git a/src/test/java/org/onap/music/unittests/MusicDataStoreTest.java b/src/test/java/org/onap/music/unittests/MusicDataStoreTest.java index 6b7dc781..68e6f3dc 100644 --- a/src/test/java/org/onap/music/unittests/MusicDataStoreTest.java +++ b/src/test/java/org/onap/music/unittests/MusicDataStoreTest.java @@ -37,7 +37,6 @@ import org.onap.music.exceptions.MusicServiceException; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.onap.music.authentication.CachingUtil; import org.onap.music.datastore.MusicDataStore; import org.onap.music.datastore.PreparedQueryObject; @@ -84,7 +83,7 @@ public class MusicDataStoreTest { assertEquals(true, result); } - + @Test public void Test2_ExecutePut_eventual_insert() throws MusicServiceException, MusicQueryException { testObject = CassandraCQL.setPreparedInsertQueryObject1(); diff --git a/src/test/java/org/onap/music/unittests/MusicUtilTest.java b/src/test/java/org/onap/music/unittests/MusicUtilTest.java index 04149fc6..21b943f0 100644 --- a/src/test/java/org/onap/music/unittests/MusicUtilTest.java +++ b/src/test/java/org/onap/music/unittests/MusicUtilTest.java @@ -30,14 +30,10 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; -import org.apache.cassandra.exceptions.PreparedQueryNotFoundException; import org.junit.Test; -import org.onap.music.authentication.CachingUtil; import org.onap.music.datastore.PreparedQueryObject; -import org.onap.music.exceptions.MusicServiceException; import org.onap.music.main.MusicUtil; import com.datastax.driver.core.DataType; -import javassist.CodeConverter.ArrayAccessReplacementMethodNames; public class MusicUtilTest { @@ -59,49 +55,11 @@ public class MusicUtilTest { assertEquals(MusicUtil.getAafEndpointUrl(),"url"); } - @Test - public void testGetMyId() { - MusicUtil.setMyId(1); - assertEquals(MusicUtil.getMyId(),1); - } - - @Test - public void testGetAllIds() { - List ids = new ArrayList(); - ids.add("1"); - ids.add("2"); - ids.add("3"); - MusicUtil.setAllIds(ids); - assertEquals(MusicUtil.getAllIds().get(0),"1"); - } - -// @Test -// public void testGetPublicIp() { -// MusicUtil.setPublicIp("10.0.0.1"); -// assertEquals(MusicUtil.getPublicIp(),"10.0.0.1"); -// } - - @Test - public void testGetAllPublicIps() { - List ips = new ArrayList(); - ips.add("10.0.0.1"); - ips.add("10.0.0.2"); - ips.add("10.0.0.3"); - MusicUtil.setAllPublicIps(ips); - assertEquals(MusicUtil.getAllPublicIps().get(1),"10.0.0.2"); - } - @Test public void testGetPropkeys() { assertEquals(MusicUtil.getPropkeys()[2],"debug"); } - @Test - public void testGetMusicRestIp() { - MusicUtil.setMusicRestIp("localhost"); - assertEquals(MusicUtil.getMusicRestIp(),"localhost"); - } - @Test public void testGetMusicPropertiesFilePath() { MusicUtil.setMusicPropertiesFilePath("filepath"); diff --git a/src/test/java/org/onap/music/unittests/TestRestMusicQAPI.java b/src/test/java/org/onap/music/unittests/TestRestMusicQAPI.java index 163f8dda..a9e6e4b6 100644 --- a/src/test/java/org/onap/music/unittests/TestRestMusicQAPI.java +++ b/src/test/java/org/onap/music/unittests/TestRestMusicQAPI.java @@ -52,6 +52,7 @@ import org.mindrot.jbcrypt.BCrypt; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; +import org.onap.music.datastore.MusicDataStore; import org.onap.music.datastore.MusicDataStoreHandle; import org.onap.music.datastore.PreparedQueryObject; import org.onap.music.datastore.jsonobjects.JsonDelete; @@ -66,9 +67,10 @@ import org.onap.music.lockingservice.cassandra.CassaLockStore; import org.onap.music.main.MusicCore; import org.onap.music.main.MusicUtil; //import org.onap.music.main.ResultType; -import org.onap.music.rest.RestMusicAdminAPI; +//import org.onap.music.rest.RestMusicAdminAPI; import org.onap.music.rest.RestMusicDataAPI; import org.onap.music.rest.RestMusicQAPI; +import org.springframework.test.util.ReflectionTestUtils; import org.onap.music.rest.RestMusicLocksAPI; import com.datastax.driver.core.DataType; import com.datastax.driver.core.ResultSet; @@ -84,7 +86,7 @@ import com.sun.jersey.core.util.MultivaluedMapImpl; public class TestRestMusicQAPI { - RestMusicAdminAPI admin = new RestMusicAdminAPI(); + //RestMusicAdminAPI admin = new RestMusicAdminAPI(); RestMusicLocksAPI lock = new RestMusicLocksAPI(); RestMusicQAPI qData = new RestMusicQAPI(); static PreparedQueryObject testObject; @@ -128,8 +130,9 @@ public class TestRestMusicQAPI { @BeforeClass public static void init() throws Exception { try { - MusicDataStoreHandle.mDstoreHandle = CassandraCQL.connectToEmbeddedCassandra(); - MusicCore.mLockHandle = new CassaLockStore(MusicDataStoreHandle.mDstoreHandle); + ReflectionTestUtils.setField(MusicDataStoreHandle.class, "mDstoreHandle", + CassandraCQL.connectToEmbeddedCassandra()); + MusicCore.mLockHandle = new CassaLockStore(MusicDataStoreHandle.getDSHandle()); // System.out.println("before class keysp"); //resp=data.createKeySpace(majorV,minorV,patchV,aid,appName,userId,password,kspObject,keyspaceName); @@ -216,8 +219,9 @@ public class TestRestMusicQAPI { testObject = new PreparedQueryObject(); testObject.appendQueryString("DROP KEYSPACE IF EXISTS admin"); MusicCore.eventualPut(testObject); - if (MusicDataStoreHandle.mDstoreHandle!=null) {} - //MusicDataStoreHandle.mDstoreHandle.close(); + MusicDataStore mds = (MusicDataStore) ReflectionTestUtils.getField(MusicDataStoreHandle.class, "mDstoreHandle"); + if (mds != null) + mds.close(); } @@ -472,7 +476,7 @@ public class TestRestMusicQAPI { // "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, userId, password, System.out.println("#######status is " + response.getStatus()+"table namec="+tableNameC); System.out.println("Entity" + response.getEntity()); - assertEquals(401, response.getStatus()); + assertEquals(400, response.getStatus()); } @@ -514,34 +518,9 @@ public class TestRestMusicQAPI { //assertNotEquals(200,response0.getStatus()); } - // Improper Auth - @Test - public void Test3_createQ1() throws Exception { - JsonTable jsonTable = new JsonTable(); - Map consistencyInfo = new HashMap<>(); - Map fields = new HashMap<>(); - fields.put("uuid", "text"); - fields.put("emp_name", "text"); - fields.put("emp_salary", "varint"); - fields.put("PRIMARY KEY", "(emp_name)"); - consistencyInfo.put("type", "eventual"); - jsonTable.setConsistencyInfo(consistencyInfo); - jsonTable.setKeyspaceName(keyspaceName); - jsonTable.setPartitionKey("emp_name"); - jsonTable.setClusteringKey("uuid"); - jsonTable.setTableName(tableName); - jsonTable.setClusteringOrder("uuid DESC"); - jsonTable.setFields(fields); - //Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); - Response response = qData.createQ(majorV, minorV,patchV, - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, wrongAuthorization, - jsonTable, keyspaceName, tableName); - System.out.println("#######status is " + response.getStatus()); - System.out.println("Entity" + response.getEntity()); - assertEquals(401, response.getStatus()); - } // Improper keyspace + @Ignore @Test public void Test3_createQ2() throws Exception { JsonTable jsonTable = new JsonTable(); @@ -631,47 +610,7 @@ public class TestRestMusicQAPI { assertEquals(200, response.getStatus()); }*/ - // Auth Error - @Test - public void Test4_insertIntoQ3() throws Exception { - JsonInsert jsonInsert = new JsonInsert(); - Map consistencyInfo = new HashMap<>(); - Map values = new HashMap<>(); - values.put("uuid", "cfd66ccc-d857-4e90-b1e5-df98a3d40cd6"); - values.put("emp_name", "test1"); - values.put("emp_salary", 1500); - consistencyInfo.put("type", "eventual"); - jsonInsert.setConsistencyInfo(consistencyInfo); - jsonInsert.setKeyspaceName(keyspaceName); - jsonInsert.setTableName(tableName); - jsonInsert.setValues(values); - //Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); - Response response = qData.insertIntoQ(majorV, minorV,patchV, - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, wrongAuthorization, - jsonInsert, keyspaceName, tableName); - assertEquals(401, response.getStatus()); - } - // Table wrong - @Test - public void Test4_insertIntoQ4() throws Exception { - JsonInsert jsonInsert = new JsonInsert(); - Map consistencyInfo = new HashMap<>(); - Map values = new HashMap<>(); - values.put("uuid", "cfd66ccc-d857-4e90-b1e5-df98a3d40cd6"); - values.put("emp_name", "test1"); - values.put("emp_salary", 1500); - consistencyInfo.put("type", "eventual"); - jsonInsert.setConsistencyInfo(consistencyInfo); - jsonInsert.setKeyspaceName(keyspaceName); - jsonInsert.setTableName(tableName); - jsonInsert.setValues(values); - //Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); - Response response = qData.insertIntoQ(majorV, minorV,patchV, - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, authorization, - jsonInsert, keyspaceName, "wrong"); - assertEquals(401, response.getStatus()); - } /* @Test public void Test5_updateQ() throws Exception { diff --git a/src/test/java/org/onap/music/unittests/TestsUsingCassandra.java b/src/test/java/org/onap/music/unittests/TestsUsingCassandra.java index ef2867d8..e2c65447 100644 --- a/src/test/java/org/onap/music/unittests/TestsUsingCassandra.java +++ b/src/test/java/org/onap/music/unittests/TestsUsingCassandra.java @@ -30,74 +30,77 @@ import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; import org.mindrot.jbcrypt.BCrypt; +import org.onap.music.datastore.MusicDataStore; import org.onap.music.datastore.MusicDataStoreHandle; import org.onap.music.datastore.PreparedQueryObject; import org.onap.music.lockingservice.cassandra.CassaLockStore; import org.onap.music.main.MusicCore; import org.onap.music.main.MusicUtil; - +import org.springframework.test.util.ReflectionTestUtils; import com.datastax.driver.core.DataType; import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.Row; import com.sun.jersey.core.util.Base64; @RunWith(Suite.class) -@SuiteClasses({ TstRestMusicDataAPI.class, TstRestMusicLockAPI.class, TstRestMusicAdminAPI.class, - TstRestMusicConditionalAPI.class, TstCachingUtil.class}) +@SuiteClasses({ TstRestMusicDataAPI.class, TstRestMusicLockAPI.class, + TstRestMusicConditionalAPI.class}) public class TestsUsingCassandra { - static String appName = "TestApp"; - static String userId = "TestUser"; - static String password = "TestPassword"; - static String authData = userId+":"+password; - static String wrongAuthData = userId+":"+"pass"; - static String authorization = new String(Base64.encode(authData.getBytes())); - static String wrongAuthorization = new String(Base64.encode(wrongAuthData.getBytes())); - static boolean isAAF = false; - static UUID uuid = UUID.fromString("abc66ccc-d857-4e90-b1e5-df98a3d40ce6"); - static String keyspaceName = "testcassa"; - static String tableName = "employees"; - static String xLatestVersion = "X-latestVersion"; - static String onboardUUID = null; - static String aid = "abc66ccc-d857-4e90-b1e5-df98a3d40ce6"; - - @BeforeClass - public static void beforeClass() throws Exception { - MusicDataStoreHandle.mDstoreHandle = CassandraCQL.connectToEmbeddedCassandra(); - MusicCore.mLockHandle = new CassaLockStore(MusicDataStoreHandle.mDstoreHandle); - createAdminTable(); - } - - @AfterClass - public static void afterClass() { - PreparedQueryObject testObject = new PreparedQueryObject(); - testObject.appendQueryString("DROP KEYSPACE IF EXISTS admin"); - MusicCore.eventualPut(testObject); - if(MusicDataStoreHandle.mDstoreHandle!=null) - MusicDataStoreHandle.mDstoreHandle.close(); - } - - private static void createAdminTable() throws Exception { - PreparedQueryObject testObject = new PreparedQueryObject(); - testObject.appendQueryString(CassandraCQL.createAdminKeyspace); - MusicCore.eventualPut(testObject); - testObject = new PreparedQueryObject(); - testObject.appendQueryString(CassandraCQL.createAdminTable); - MusicCore.eventualPut(testObject); + static String appName = "TestApp"; + static String userId = "TestUser"; + static String password = "TestPassword"; + static String authData = userId+":"+password; + static String wrongAuthData = userId+":"+"pass"; + static String authorization = new String(Base64.encode(authData.getBytes())); + static String wrongAuthorization = new String(Base64.encode(wrongAuthData.getBytes())); + static boolean isAAF = false; + static UUID uuid = UUID.fromString("abc66ccc-d857-4e90-b1e5-df98a3d40ce6"); + static String keyspaceName = "testcassa"; + static String tableName = "employees"; + static String xLatestVersion = "X-latestVersion"; + static String onboardUUID = null; + static String aid = "abc66ccc-d857-4e90-b1e5-df98a3d40ce6"; + + @BeforeClass + public static void beforeClass() throws Exception { + ReflectionTestUtils.setField(MusicDataStoreHandle.class, "mDstoreHandle", + CassandraCQL.connectToEmbeddedCassandra()); + MusicCore.mLockHandle = new CassaLockStore(MusicDataStoreHandle.getDSHandle()); + createAdminTable(); + } + + @AfterClass + public static void afterClass() { + PreparedQueryObject testObject = new PreparedQueryObject(); + testObject.appendQueryString("DROP KEYSPACE IF EXISTS admin"); + MusicCore.eventualPut(testObject); + MusicDataStore mds = (MusicDataStore) ReflectionTestUtils.getField(MusicDataStoreHandle.class, "mDstoreHandle"); + if (mds != null) + mds.close(); + } + + private static void createAdminTable() throws Exception { + PreparedQueryObject testObject = new PreparedQueryObject(); + testObject.appendQueryString(CassandraCQL.createAdminKeyspace); + MusicCore.eventualPut(testObject); + testObject = new PreparedQueryObject(); + testObject.appendQueryString(CassandraCQL.createAdminTable); + MusicCore.eventualPut(testObject); - testObject = new PreparedQueryObject(); - testObject.appendQueryString( - "INSERT INTO admin.keyspace_master (uuid, keyspace_name, application_name, is_api, " - + "password, username, is_aaf) VALUES (?,?,?,?,?,?,?)"); - testObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); - testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), - keyspaceName)); - testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); - testObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "True")); - testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), BCrypt.hashpw(password, BCrypt.gensalt()))); - testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); - testObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF)); - MusicCore.eventualPut(testObject); + testObject = new PreparedQueryObject(); + testObject.appendQueryString( + "INSERT INTO admin.keyspace_master (uuid, keyspace_name, application_name, is_api, " + + "password, username, is_aaf) VALUES (?,?,?,?,?,?,?)"); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), + keyspaceName)); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "True")); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), BCrypt.hashpw(password, BCrypt.gensalt()))); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF)); + MusicCore.eventualPut(testObject); testObject = new PreparedQueryObject(); testObject.appendQueryString( diff --git a/src/test/java/org/onap/music/unittests/TstCachingUtil.java b/src/test/java/org/onap/music/unittests/TstCachingUtil.java deleted file mode 100644 index ea47b7c1..00000000 --- a/src/test/java/org/onap/music/unittests/TstCachingUtil.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * ============LICENSE_START========================================== org.onap.music - * =================================================================== Copyright (c) 2017 AT&T - * Intellectual Property =================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - * - * ============LICENSE_END============================================= - * ==================================================================== - */ - -package org.onap.music.unittests; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import javax.ws.rs.core.Response; - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mindrot.jbcrypt.BCrypt; -import org.mockito.junit.MockitoJUnitRunner; -import org.onap.music.authentication.CachingUtil; -import org.onap.music.datastore.MusicDataStoreHandle; -import org.onap.music.datastore.PreparedQueryObject; -import org.onap.music.datastore.jsonobjects.JsonInsert; -import org.onap.music.datastore.jsonobjects.JsonLeasedLock; -import org.onap.music.datastore.jsonobjects.JsonTable; -import org.onap.music.exceptions.MusicServiceException; -import org.onap.music.lockingservice.cassandra.CassaLockStore; -import org.onap.music.main.MusicCore; -import org.onap.music.main.MusicUtil; -import org.onap.music.rest.RestMusicDataAPI; -import org.onap.music.rest.RestMusicLocksAPI; -import com.datastax.driver.core.DataType; -import com.datastax.driver.core.ResultSet; -import com.datastax.driver.core.Row; -import com.sun.jersey.core.util.Base64; - -@RunWith(MockitoJUnitRunner.class) -public class TstCachingUtil { - - RestMusicLocksAPI lock = new RestMusicLocksAPI(); - RestMusicDataAPI data = new RestMusicDataAPI(); - static PreparedQueryObject testObject; - - static String appName = TestsUsingCassandra.appName; - static String userId = TestsUsingCassandra.userId; - static String password = TestsUsingCassandra.password; - static String authData = TestsUsingCassandra.authData; - static String authorization = TestsUsingCassandra.authorization; - static boolean isAAF = TestsUsingCassandra.isAAF; - static UUID uuid = TestsUsingCassandra.uuid; - static String keyspaceName = TestsUsingCassandra.keyspaceName; - static String tableName = TestsUsingCassandra.tableName; - static String onboardUUID = null; - - @BeforeClass - public static void init() throws Exception { - System.out.println("Testing CachingUtil class"); - try { - - } catch (Exception e) { - e.printStackTrace(); - throw new Exception("Unable to initialize before TestRestMusicData test class. " + e.getMessage()); - } - } - - @After - public void afterEachTest( ) throws MusicServiceException { - - } - - @AfterClass - public static void tearDownAfterClass() throws Exception { - testObject = new PreparedQueryObject(); - testObject.appendQueryString("DROP KEYSPACE IF EXISTS " + keyspaceName); - MusicCore.eventualPut(testObject); - } - - @Test - public void test_verifyOnboard() throws Exception { - System.out.println("Testing onboarding of app"); - CachingUtil cache = new CachingUtil(); - cache.initializeAafCache(); - Map authMap = CachingUtil.verifyOnboarding(appName, userId, password); - assertEquals(0, authMap.size()); - } - - @Test - public void test_authenticateAIDUser() throws Exception { - System.out.println("Testing authentication of AID user"); - createKeyspace(); - CachingUtil cache = new CachingUtil(); - cache.initializeAafCache(); - Map authMap = CachingUtil.authenticateAIDUser(appName, - userId, password, keyspaceName); - System.out.println("authMap is: " + authMap); - assertEquals(0, authMap.size()); - } - - @Test - public void test_getAppName() throws MusicServiceException { - System.out.println("Testing getAppName"); - CachingUtil cache = new CachingUtil(); - cache.initializeAafCache(); - assertEquals(appName, CachingUtil.getAppName(keyspaceName)); - } - - @Test - public void test_getUUIDFromCache() throws MusicServiceException { - System.out.println("Testing getUUID"); - CachingUtil cache = new CachingUtil(); - cache.initializeAafCache(); - assertEquals(uuid.toString(), CachingUtil.getUuidFromMusicCache(keyspaceName)); - } - - @Test - public void test_isAAFApplcation() throws MusicServiceException { - System.out.println("Testing to see if cache gets correct isAAF info"); - CachingUtil cache = new CachingUtil(); - cache.initializeAafCache(); - assertEquals(isAAF, Boolean.valueOf(CachingUtil.isAAFApplication(appName))); - } - - private static void createKeyspace() throws Exception { - //shouldn't really be doing this here, but create keyspace is currently turned off - PreparedQueryObject query = new PreparedQueryObject(); - query.appendQueryString(CassandraCQL.createKeySpace); - MusicCore.eventualPut(query); - - boolean isAAF = false; - String hashedpwd = BCrypt.hashpw(password, BCrypt.gensalt()); - query = new PreparedQueryObject(); - query.appendQueryString( - "INSERT into admin.keyspace_master (uuid, keyspace_name, application_name, is_api, " - + "password, username, is_aaf) values (?,?,?,?,?,?,?)"); - query.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); - query.addValue(MusicUtil.convertToActualDataType(DataType.text(), keyspaceName)); - query.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); - query.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "True")); - query.addValue(MusicUtil.convertToActualDataType(DataType.text(), hashedpwd)); - query.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); - query.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF)); - CachingUtil.updateMusicCache(keyspaceName, appName); - CachingUtil.updateMusicValidateCache(appName, userId, hashedpwd); - MusicCore.eventualPut(query); - } - -} diff --git a/src/test/java/org/onap/music/unittests/TstRestMusicAdminAPI.java b/src/test/java/org/onap/music/unittests/TstRestMusicAdminAPI.java deleted file mode 100644 index e6bc3107..00000000 --- a/src/test/java/org/onap/music/unittests/TstRestMusicAdminAPI.java +++ /dev/null @@ -1,464 +0,0 @@ -/* - * ============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.unittests; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.Map; -import java.util.UUID; - -import javax.ws.rs.core.Response; - - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Ignore; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.internal.util.reflection.FieldSetter; -import org.onap.music.authentication.MusicAAFAuthentication; -import org.onap.music.datastore.PreparedQueryObject; -import org.onap.music.datastore.jsonobjects.JsonOnboard; -import org.onap.music.datastore.jsonobjects.MusicResponse; -import org.onap.music.main.MusicCore; -import org.onap.music.rest.RestMusicAdminAPI; -import com.sun.jersey.core.util.Base64; - -public class TstRestMusicAdminAPI { - - RestMusicAdminAPI admin = new RestMusicAdminAPI(); - static PreparedQueryObject testObject; - - @Mock - MusicAAFAuthentication authMock; - - static String appName = "TestApp"; - static String userId = "TestUser"; - static String password = "TestPassword"; - static String adminName = "username"; - static String adminPassword = "password"; - static String adminAuthData = adminName +":"+adminPassword; - static String wrongAdminAuthData = adminName+"123"+":"+adminPassword; - static String authData = userId+":"+password; - static String wrongAuthData = userId+":"+"pass"; - static String authorization = new String(Base64.encode(authData.getBytes())); - static String wrongAuthorization = new String(Base64.encode(wrongAuthData.getBytes())); - static String adminAuthorization = new String(Base64.encode(adminAuthData.getBytes())); - static String wrongAdminAuthorization = new String(Base64.encode(wrongAdminAuthData.getBytes())); - - static boolean isAAF = false; - static UUID uuid = UUID.fromString("abc66ccc-d857-4e90-b1e5-df98a3d40ce6"); - static String keyspaceName = "testCassa"; - static String tableName = "employees"; - static String tableNameConditional = "Conductor"; - static String xLatestVersion = "X-latestVersion"; - static String onboardUUID = TestsUsingCassandra.onboardUUID; - static String lockId = null; - static String lockName = "testCassa.employees.sample3"; - - @BeforeClass - public static void init() throws Exception { - System.out.println("Testing RestMusicAdmin class"); - //PowerMockito.mockStatic(MusicAuthentication.class); - try { - //MusicDataStoreHandle.mDstoreHandle = CassandraCQL.connectToEmbeddedCassandra(); - } catch (Exception e) { - e.printStackTrace(); - throw new Exception("Unable to initialize before TestRestMusicData test class. " + e.getMessage()); - } - } - - @Before - public void beforeEach() throws NoSuchFieldException { - authenticateAdminTrue(); - } - - @After - public void afterEach() { - testObject = new PreparedQueryObject(); - testObject.appendQueryString("DELETE * FROM admin.keyspace_master;"); - MusicCore.eventualPut(testObject); - } - - @AfterClass - public static void tearDownAfterClass() throws Exception { - testObject = new PreparedQueryObject(); - testObject.appendQueryString("DROP KEYSPACE IF EXISTS " + keyspaceName); - MusicCore.eventualPut(testObject); - } - - @Ignore - @Test - public void test6_onboard() throws Exception { - System.out.println("Testing application onboarding"); - - JsonOnboard jsonOnboard = new JsonOnboard(); - jsonOnboard.setAppname("TestApp2"); - jsonOnboard.setIsAAF("false"); jsonOnboard.setUserId("TestUser2"); - jsonOnboard.setKeyspace_name(keyspaceName); - jsonOnboard.setPassword("TestPassword2"); - - Response response = admin.onboardAppWithMusic(jsonOnboard,adminAuthorization); - - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(200, response.getStatus()); - } - - @Test - public void test6_onboard_wrongCredentials() throws Exception { - System.out.println("Testing application onboarding wrong credentials"); - JsonOnboard jsonOnboard = new JsonOnboard(); - jsonOnboard.setAppname("TestApp2"); - jsonOnboard.setIsAAF("false"); jsonOnboard.setUserId("TestUser2"); - jsonOnboard.setKeyspace_name(keyspaceName); - jsonOnboard.setPassword("TestPassword2"); - - Response response = admin.onboardAppWithMusic(jsonOnboard,wrongAdminAuthorization); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(401, response.getStatus()); - } - - @Ignore - @Test - public void test6_onboard_duplicate() throws Exception { - System.out.println("Testing a duplicate onboarding call"); - - JsonOnboard jsonOnboard = new JsonOnboard(); - jsonOnboard.setAppname("TestApp2"); - jsonOnboard.setIsAAF("false"); - jsonOnboard.setKeyspace_name(keyspaceName); - jsonOnboard.setUserId("TestUser2"); - jsonOnboard.setPassword("TestPassword2"); - Response response = admin.onboardAppWithMusic(jsonOnboard,adminAuthorization); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(200, response.getStatus()); - } - - // Missing appname - @Test - public void test6_onboard_noAppName() throws Exception { - System.out.println("Testing onboard missing app name"); - - JsonOnboard jsonOnboard = new JsonOnboard(); - jsonOnboard.setIsAAF("false"); - jsonOnboard.setKeyspace_name(keyspaceName); - jsonOnboard.setUserId("TestUser2"); - jsonOnboard.setPassword("TestPassword2"); - Response response = admin.onboardAppWithMusic(jsonOnboard,adminAuthorization); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - - assertEquals(400, response.getStatus()); - } - - - @Test - public void test7_onboardSearch_notOnboarded() throws Exception { - System.out.println("Testing application onboarding search for app that isn't onboarded"); - - JsonOnboard jsonOnboard = new JsonOnboard(); - jsonOnboard.setAppname("TestApp2"); - jsonOnboard.setIsAAF("false"); - jsonOnboard.setAid(onboardUUID); - Response response = admin.getOnboardedInfoSearch(jsonOnboard,adminAuthorization); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - //Application is not onboarded - assertEquals(400, response.getStatus()); - } - - @Ignore - @Test - public void test7_onboardSearch() throws Exception { - System.out.println("Testing application onboarding search no matching app"); - onboardApp(); - - JsonOnboard jsonOnboard = new JsonOnboard(); - jsonOnboard.setAppname("TestApp2"); - jsonOnboard.setIsAAF("false"); - jsonOnboard.setAid(onboardUUID); - - Response response = admin.getOnboardedInfoSearch(jsonOnboard,adminAuthorization); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - - assertEquals(200, response.getStatus()); - } - - @Test - public void test7_onboardSearch_wrongCredentials() throws Exception { - System.out.println("Testing application onboarding search w/ wrong credentials"); - - JsonOnboard jsonOnboard = new JsonOnboard(); - jsonOnboard.setAppname("TestApp2"); - jsonOnboard.setIsAAF("false"); - jsonOnboard.setAid(onboardUUID); - Response response = admin.getOnboardedInfoSearch(jsonOnboard,wrongAdminAuthorization); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - - assertEquals(401, response.getStatus()); - } - - // Missing appname - @Test - public void test7_onboardSearch_noAppName() throws Exception { - System.out.println("Testing application onboarding search w/o appname"); - onboardApp(); - - JsonOnboard jsonOnboard = new JsonOnboard(); - jsonOnboard.setIsAAF("false"); - jsonOnboard.setAid(onboardUUID); - Response response = admin.getOnboardedInfoSearch(jsonOnboard,adminAuthorization); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - - assertEquals(200, response.getStatus()); - } - - @Ignore - @Test - public void test7_onboardSearch_empty() throws Exception { - System.out.println("Testing onboard search no app information"); - - JsonOnboard jsonOnboard = new JsonOnboard(); - Response response = admin.getOnboardedInfoSearch(jsonOnboard,adminAuthorization); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - - assertEquals(400, response.getStatus()); - } - - @Ignore - @Test - public void test8_onboardUpdate() throws Exception { - System.out.println("Testing application onboarding update"); - onboardApp(); - - JsonOnboard jsonOnboard = new JsonOnboard(); - jsonOnboard.setIsAAF("false"); - jsonOnboard.setUserId("TestUser3"); - jsonOnboard.setPassword("TestPassword3"); - jsonOnboard.setAid(onboardUUID); - Response response = admin.updateOnboardApp(jsonOnboard,adminAuthorization); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - - assertEquals(200, response.getStatus()); - } - - @Ignore //not working correctly - @Test - public void test8_onboardUpdate_withAppName() throws Exception { - System.out.println("Testing application onboarding update w appname"); - onboardApp(); - - JsonOnboard jsonOnboard = new JsonOnboard(); - jsonOnboard.setIsAAF("false"); - jsonOnboard.setUserId("TestUser3"); - jsonOnboard.setPassword("TestPassword3"); - jsonOnboard.setAppname("TestApp2"); - jsonOnboard.setAid(onboardUUID); - Response response = admin.updateOnboardApp(jsonOnboard,adminAuthorization); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - - assertEquals(200, response.getStatus()); - } - - @Test - public void test8_onboardUpdate_noUUID() throws Exception { - System.out.println("Testing application onboarding update null uuid"); - onboardApp(); - - JsonOnboard jsonOnboard = new JsonOnboard(); - jsonOnboard.setIsAAF("false"); - jsonOnboard.setUserId("TestUser3"); - jsonOnboard.setPassword("TestPassword3"); - jsonOnboard.setAid(null); - Response response = admin.updateOnboardApp(jsonOnboard,adminAuthorization); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - - assertEquals(400, response.getStatus()); - } - - @Test - public void test8_onboardUpdate_wrongCredentialsNoAAF() throws Exception { - System.out.println("Testing update application onboarding search w/ wrong credentials"); - JsonOnboard jsonOnboard = new JsonOnboard(); - jsonOnboard.setIsAAF("false"); - jsonOnboard.setUserId("TestUser3"); - jsonOnboard.setPassword("TestPassword3"); - jsonOnboard.setAid(onboardUUID); - Response response = admin.updateOnboardApp(jsonOnboard,wrongAdminAuthorization); - - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(401, response.getStatus()); - } - - // All null - @Test - public void test8_onboardUpdate_noAppInfo() throws Exception { - System.out.println("Testing update application onboarding update no app information"); - onboardApp(); - - JsonOnboard jsonOnboard = new JsonOnboard(); - jsonOnboard.setAid(onboardUUID); - Response response = admin.updateOnboardApp(jsonOnboard,adminAuthorization); - - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(400, response.getStatus()); - } - - @Test - @Ignore - public void test9_onboardDelete() throws Exception { - System.out.println("Testing update application onboarding delete"); - onboardApp(); - - JsonOnboard jsonOnboard = new JsonOnboard(); - jsonOnboard.setAppname("TestApp2"); - jsonOnboard.setAid(onboardUUID); - Response response = admin.deleteOnboardApp(jsonOnboard,adminAuthorization); - - //only 1 app matches keyspace - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(200, response.getStatus()); - } - - @Ignore //not working as expected - @Test - public void test9_onboardDelete_noAID() throws Exception { - System.out.println("Testing update application onboarding delete no AID"); - onboardApp(); - - JsonOnboard jsonOnboard = new JsonOnboard(); - jsonOnboard.setAppname("TestApp2"); - jsonOnboard.setAid(null); - Response response = admin.deleteOnboardApp(jsonOnboard,adminAuthorization); - - //only 1 app matches name - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(200, response.getStatus()); - } - - @Ignore - @Test - public void test9_onboardDelete_noAIDManyMatch() throws Exception { - System.out.println("Testing update application onboarding delete no AID many apps in namespace"); - onboardApp(); - onboardApp(); - - JsonOnboard jsonOnboard = new JsonOnboard(); - jsonOnboard.setAppname("TestApp2"); - jsonOnboard.setAid(null); - Response response = admin.deleteOnboardApp(jsonOnboard,adminAuthorization); - - //multiple apps matches name - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(400, response.getStatus()); - } - - @Ignore - @Test - public void test9_onboardDelete_noAID_noApp() throws Exception { - System.out.println("Testing update application onboarding delete no AID, app not onboarded"); - - JsonOnboard jsonOnboard = new JsonOnboard(); - jsonOnboard.setAppname("TestApp2"); - jsonOnboard.setAid(null); - Response response = admin.deleteOnboardApp(jsonOnboard,adminAuthorization); - - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(400, response.getStatus()); - } - - @Test - public void test9_onboardDelete_noAppToDelete() throws Exception { - System.out.println("Testing update application onboarding delete no app information"); - onboardApp(); - - JsonOnboard jsonOnboard = new JsonOnboard(); - jsonOnboard.setAppname(null); - jsonOnboard.setAid(null); - Response response = admin.deleteOnboardApp(jsonOnboard,adminAuthorization); - - //only 1 app matches keyspace - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(400, response.getStatus()); - } - - @Test - public void test9_onboardDelete_wrongCredentials() throws Exception { - System.out.println("Testing onboard delete with wrong credentials"); - JsonOnboard jsonOnboard = new JsonOnboard(); - jsonOnboard.setAppname("TestApp2"); - jsonOnboard.setAid(onboardUUID); - Response response = admin.deleteOnboardApp(jsonOnboard,wrongAdminAuthorization); - - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(401, response.getStatus()); - } - - @Ignore - @Test - public void test10_delete() throws Exception { - System.out.println("Testing GUI delete call"); - onboardApp(); - MusicResponse response = admin.delete(adminAuthorization, onboardUUID); - assertEquals(200, response.getStatus()); - //assertTrue(admin.delete(adminAuthorization, onboardUUID)); - } - - @Test - public void test11_getAll() { - System.out.println("Testing GUI getall call"); - - System.out.println("admin.getall(adminAuthorization)"); - } - - /** - * Inject our mocked class and accept admin credentials - * @throws NoSuchFieldException - */ - public void authenticateAdminTrue() throws NoSuchFieldException { - authMock = Mockito.mock(MusicAAFAuthentication.class); - FieldSetter.setField(admin, admin.getClass().getDeclaredField("authenticator"), authMock); - - Mockito.when(authMock.authenticateAdmin(Mockito.matches(adminAuthorization))).thenReturn(true); - } - - /** - * onboard the application and store generate uuid into {@link onboardUUID} - * @param onboard - * @throws Exception - */ - public void onboardApp() throws Exception { - JsonOnboard jsonOnboard = new JsonOnboard(); - jsonOnboard.setAppname("TestApp2"); - jsonOnboard.setIsAAF("false"); - jsonOnboard.setUserId("TestUser2"); - jsonOnboard.setPassword("TestPassword2"); - - Response response = admin.onboardAppWithMusic(jsonOnboard,adminAuthorization); - Map respMap = (Map) response.getEntity(); - onboardUUID = respMap.get("Generated AID"); - } - -} \ No newline at end of file diff --git a/src/test/java/org/onap/music/unittests/TstRestMusicConditionalAPI.java b/src/test/java/org/onap/music/unittests/TstRestMusicConditionalAPI.java index 3adab912..7021178e 100644 --- a/src/test/java/org/onap/music/unittests/TstRestMusicConditionalAPI.java +++ b/src/test/java/org/onap/music/unittests/TstRestMusicConditionalAPI.java @@ -39,7 +39,6 @@ import org.mindrot.jbcrypt.BCrypt; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; -import org.onap.music.authentication.CachingUtil; import org.onap.music.conductor.conditionals.JsonConditional; import org.onap.music.conductor.conditionals.RestMusicConditionalAPI; import org.onap.music.datastore.MusicDataStoreHandle; @@ -293,8 +292,6 @@ public class TstRestMusicConditionalAPI { query.addValue(MusicUtil.convertToActualDataType(DataType.text(), hashedpwd)); query.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); query.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF)); - CachingUtil.updateMusicCache(keyspaceName, appName); - CachingUtil.updateMusicValidateCache(appName, userId, hashedpwd); MusicCore.eventualPut(query); } diff --git a/src/test/java/org/onap/music/unittests/TstRestMusicDataAPI.java b/src/test/java/org/onap/music/unittests/TstRestMusicDataAPI.java index 18692915..67a68f6e 100644 --- a/src/test/java/org/onap/music/unittests/TstRestMusicDataAPI.java +++ b/src/test/java/org/onap/music/unittests/TstRestMusicDataAPI.java @@ -44,7 +44,6 @@ import org.mindrot.jbcrypt.BCrypt; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; -import org.onap.music.authentication.CachingUtil; import org.onap.music.datastore.MusicDataStoreHandle; import org.onap.music.datastore.PreparedQueryObject; import org.onap.music.datastore.jsonobjects.JsonDelete; @@ -264,51 +263,6 @@ public class TstRestMusicDataAPI { assertEquals("Table " + keyspaceName + "." + tableNameDup + " already exists", respMap.get("error")); } - // Improper Auth - @Test - public void test3_createTable1() throws Exception { - System.out.println("Testing create table w/ improper authentication"); - JsonTable jsonTable = new JsonTable(); - Map consistencyInfo = new HashMap<>(); - Map fields = new HashMap<>(); - fields.put("uuid", "text"); - fields.put("emp_name", "text"); - fields.put("emp_salary", "varint"); - fields.put("PRIMARY KEY", "(emp_name)"); - consistencyInfo.put("type", "eventual"); - jsonTable.setConsistencyInfo(consistencyInfo); - jsonTable.setKeyspaceName(keyspaceName); - jsonTable.setPrimaryKey("emp_name"); - jsonTable.setTableName(tableName); - jsonTable.setFields(fields); - Response response = data.createTable("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, - wrongAuthorization, jsonTable, keyspaceName, tableName); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(401, response.getStatus()); - } - - // Improper keyspace - @Test - public void test3_createTable3() throws Exception { - System.out.println("Testing create table for wrong keyspace"); - JsonTable jsonTable = new JsonTable(); - Map consistencyInfo = new HashMap<>(); - Map fields = new HashMap<>(); - fields.put("uuid", "text"); - fields.put("emp_name", "text"); - fields.put("emp_salary", "varint"); - fields.put("PRIMARY KEY", "(emp_name)"); - consistencyInfo.put("type", "eventual"); - jsonTable.setConsistencyInfo(consistencyInfo); - jsonTable.setKeyspaceName(keyspaceName); - jsonTable.setPrimaryKey("emp_name"); - jsonTable.setTableName(tableName); - jsonTable.setFields(fields); - Response response = data.createTable("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, - authorization, jsonTable, "wrong", tableName); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(401, response.getStatus()); - } // Improper parenthesis in key field @Test @@ -479,38 +433,6 @@ public class TstRestMusicDataAPI { assertEquals(200, response.getStatus()); } - - // good clustering key, need to pass queryparameter - @Test - public void test3_createTableIndex_badAuth() throws Exception { - System.out.println("Testing index in create table w/ wrong authorization"); - String tableNameC = "testTableCinx"; - JsonTable jsonTable = new JsonTable(); - Map consistencyInfo = new HashMap<>(); - Map fields = new HashMap<>(); - fields.put("uuid", "text"); - fields.put("emp_name", "text"); - fields.put("emp_salary", "varint"); - fields.put("PRIMARY KEY", "((emp_name),emp_salary)"); - consistencyInfo.put("type", "eventual"); - jsonTable.setConsistencyInfo(consistencyInfo); - jsonTable.setKeyspaceName(keyspaceName); - jsonTable.setTableName(tableNameC); - jsonTable.setClusteringOrder("emp_salary ASC"); - jsonTable.setFields(fields); - Response response = data.createTable("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, - authorization, jsonTable, keyspaceName, tableNameC); - // if 200 print to log otherwise fail assertEquals(200, response.getStatus()); - // info.setQueryParameters("index_name=inx_uuid"); - Map queryParametersMap = new HashMap(); - - queryParametersMap.put("index_name", "inxuuid"); - response = data.createIndex("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, - wrongAuthorization, keyspaceName, tableNameC, "uuid", info); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - - assertEquals(401, response.getStatus()); - } // create index without table name @Test @@ -654,29 +576,6 @@ public class TstRestMusicDataAPI { assertEquals(200, response.getStatus()); } - // Auth Error - @Test - public void test4_insertIntoTable3() throws Exception { - System.out.println("Testing insert into table with bad credentials"); - createTable(); - JsonInsert jsonInsert = new JsonInsert(); - Map consistencyInfo = new HashMap<>(); - Map values = new HashMap<>(); - values.put("uuid", "cfd66ccc-d857-4e90-b1e5-df98a3d40cd6"); - values.put("emp_name", "test1"); - values.put("emp_salary", 1500); - consistencyInfo.put("type", "eventual"); - jsonInsert.setConsistencyInfo(consistencyInfo); - jsonInsert.setKeyspaceName(keyspaceName); - jsonInsert.setTableName(tableName); - jsonInsert.setValues(values); - Response response = data.insertIntoTable("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, - wrongAuthorization, jsonInsert, keyspaceName, tableName); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - - assertEquals(401, response.getStatus()); - } - // Table wrong @Test public void test4_insertIntoTable4() throws Exception { @@ -748,28 +647,6 @@ public class TstRestMusicDataAPI { assertEquals(200, response.getStatus()); } - @Test - public void test5_updateTable_wrongAuth() throws Exception { - System.out.println("Testing update table w/ wrong credentials"); - createTable(); - - JsonUpdate jsonUpdate = new JsonUpdate(); - Map consistencyInfo = new HashMap<>(); - Map values = new HashMap<>(); - values.put("emp_salary", 2500); - consistencyInfo.put("type", "atomic"); - jsonUpdate.setConsistencyInfo(consistencyInfo); - jsonUpdate.setKeyspaceName(keyspaceName); - jsonUpdate.setTableName(tableName); - jsonUpdate.setValues(values); - Response response = data.updateTable("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, - wrongAuthorization, jsonUpdate, keyspaceName, tableName, info); - - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - - assertEquals(401, response.getStatus()); - } - @Test public void test5_updateTable_tableDNE() throws Exception { System.out.println("Testing update table that does not exist"); @@ -843,62 +720,6 @@ public class TstRestMusicDataAPI { assertEquals(200, response.getStatus()); } - @Ignore - @Test - public void test5_updateTableAuthException1() throws Exception { - System.out.println("Testing update table authentication error"); - createTable(); - JsonUpdate jsonUpdate = new JsonUpdate(); - Map consistencyInfo = new HashMap<>(); - MultivaluedMap row = new MultivaluedMapImpl(); - Map values = new HashMap<>(); - row.add("emp_name", "testname"); - values.put("emp_salary", 2500); - consistencyInfo.put("type", "atomic"); - jsonUpdate.setConsistencyInfo(consistencyInfo); - jsonUpdate.setKeyspaceName(keyspaceName); - jsonUpdate.setTableName(tableName); - jsonUpdate.setValues(values); - - Mockito.when(info.getQueryParameters()).thenReturn(row); - String authDatax = ":"; - String authorizationx = new String(Base64.encode(authDatax.getBytes())); - Response response = data.updateTable("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, - authorizationx, jsonUpdate, keyspaceName, tableName, info); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - - assertEquals(401, response.getStatus()); - } - - @Ignore - @Test - public void test5_updateTableAuthEmpty() throws Exception { - System.out.println("Testing update table without authentication"); - createTable(); - - JsonUpdate jsonUpdate = new JsonUpdate(); - Map consistencyInfo = new HashMap<>(); - MultivaluedMap row = new MultivaluedMapImpl(); - Map values = new HashMap<>(); - row.add("emp_name", "testname"); - values.put("emp_salary", 2500); - consistencyInfo.put("type", "atomic"); - jsonUpdate.setConsistencyInfo(consistencyInfo); - jsonUpdate.setKeyspaceName(keyspaceName); - jsonUpdate.setTableName(tableName); - jsonUpdate.setValues(values); - - Mockito.when(info.getQueryParameters()).thenReturn(row); - String authDatax = ":" + password; - String authorizationx = new String(Base64.encode(authDatax.getBytes())); - String appNamex = "xx"; - Response response = data.updateTable("1", "1", "1", "", appNamex, authorizationx, jsonUpdate, keyspaceName, - tableName, info); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - - assertEquals(401, response.getStatus()); - } - @Test public void test6_critical_selectAtomic() throws Exception { System.out.println("Testing critical select atomic"); @@ -941,21 +762,6 @@ public class TstRestMusicDataAPI { assertEquals(400, response.getStatus()); } - @Test - public void test6_critical_select_wrongAuth() throws Exception { - System.out.println("Testing critical select w/ wrong authentication"); - createAndInsertIntoTable(); - JsonInsert jsonInsert = new JsonInsert(); - Map consistencyInfo = new HashMap<>(); - consistencyInfo.put("type", "atomic"); - jsonInsert.setConsistencyInfo(consistencyInfo); - Response response = data.selectCritical("1", "1", "1","abc66ccc-d857-4e90-b1e5-df98a3d40ce6", - appName, wrongAuthorization, jsonInsert, keyspaceName, tableName,info); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - - assertEquals(401, response.getStatus()); - } - @Test public void test6_critical_select_nulltable() throws Exception { System.out.println("Testing critical select w/ null tablename"); @@ -993,21 +799,6 @@ public class TstRestMusicDataAPI { assertEquals(BigInteger.valueOf(500), row0.get("emp_salary")); } - @Test - public void test6_select_wrongAuth() throws Exception { - System.out.println("Testing select w/ wrong authentication"); - createAndInsertIntoTable(); - JsonSelect jsonSelect = new JsonSelect(); - Map consistencyInfo = new HashMap<>(); - consistencyInfo.put("type", "atomic"); - jsonSelect.setConsistencyInfo(consistencyInfo); - Response response = data.select("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", - appName, wrongAuthorization, keyspaceName, tableName, info); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - - assertEquals(401, response.getStatus()); - } - @Test public void test6_select_nullTablename() throws Exception { System.out.println("Testing select w/ null tablename"); @@ -1040,20 +831,6 @@ public class TstRestMusicDataAPI { assertEquals(200, response.getStatus()); } - @Test - public void test6_deleteFromTable_wrongAuth() throws Exception { - System.out.println("Testing delete from table"); - createAndInsertIntoTable(); - JsonDelete jsonDelete = new JsonDelete(); - Map consistencyInfo = new HashMap<>(); - consistencyInfo.put("type", "atomic"); - jsonDelete.setConsistencyInfo(consistencyInfo); - Response response = data.deleteFromTable("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, - wrongAuthorization, jsonDelete, keyspaceName, tableName, info); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(401, response.getStatus()); - } - @Test public void test6_deleteFromTable_missingTablename() throws Exception { System.out.println("Testing delete from table w/ null tablename"); @@ -1119,21 +896,6 @@ public class TstRestMusicDataAPI { assertEquals(200, response.getStatus()); } - @Test - public void test7_dropTable_wrongAuth() throws Exception { - System.out.println("Testing drop table w/ wrong auth"); - createTable(); - JsonTable jsonTable = new JsonTable(); - Map consistencyInfo = new HashMap<>(); - consistencyInfo.put("type", "atomic"); - jsonTable.setConsistencyInfo(consistencyInfo); - Response response = data.dropTable("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, - wrongAuthorization, keyspaceName, tableName); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - - assertEquals(401, response.getStatus()); - } - @Test public void test7_dropTable_nullTablename() throws Exception { System.out.println("Testing drop table w/ null tablename"); @@ -1189,8 +951,6 @@ public class TstRestMusicDataAPI { query.addValue(MusicUtil.convertToActualDataType(DataType.text(), hashedpwd)); query.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); query.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF)); - CachingUtil.updateMusicCache(keyspaceName, appName); - CachingUtil.updateMusicValidateCache(appName, userId, hashedpwd); MusicCore.eventualPut(query); } diff --git a/src/test/java/org/onap/music/unittests/TstRestMusicLockAPI.java b/src/test/java/org/onap/music/unittests/TstRestMusicLockAPI.java index 956a266d..86746472 100644 --- a/src/test/java/org/onap/music/unittests/TstRestMusicLockAPI.java +++ b/src/test/java/org/onap/music/unittests/TstRestMusicLockAPI.java @@ -29,9 +29,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; - +import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; - +import javax.ws.rs.core.UriInfo; import org.junit.After; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -39,15 +39,18 @@ import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mindrot.jbcrypt.BCrypt; +import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; -import org.onap.music.authentication.CachingUtil; -import org.onap.music.datastore.MusicDataStoreHandle; import org.onap.music.datastore.PreparedQueryObject; import org.onap.music.datastore.jsonobjects.JsonInsert; import org.onap.music.datastore.jsonobjects.JsonLeasedLock; +import org.onap.music.datastore.jsonobjects.JsonLock; import org.onap.music.datastore.jsonobjects.JsonTable; +import org.onap.music.datastore.jsonobjects.JsonUpdate; import org.onap.music.exceptions.MusicServiceException; import org.onap.music.lockingservice.cassandra.CassaLockStore; +import org.onap.music.lockingservice.cassandra.LockType; import org.onap.music.main.MusicCore; import org.onap.music.main.MusicUtil; import org.onap.music.rest.RestMusicDataAPI; @@ -56,256 +59,253 @@ import com.datastax.driver.core.DataType; import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.Row; import com.sun.jersey.core.util.Base64; +import com.sun.jersey.core.util.MultivaluedMapImpl; @RunWith(MockitoJUnitRunner.class) public class TstRestMusicLockAPI { - RestMusicLocksAPI lock = new RestMusicLocksAPI(); - RestMusicDataAPI data = new RestMusicDataAPI(); - static PreparedQueryObject testObject; - - static String appName = "TestApp"; - static String userId = "TestUser"; - static String password = "TestPassword"; - static String authData = userId+":"+password; - static String wrongAuthData = userId+":"+"pass"; - static String authorization = new String(Base64.encode(authData.getBytes())); - static String wrongAuthorization = new String(Base64.encode(wrongAuthData.getBytes())); - static boolean isAAF = false; - static UUID uuid = UUID.fromString("abc66ccc-d857-4e90-b1e5-df98a3d40ce6"); - static String keyspaceName = "testcassa"; - static String tableName = "employees"; - static String onboardUUID = null; - static String lockName = "testcassa.employees.testname"; - static String malformedLock = "malformedLock"; - - @BeforeClass - public static void init() throws Exception { - System.out.println("Testing RestMusicLock class"); - try { - createKeyspace(); - } catch (Exception e) { - e.printStackTrace(); - throw new Exception("Unable to initialize before TestRestMusicData test class. " + e.getMessage()); - } - } - - @After - public void afterEachTest( ) throws MusicServiceException { - clearAllTablesFromKeyspace(); - } - - @AfterClass - public static void tearDownAfterClass() throws Exception { - testObject = new PreparedQueryObject(); - testObject.appendQueryString("DROP KEYSPACE IF EXISTS " + keyspaceName); - MusicCore.eventualPut(testObject); - } - @SuppressWarnings("unchecked") - @Test - public void test_createLockReference() throws Exception { - System.out.println("Testing create lockref"); - createAndInsertIntoTable(); - Response response =lock.createLockReference(lockName,"1","1",authorization, - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); - Map respMap = (Map) response.getEntity(); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - - assertEquals(200, response.getStatus()); - assertTrue(respMap.containsKey("lock")); - assertTrue(((Map) respMap.get("lock")).containsKey("lock")); + @Mock + UriInfo info; + + RestMusicLocksAPI lock = new RestMusicLocksAPI(); + RestMusicDataAPI data = new RestMusicDataAPI(); + static PreparedQueryObject testObject; + + static String appName = "TestApp"; + static String userId = "TestUser"; + static String password = "TestPassword"; + static String authData = userId + ":" + password; + static String wrongAuthData = userId + ":" + "pass"; + static String authorization = new String(Base64.encode(authData.getBytes())); + static String wrongAuthorization = new String(Base64.encode(wrongAuthData.getBytes())); + static boolean isAAF = false; + static UUID uuid = UUID.fromString("abc66ccc-d857-4e90-b1e5-df98a3d40ce6"); + static String keyspaceName = "testcassa"; + static String tableName = "employees"; + static String onboardUUID = null; + static String lockName = "testcassa.employees.testname"; + + @BeforeClass + public static void init() throws Exception { + System.out.println("Testing RestMusicLock class"); + try { + createKeyspace(); + } catch (Exception e) { + e.printStackTrace(); + throw new Exception("Unable to initialize before TestRestMusicData test class. " + e.getMessage()); + } } - @Test - public void test_createLockReference_wrongAuth() throws Exception { - System.out.println("Testing create lockref with wrong auth"); - createAndInsertIntoTable(); - Response response =lock.createLockReference(lockName,"1","1", wrongAuthorization, - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); + @After + public void afterEachTest() throws MusicServiceException { + clearAllTablesFromKeyspace(); + } - assertEquals(401, response.getStatus()); + @AfterClass + public static void tearDownAfterClass() throws Exception { + testObject = new PreparedQueryObject(); + testObject.appendQueryString("DROP KEYSPACE IF EXISTS " + keyspaceName); + MusicCore.eventualPut(testObject); } - + + @SuppressWarnings("unchecked") @Test - public void test_createLockReference_malformedLockName() throws Exception { - System.out.println("Testing create lockref w/ malformed lock"); + public void test_createLockReference() throws Exception { + System.out.println("Testing create lockref"); createAndInsertIntoTable(); - Response response =lock.createLockReference(malformedLock,"1","1",authorization, - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); + Response response = lock.createLockReference(lockName, "1", "1", authorization, + "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", null, appName); + Map respMap = (Map) response.getEntity(); System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(400, response.getStatus()); + assertEquals(200, response.getStatus()); + assertTrue(respMap.containsKey("lock")); + assertTrue(((Map) respMap.get("lock")).containsKey("lock")); } @Test - public void test_accquireLock() throws Exception { - System.out.println("Testing acquire lock"); - createAndInsertIntoTable(); - String lockRef = createLockReference(); - - Response response = lock.accquireLock(lockRef, "1", "1", authorization, - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(200, response.getStatus()); - } - - @Test - public void test_accquireLock_wrongAuth() throws Exception { - System.out.println("Testing acquire lock w/ wrong auth"); + public void test_createReadLock() throws Exception { + System.out.println("Testing create read lockref"); createAndInsertIntoTable(); - String lockRef = createLockReference(); - - Response response = lock.accquireLock(lockRef, "1", "1", wrongAuthorization, - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); + JsonLock jsonLock = createJsonLock(LockType.READ); + Response response = lock.createLockReference(lockName, "1", "1", authorization, + "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", jsonLock, appName); + Map respMap = (Map) response.getEntity(); System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(401, response.getStatus()); + + assertEquals(200, response.getStatus()); + assertTrue(respMap.containsKey("lock")); + assertTrue(((Map) respMap.get("lock")).containsKey("lock")); } - + @Test - public void test_accquireBadLock() throws Exception { - System.out.println("Testing acquire lock that is not lock-holder"); + public void test_createWriteLock() throws Exception { + System.out.println("Testing create read lockref"); createAndInsertIntoTable(); - - String lockRef1 = createLockReference(); - String lockRef2 = createLockReference(); - - - Response response = lock.accquireLock(lockRef2, "1", "1", authorization, - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); + JsonLock jsonLock = createJsonLock(LockType.WRITE); + Response response = lock.createLockReference(lockName, "1", "1", authorization, + "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", jsonLock, appName); + Map respMap = (Map) response.getEntity(); System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(400, response.getStatus()); + + assertEquals(200, response.getStatus()); + assertTrue(respMap.containsKey("lock")); + assertTrue(((Map) respMap.get("lock")).containsKey("lock")); } - + @Test - public void test_accquireLock_malformedLock() throws Exception { - System.out.println("Testing acquire lock w/ malformedLock"); + public void test_accquireLock() throws Exception { + System.out.println("Testing acquire lock"); createAndInsertIntoTable(); + String lockRef = createLockReference(); - Response response = lock.accquireLock(malformedLock, "1", "1", wrongAuthorization, - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); + Response response = + lock.accquireLock(lockRef, "1", "1", authorization, "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(400, response.getStatus()); + assertEquals(200, response.getStatus()); } - + @Test - public void test_accquireLockWLease() throws Exception { - System.out.println("Testing acquire lock with lease"); + public void test_acquireReadLock() throws Exception { + System.out.println("Testing acquire read lock"); createAndInsertIntoTable(); - String lockRef = createLockReference(); + String lockRef = createLockReference(LockType.READ); + String lockRef2 = createLockReference(LockType.READ); - JsonLeasedLock jsonLock = new JsonLeasedLock(); - jsonLock.setLeasePeriod(10000); //10 second lease period? - Response response = lock.accquireLockWithLease(jsonLock, lockRef, "1", "1", authorization, - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); + Response response = + lock.accquireLock(lockRef, "1", "1", authorization, "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); + System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); + assertEquals(200, response.getStatus()); + response = + lock.accquireLock(lockRef2, "1", "1", authorization, "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); assertEquals(200, response.getStatus()); } @Test - public void test_accquireLockWLease_wrongAuth() throws Exception { - System.out.println("Testing acquire lock with lease w/ wrong Auth"); + public void test_acquireReadLockaFail() throws Exception { + System.out.println("Testing acquire read lock"); createAndInsertIntoTable(); - String lockRef = createLockReference(); + String lockRef = createLockReference(LockType.WRITE); + String lockRef2 = createLockReference(LockType.READ); - JsonLeasedLock jsonLock = new JsonLeasedLock(); - jsonLock.setLeasePeriod(10000); //10 second lease period? - Response response = lock.accquireLockWithLease(jsonLock, lockRef, "1", "1", wrongAuthorization, - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); + Response response = + lock.accquireLock(lockRef, "1", "1", authorization, "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); + System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); + assertEquals(200, response.getStatus()); + response = + lock.accquireLock(lockRef2, "1", "1", authorization, "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(401, response.getStatus()); + assertEquals(400, response.getStatus()); } - + @Test - public void test_accquireLockWLease_malformedLock() throws Exception { - System.out.println("Testing acquire lock with lease w/ malformed lock"); + public void test_writeWReadLock() throws Exception { + System.out.println("Testing writing with a read lock"); createAndInsertIntoTable(); - String lockRef = createLockReference(); + String lockRef = createLockReference(LockType.READ); + + JsonUpdate jsonUpdate = new JsonUpdate(); + Map consistencyInfo = new HashMap<>(); + Map values = new HashMap<>(); + values.put("emp_salary", 2500); + consistencyInfo.put("type", "critical"); + consistencyInfo.put("lockId", lockRef); + jsonUpdate.setConsistencyInfo(consistencyInfo); + jsonUpdate.setKeyspaceName(keyspaceName); + jsonUpdate.setTableName(tableName); + jsonUpdate.setValues(values); + MultivaluedMap row = new MultivaluedMapImpl(); + row.add("emp_name", "testname"); + Mockito.when(info.getQueryParameters()).thenReturn(row); + + Response response = data.updateTable("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, + authorization, jsonUpdate, keyspaceName, tableName, info); - JsonLeasedLock jsonLock = new JsonLeasedLock(); - jsonLock.setLeasePeriod(10000); //10 second lease period? - Response response = lock.accquireLockWithLease(jsonLock, malformedLock, "1", "1", - wrongAuthorization, "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); assertEquals(400, response.getStatus()); } - - @Test - public void test_currentLockHolder() throws Exception { - System.out.println("Testing get current lock holder"); - createAndInsertIntoTable(); - String lockRef = createLockReference(); + @Test + public void test_writeWWriteLock() throws Exception { + System.out.println("Testing writing with a read lock"); + createAndInsertIntoTable(); + String lockRef = createLockReference(LockType.WRITE); + + JsonUpdate jsonUpdate = new JsonUpdate(); + Map consistencyInfo = new HashMap<>(); + Map values = new HashMap<>(); + values.put("emp_salary", 2500); + consistencyInfo.put("type", "critical"); + consistencyInfo.put("lockId", lockRef); + jsonUpdate.setConsistencyInfo(consistencyInfo); + jsonUpdate.setKeyspaceName(keyspaceName); + jsonUpdate.setTableName(tableName); + jsonUpdate.setValues(values); + MultivaluedMap row = new MultivaluedMapImpl(); + row.add("emp_name", "testname"); + Mockito.when(info.getQueryParameters()).thenReturn(row); + + Response response = data.updateTable("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, + authorization, jsonUpdate, keyspaceName, tableName, info); - Response response = lock.currentLockHolder(lockName, "1", "1", authorization, - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(200, response.getStatus()); - Map respMap = (Map) response.getEntity(); - assertEquals(lockRef, ((Map) respMap.get("lock")).get("lock-holder")); + assertEquals(200, response.getStatus()); } - + @Test - public void test_currentLockHolder_wrongAuth() throws Exception { - System.out.println("Testing get current lock holder w/ wrong Auth"); + public void test_accquireLockWLease() throws Exception { + System.out.println("Testing acquire lock with lease"); createAndInsertIntoTable(); - String lockRef = createLockReference(); - Response response = lock.currentLockHolder(lockName, "1", "1", wrongAuthorization, + JsonLeasedLock jsonLock = new JsonLeasedLock(); + jsonLock.setLeasePeriod(10000); // 10 second lease period? + Response response = lock.accquireLockWithLease(jsonLock, lockRef, "1", "1", authorization, "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(401, response.getStatus()); + assertEquals(200, response.getStatus()); } @Test - public void test_currentLockHolder_malformedLock() throws Exception { - System.out.println("Testing get current lock holder w/ malformed lock"); + public void test_accquireBadLock() throws Exception { + System.out.println("Testing acquire lock that is not lock-holder"); createAndInsertIntoTable(); + // This is required to create an initial loc reference. + String lockRef1 = createLockReference(); + // This will create the next lock reference, whcih will not be avalale yet. + String lockRef2 = createLockReference(); - String lockRef = createLockReference(); - - Response response = lock.currentLockHolder(malformedLock, "1", "1", wrongAuthorization, + Response response = lock.accquireLock(lockRef2, "1", "1", authorization, "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); assertEquals(400, response.getStatus()); } @Test - public void test_unLock() throws Exception { - System.out.println("Testing unlock"); - createAndInsertIntoTable(); - String lockRef = createLockReference(); - - Response response = lock.unLock(lockRef, "1", "1", authorization, - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(200, response.getStatus()); - } - - @Test - public void test_unLock_wrongAuth() throws Exception { - System.out.println("Testing unlock w/ wrong auth"); + public void test_currentLockHolder() throws Exception { + System.out.println("Testing get current lock holder"); createAndInsertIntoTable(); + String lockRef = createLockReference(); - Response response = lock.unLock(lockRef, "1", "1", wrongAuthorization, - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); + Response response = + lock.enquireLock(lockName, "1", "1", authorization, "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(401, response.getStatus()); + assertEquals(200, response.getStatus()); + Map respMap = (Map) response.getEntity(); + assertEquals(lockRef, ((Map) respMap.get("lock")).get("lock-holder")); } @Test - public void test_unLock_malformedLock() throws Exception { - System.out.println("Testing unlock w/ malformedLock"); + public void test_unLock() throws Exception { + System.out.println("Testing unlock"); createAndInsertIntoTable(); String lockRef = createLockReference(); - Response response = lock.unLock("malformedLock", "1", "1", wrongAuthorization, - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); + Response response = + lock.unLock(lockRef, "1", "1", authorization, "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(400, response.getStatus()); + assertEquals(200, response.getStatus()); } @Test @@ -322,102 +322,59 @@ public class TstRestMusicLockAPI { Map respMap = (Map) response.getEntity(); assertEquals(lockRef, ((Map) respMap.get("lock")).get("lock-holder")); } - - @Test - public void test_getLockState_wrongAuth() throws Exception { - System.out.println("Testing get lock state w/ wrong auth"); - createAndInsertIntoTable(); - - String lockRef = createLockReference(); - Response response = lock.currentLockState(lockName, "1", "1", wrongAuthorization, - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(401, response.getStatus()); - } - + // Ignoring since this is now a duplicate of delete lock ref. @Test - public void test_getLockState_malformedLock() throws Exception { - System.out.println("Testing get lock state w/ malformedLock"); - createAndInsertIntoTable(); - - String lockRef = createLockReference(); - - Response response = lock.currentLockState(malformedLock, "1", "1", wrongAuthorization, - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(400, response.getStatus()); - } - - @Test - @Ignore //deprecated function + @Ignore public void test_deleteLock() throws Exception { - System.out.println("Testing delete lock"); + System.out.println("Testing get lock state"); createAndInsertIntoTable(); - String lockRef = createLockReference(); - Response response = lock.deleteLock(lockName, "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", authorization, appName); System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); assertEquals(200, response.getStatus()); } - @Test - @Ignore //deprecated function - public void test_deleteLock_wrongAuth() throws Exception { - System.out.println("Testing delete lock w/ wrong auth"); - createAndInsertIntoTable(); - - String lockRef = createLockReference(); - - Response response = lock.deleteLock(lockName, "1", "1", - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", wrongAuthorization, appName); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(401, response.getStatus()); + /** + * Create table and lock reference + * + * @return the lock ref created + * @throws Exception + */ + @SuppressWarnings("unchecked") + private String createLockReference() throws Exception { + Response response = lock.createLockReference(lockName, "1", "1", authorization, + "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", null, appName); + Map respMap = (Map) response.getEntity(); + return ((Map) respMap.get("lock")).get("lock"); } - - @Test - @Ignore //deprecated function - public void test_deleteLock_malformedLock() throws Exception { - System.out.println("Testing delete lock w/ malformed lock"); - createAndInsertIntoTable(); - - String lockRef = createLockReference(); - Response response = lock.deleteLock(malformedLock, "1", "1", - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", wrongAuthorization, appName); - System.out.println("Status: " + response.getStatus() + ". Entity " + response.getEntity()); - assertEquals(400, response.getStatus()); + /** + * Create table and lock reference + * + * @return the lock ref created + * @throws Exception + */ + @SuppressWarnings("unchecked") + private String createLockReference(LockType lockType) throws Exception { + JsonLock jsonLock = createJsonLock(lockType); + Response response = lock.createLockReference(lockName, "1", "1", authorization, + "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", jsonLock, appName); + Map respMap = (Map) response.getEntity(); + return ((Map) respMap.get("lock")).get("lock"); } - - /** - * Create table and lock reference - * @return the lock ref created - * @throws Exception - */ - @SuppressWarnings("unchecked") - private String createLockReference() throws Exception { - Response response =lock.createLockReference(lockName,"1","1",authorization, - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName); - Map respMap = (Map) response.getEntity(); - return ((Map) respMap.get("lock")).get("lock"); - } - - - - - private static void createKeyspace() throws Exception { - //shouldn't really be doing this here, but create keyspace is currently turned off - PreparedQueryObject query = new PreparedQueryObject(); - query.appendQueryString(CassandraCQL.createKeySpace); - MusicCore.eventualPut(query); - - boolean isAAF = false; + + private static void createKeyspace() throws Exception { + // shouldn't really be doing this here, but create keyspace is currently turned off + PreparedQueryObject query = new PreparedQueryObject(); + query.appendQueryString(CassandraCQL.createKeySpace); + MusicCore.eventualPut(query); + + boolean isAAF = false; String hashedpwd = BCrypt.hashpw(password, BCrypt.gensalt()); query = new PreparedQueryObject(); - query.appendQueryString( - "INSERT into admin.keyspace_master (uuid, keyspace_name, application_name, is_api, " + query.appendQueryString("INSERT into admin.keyspace_master (uuid, keyspace_name, application_name, is_api, " + "password, username, is_aaf) values (?,?,?,?,?,?,?)"); query.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); query.addValue(MusicUtil.convertToActualDataType(DataType.text(), keyspaceName)); @@ -426,69 +383,78 @@ public class TstRestMusicLockAPI { query.addValue(MusicUtil.convertToActualDataType(DataType.text(), hashedpwd)); query.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); query.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF)); - CachingUtil.updateMusicCache(keyspaceName, appName); - CachingUtil.updateMusicValidateCache(appName, userId, hashedpwd); + //CachingUtil.updateMusicCache(keyspaceName, appName); + //CachingUtil.updateMusicValidateCache(appName, userId, hashedpwd); MusicCore.eventualPut(query); - } - - private void clearAllTablesFromKeyspace() throws MusicServiceException { - ArrayList tableNames = new ArrayList<>(); - PreparedQueryObject query = new PreparedQueryObject(); - query.appendQueryString("SELECT table_name FROM system_schema.tables WHERE keyspace_name = '"+keyspaceName+"';"); - ResultSet rs = MusicCore.get(query); - for (Row row: rs) { - tableNames.add(row.getString("table_name")); - } - for (String table: tableNames) { - query = new PreparedQueryObject(); - query.appendQueryString("DROP TABLE " + keyspaceName + "." + table); - MusicCore.eventualPut(query); - } - } - - /** - * Create a table {@link tableName} in {@link keyspaceName} - * @throws Exception - */ - private void createTable() throws Exception { - JsonTable jsonTable = new JsonTable(); - Map consistencyInfo = new HashMap<>(); - Map fields = new HashMap<>(); - fields.put("uuid", "text"); - fields.put("emp_name", "text"); - fields.put("emp_salary", "varint"); - fields.put("PRIMARY KEY", "(emp_name)"); - consistencyInfo.put("type", "eventual"); - jsonTable.setConsistencyInfo(consistencyInfo); - jsonTable.setKeyspaceName(keyspaceName); - jsonTable.setPrimaryKey("emp_name"); - jsonTable.setTableName(tableName); - jsonTable.setFields(fields); - //Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); - Response response = data.createTable("1", "1", "1", - "abc66ccc-d857-4e90-b1e5-df98a3d40ce6",appName, authorization, - jsonTable, keyspaceName, tableName); - } - - /** - * Create table {@link createTable} and insert into said table - * @throws Exception - */ - private void createAndInsertIntoTable() throws Exception { - createTable(); - - JsonInsert jsonInsert = new JsonInsert(); - Map consistencyInfo = new HashMap<>(); - Map values = new HashMap<>(); - values.put("uuid", "cfd66ccc-d857-4e90-b1e5-df98a3d40cd6"); - values.put("emp_name", "testname"); - values.put("emp_salary", 500); - consistencyInfo.put("type", "eventual"); - jsonInsert.setConsistencyInfo(consistencyInfo); - jsonInsert.setKeyspaceName(keyspaceName); - jsonInsert.setTableName(tableName); - jsonInsert.setValues(values); - Response response = data.insertIntoTable("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", - appName, authorization, jsonInsert, keyspaceName, tableName); - } -} + } + + private void clearAllTablesFromKeyspace() throws MusicServiceException { + ArrayList tableNames = new ArrayList<>(); + PreparedQueryObject query = new PreparedQueryObject(); + query.appendQueryString( + "SELECT table_name FROM system_schema.tables WHERE keyspace_name = '" + keyspaceName + "';"); + ResultSet rs = MusicCore.get(query); + for (Row row : rs) { + tableNames.add(row.getString("table_name")); + } + for (String table : tableNames) { + query = new PreparedQueryObject(); + query.appendQueryString("DROP TABLE " + keyspaceName + "." + table); + MusicCore.eventualPut(query); + } + } + + /** + * Create a table {@link tableName} in {@link keyspaceName} + * + * @throws Exception + */ + private void createTable() throws Exception { + JsonTable jsonTable = new JsonTable(); + Map consistencyInfo = new HashMap<>(); + Map fields = new HashMap<>(); + fields.put("uuid", "text"); + fields.put("emp_name", "text"); + fields.put("emp_salary", "varint"); + fields.put("PRIMARY KEY", "(emp_name)"); + consistencyInfo.put("type", "eventual"); + jsonTable.setConsistencyInfo(consistencyInfo); + jsonTable.setKeyspaceName(keyspaceName); + jsonTable.setPrimaryKey("emp_name"); + jsonTable.setTableName(tableName); + jsonTable.setFields(fields); + // Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Response response = data.createTable("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, + authorization, jsonTable, keyspaceName, tableName); + } + + /** + * Create table {@link createTable} and insert into said table + * + * @throws Exception + */ + private void createAndInsertIntoTable() throws Exception { + createTable(); + + JsonInsert jsonInsert = new JsonInsert(); + Map consistencyInfo = new HashMap<>(); + Map values = new HashMap<>(); + values.put("uuid", "cfd66ccc-d857-4e90-b1e5-df98a3d40cd6"); + values.put("emp_name", "testname"); + values.put("emp_salary", 500); + consistencyInfo.put("type", "eventual"); + jsonInsert.setConsistencyInfo(consistencyInfo); + jsonInsert.setKeyspaceName(keyspaceName); + jsonInsert.setTableName(tableName); + jsonInsert.setValues(values); + Response response = data.insertIntoTable("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, + authorization, jsonInsert, keyspaceName, tableName); + } + + private JsonLock createJsonLock(LockType lockType) { + JsonLock jsonLock = new JsonLock(); + jsonLock.setLockType(lockType); + return jsonLock; + } + +} \ No newline at end of file diff --git a/version.properties b/version.properties index 2e44b609..e4766ef0 100755 --- a/version.properties +++ b/version.properties @@ -4,7 +4,7 @@ major=3 minor=2 -patch=28 +patch=29 base_version=${major}.${minor}.${patch} -- cgit 1.2.3-korg