X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Forg%2Fonap%2Fmusic%2Frest%2FRestMusicDataAPI.java;h=8500298b9566ead255e794079e19f8212c033d64;hb=0a358ea9fd56796d7dcf9c2a50df82a4f05b9738;hp=4c8de434241f36b95a72686d9fc6c0630c55c08a;hpb=c3b32d4f9e681115e061b5d3a907363a346b1f40;p=music.git diff --git a/src/main/java/org/onap/music/rest/RestMusicDataAPI.java b/src/main/java/org/onap/music/rest/RestMusicDataAPI.java index 4c8de434..8500298b 100755 --- a/src/main/java/org/onap/music/rest/RestMusicDataAPI.java +++ b/src/main/java/org/onap/music/rest/RestMusicDataAPI.java @@ -1,28 +1,34 @@ /* - * ============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_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.rest; -import java.util.ArrayList; -import java.util.HashMap; +import java.nio.ByteBuffer; import java.util.List; import java.util.Map; import java.util.UUID; -import javax.servlet.http.HttpServletResponse; + import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; @@ -35,7 +41,17 @@ import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.UriInfo; + +import org.apache.commons.lang3.StringUtils; +import org.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; @@ -44,28 +60,33 @@ import org.onap.music.datastore.jsonobjects.JsonTable; import org.onap.music.datastore.jsonobjects.JsonUpdate; import org.onap.music.eelf.logging.EELFLoggerDelegate; import org.onap.music.exceptions.MusicLockingException; +import org.onap.music.exceptions.MusicQueryException; import org.onap.music.eelf.logging.format.AppMessages; import org.onap.music.eelf.logging.format.ErrorSeverity; import org.onap.music.eelf.logging.format.ErrorTypes; import org.onap.music.exceptions.MusicServiceException; -import org.onap.music.main.CachingUtil; import org.onap.music.main.MusicCore; -import org.onap.music.main.MusicCore.Condition; +import org.onap.music.datastore.Condition; +import org.onap.music.datastore.MusicDataStoreHandle; import org.onap.music.main.MusicUtil; import org.onap.music.main.ResultType; import org.onap.music.main.ReturnType; import org.onap.music.response.jsonobjects.JsonResponse; -import com.att.eelf.configuration.EELFLogger; import com.datastax.driver.core.DataType; import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.Row; import com.datastax.driver.core.TableMetadata; + import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponses; +import io.swagger.annotations.ApiResponse; -@Path("/v{version: [0-9]+}/keyspaces") +/* Version 2 Class */ +//@Path("/v{version: [0-9]+}/keyspaces") +@Path("/v2/keyspaces") @Api(value = "Data Api") public class RestMusicDataAPI { /* @@ -76,23 +97,29 @@ public class RestMusicDataAPI { * (e.g. if the full version is 1.24.5, X-minorVersion = "24") - Is optional for the client on * request; however, this header should be provided if the client needs to take advantage of * MINOR incremented version functionality - Is mandatory for the server on response - * + * *** X-patchVersion *** - Used only to communicate a PATCH version in a response for * troubleshooting purposes only, and will not be provided by the client on request - This will * be the latest PATCH version of the MINOR requested by the client, or the latest PATCH version * of the MAJOR (if not specified by the client on the request) - Contains a single position * value (e.g. if the full version is 1.24.5, X-patchVersion = "5") - Is mandatory for the - * server on response + * server on response (CURRENTLY NOT USED) * *** X-latestVersion *** - Used only to communicate an API's latest version - Is mandatory for the * server on response, and shall include the entire version of the API (e.g. if the full version * is 1.24.5, X-latestVersion = "1.24.5") - Used in the response to inform clients that they are - * not using the latest version of the API + * not using the latest version of the API (CURRENTLY NOT USED) * */ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicDataAPI.class); - private static String xLatestVersion = "X-latestVersion"; + 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(); + // 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; @@ -109,20 +136,10 @@ public class RestMusicDataAPI { } } - @SuppressWarnings("unused") - private String buildVersion(String major, String minor, String patch) { - if (minor != null) { - major += "." + minor; - if (patch != null) { - major += "." + patch; - } - } - return major; - } /** * Create Keyspace REST - * + * * @param kspObject * @param keyspaceName * @return @@ -130,126 +147,140 @@ public class RestMusicDataAPI { */ @POST @Path("/{name}") - @ApiOperation(value = "Create Keyspace", response = String.class) + @ApiOperation(value = "Create Keyspace", response = String.class,hidden = true) @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - public Map createKeySpace( - @ApiParam(value = "Major Version", - required = true) @PathParam("version") String version, - @ApiParam(value = "Minor Version", - required = false) @HeaderParam("X-minorVersion") String minorVersion, - @ApiParam(value = "Patch Version", - required = false) @HeaderParam("X-patchVersion") String patchVersion, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, - @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns, - @ApiParam(value = "userId", - required = true) @HeaderParam("userId") String userId, - @ApiParam(value = "Password", - required = true) @HeaderParam("password") String password, + public Response createKeySpace( + @ApiParam(value = "Major Version",required = true) @PathParam("version") String version, + @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, + @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, + @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid, + @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, + @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns, JsonKeySpace kspObject, - @ApiParam(value = "Keyspace Name", - required = true) @PathParam("name") String keyspaceName, - @Context HttpServletResponse response) { - Map authMap = CachingUtil.verifyOnboarding(ns, userId, password); - response.addHeader(xLatestVersion, MusicUtil.getVersion()); - if (!authMap.isEmpty()) { - return new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap(); - } - if(kspObject == null || kspObject.getReplicationInfo() == null) { - authMap.put(ResultType.EXCEPTION.getResult(), ResultType.BODYMISSING.getResult()); - return authMap; - } - + @ApiParam(value = "Keyspace Name",required = true) @PathParam("name") String keyspaceName) { try { - authMap = MusicCore.autheticateUser(ns, userId, password, keyspaceName, aid, - "createKeySpace"); - } catch (Exception e) { - logger.error(EELFLoggerDelegate.applicationLogger, - "Exception while authenting the user."); - return new JsonResponse(ResultType.FAILURE).setError("Unable to authenticate.").toMap(); - } - String newAid = null; - if (!authMap.isEmpty()) { - if (authMap.containsKey("aid")) { - newAid = (String) authMap.get("aid"); - } else { - return new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap(); + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) "); + logger.info(EELFLoggerDelegate.applicationLogger,"In Create Keyspace " + keyspaceName); + if ( KEYSPACE_ACTIVE ) { + 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(); + } + PreparedQueryObject queryObject = new PreparedQueryObject(); + if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && kspObject.getConsistencyInfo().get("consistency") != null) { + if(MusicUtil.isValidConsistency(kspObject.getConsistencyInfo().get("consistency"))) + queryObject.setConsistency(kspObject.getConsistencyInfo().get("consistency")); + else + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build(); + } + long start = System.currentTimeMillis(); + Map replicationInfo = kspObject.getReplicationInfo(); + String repString = null; + try { + repString = "{" + MusicUtil.jsonMaptoSqlString(replicationInfo, ",") + "}"; + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGDATA ,ErrorSeverity + .CRITICAL, ErrorTypes.DATAERROR, e); + } - } - - String consistency = MusicUtil.EVENTUAL;// for now this needs only - // eventual consistency - - PreparedQueryObject queryObject = new PreparedQueryObject(); - long start = System.currentTimeMillis(); - Map replicationInfo = kspObject.getReplicationInfo(); - String repString = null; - try { - repString = "{" + MusicUtil.jsonMaptoSqlString(replicationInfo, ",") + "}"; - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); - } - queryObject.appendQueryString( - "CREATE KEYSPACE " + keyspaceName + " WITH replication = " + repString); - if (kspObject.getDurabilityOfWrites() != null) { queryObject.appendQueryString( - " AND durable_writes = " + kspObject.getDurabilityOfWrites()); - } - - queryObject.appendQueryString(";"); - long end = System.currentTimeMillis(); - logger.info(EELFLoggerDelegate.applicationLogger, - "Time taken for setting up query in create keyspace:" + (end - start)); - - ResultType result = ResultType.FAILURE; - try { - result = MusicCore.nonKeyRelatedPut(queryObject, consistency); - logger.error(EELFLoggerDelegate.errorLogger, "result = " + result); - } catch ( MusicServiceException ex) { - logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); - return new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap(); - } - - 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 + "'"); + "CREATE KEYSPACE " + keyspaceName + " WITH replication = " + repString); + if (kspObject.getDurabilityOfWrites() != null) { + queryObject.appendQueryString( + " AND durable_writes = " + kspObject.getDurabilityOfWrites()); + } + queryObject.appendQueryString(";"); - MusicCore.nonKeyRelatedPut(queryObject, consistency); - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); + long end = System.currentTimeMillis(); + logger.info(EELFLoggerDelegate.applicationLogger, + "Time taken for setting up query in create keyspace:" + (end - start)); + + ResultType result = ResultType.FAILURE; + try { + result = MusicCore.nonKeyRelatedPut(queryObject, consistency); + logger.info(EELFLoggerDelegate.applicationLogger, "result = " + result); + } catch ( MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity + .WARN, ErrorTypes.MUSICSERVICEERROR, ex); + 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 no longer supported after versions 3.2.x. Contact DBA to create the keyspace."; + logger.info(EELFLoggerDelegate.applicationLogger,vError); + logger.error(EELFLoggerDelegate.errorLogger,vError, AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); + return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(vError).toMap()).build(); } - - try { - boolean isAAF = Boolean.valueOf(CachingUtil.isAAFApplication(ns)); - queryObject = new PreparedQueryObject(); - queryObject.appendQueryString( - "INSERT into admin.keyspace_master (uuid, keyspace_name, application_name, is_api, " - + "password, username, is_aaf) values (?,?,?,?,?,?,?)"); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), newAid)); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), keyspaceName)); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), ns)); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "True")); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), password)); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF)); - CachingUtil.updateMusicCache(newAid, keyspaceName); - MusicCore.eventualPut(queryObject); - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); - return new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap(); + } finally { + EELFLoggerDelegate.mdcRemove("keyspace"); } - return new JsonResponse(ResultType.SUCCESS).toMap(); } /** - * + * * @param kspObject * @param keyspaceName * @return @@ -257,138 +288,232 @@ public class RestMusicDataAPI { */ @DELETE @Path("/{name}") - @ApiOperation(value = "Delete Keyspace", response = String.class) - @Consumes(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Delete Keyspace", response = String.class,hidden=true) @Produces(MediaType.APPLICATION_JSON) - public Map dropKeySpace( - @ApiParam(value = "Major Version", - required = true) @PathParam("version") String version, - @ApiParam(value = "Minor Version", - required = false) @HeaderParam("X-minorVersion") String minorVersion, - @ApiParam(value = "Patch Version", - required = false) @HeaderParam("X-patchVersion") String patchVersion, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, - @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns, - @ApiParam(value = "userId", - required = true) @HeaderParam("userId") String userId, - @ApiParam(value = "Password", - required = true) @HeaderParam("password") String password, - JsonKeySpace kspObject, - @ApiParam(value = "Keyspace Name", - required = true) @PathParam("name") String keyspaceName, - @Context HttpServletResponse response) throws Exception { - Map authMap = MusicCore.autheticateUser(ns, userId, password, - keyspaceName, aid, "dropKeySpace"); - response.addHeader(xLatestVersion, MusicUtil.getVersion()); - if (authMap.containsKey("aid")) - authMap.remove("aid"); - if (!authMap.isEmpty()) { - return authMap; - } - - 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) { - return new JsonResponse(ResultType.FAILURE).setError("Keyspace not found. Please make sure keyspace exists.").toMap(); - } else if (count == 1) { - pQuery = new PreparedQueryObject(); + public Response dropKeySpace( + @ApiParam(value = "Major Version",required = true) @PathParam("version") String version, + @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, + @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, + @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid, + @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, + @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns, + @ApiParam(value = "Keyspace Name",required = true) @PathParam("name") String keyspaceName) throws Exception { + try { + ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion); + EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) "); + logger.info(EELFLoggerDelegate.applicationLogger,"In Drop Keyspace " + keyspaceName); + if ( KEYSPACE_ACTIVE ) { + 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( - "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); + "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); + if ( result.equals(ResultType.FAILURE) ) { + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Error Deleteing Keyspace " + keyspaceName).toMap()).build(); + } + return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Deleted").toMap()).build(); } else { - pQuery = new PreparedQueryObject(); - pQuery.appendQueryString("delete from admin.keyspace_master where uuid = ?"); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); - MusicCore.nonKeyRelatedPut(pQuery, consistency); + String vError = "Keyspace Droping no longer supported after versions 3.2.x. Contact DBA to drop the keyspace."; + logger.info(EELFLoggerDelegate.applicationLogger,vError); + logger.error(EELFLoggerDelegate.errorLogger,vError, AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); + return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(vError).toMap()).build(); + } + } finally { + EELFLoggerDelegate.mdcRemove("keyspace"); } - - PreparedQueryObject queryObject = new PreparedQueryObject(); - queryObject.appendQueryString("DROP KEYSPACE " + keyspaceName + ";"); - return new JsonResponse(MusicCore.nonKeyRelatedPut(queryObject, consistency)).toMap(); } /** - * + * * @param tableObj + * @param version * @param keyspace * @param tablename + * @param headers * @return * @throws Exception */ @POST - @Path("/{keyspace}/tables/{tablename}") + @Path("/{keyspace: .*}/tables/{tablename: .*}") @ApiOperation(value = "Create Table", response = String.class) @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - public Map createTable( - @ApiParam(value = "Major Version", - required = true) @PathParam("version") String version, - @ApiParam(value = "Minor Version", - required = false) @HeaderParam("X-minorVersion") String minorVersion, - @ApiParam(value = "Patch Version", - required = false) @HeaderParam("X-patchVersion") String patchVersion, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, - @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns, - @ApiParam(value = "userId", - required = true) @HeaderParam("userId") String userId, - @ApiParam(value = "Password", - required = true) @HeaderParam("password") String password, - JsonTable tableObj, - @ApiParam(value = "Keyspace Name", - required = true) @PathParam("keyspace") String keyspace, - @ApiParam(value = "Table Name", - required = true) @PathParam("tablename") String tablename, - @Context HttpServletResponse response) throws Exception { - - Map authMap = MusicCore.autheticateUser(ns, userId, password, keyspace, - aid, "createTable"); - response.addHeader(xLatestVersion, MusicUtil.getVersion()); - if (authMap.containsKey("aid")) - authMap.remove("aid"); - if (!authMap.isEmpty()) { - return new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap(); + @ApiResponses(value={ + @ApiResponse(code= 400, message = "Will return JSON response with message"), + @ApiResponse(code= 401, message = "Unautorized User") + }) + public Response createTable( + @ApiParam(value = "Major Version",required = true) @PathParam("version") String version, + @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion, + @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion, + @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns, + @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization, + JsonTable tableObj, + @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." + + "Parameter values: keyspace='" + keyspace + "' tablename='" + tablename + "'") + .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; + String partitionKey = tableObj.getPartitionKey(); + String clusterKey = tableObj.getClusteringKey(); + String filteringKey = tableObj.getFilteringKey(); + if(filteringKey != null) { + clusterKey = clusterKey + "," + filteringKey; + } + primaryKey = tableObj.getPrimaryKey(); // get primaryKey if available + PreparedQueryObject queryObject = new PreparedQueryObject(); // first read the information about the table fields Map fields = tableObj.getFields(); StringBuilder fieldsString = new StringBuilder("(vector_ts text,"); int counter = 0; - String primaryKey; for (Map.Entry entry : fields.entrySet()) { - if (entry.getKey().equals("PRIMARY KEY")) { - if(! entry.getValue().contains("(")) - primaryKey = entry.getValue(); - else { - primaryKey = entry.getValue().substring(entry.getValue().indexOf('(') + 1); - primaryKey = primaryKey.substring(0, primaryKey.indexOf(')')); - } - fieldsString.append("" + entry.getKey() + " (" + primaryKey + ")"); - } else - fieldsString.append("" + entry.getKey() + " " + entry.getValue() + ""); - if (counter == fields.size() - 1) + primaryKey = entry.getValue(); // replaces primaryKey + primaryKey = primaryKey.trim(); + } else { + if (counter == 0 ) fieldsString.append("" + entry.getKey() + " " + entry.getValue() + ""); + else fieldsString.append("," + entry.getKey() + " " + entry.getValue() + ""); + } + + if (counter != (fields.size() - 1) ) { + + counter = counter + 1; + } else { + + if((primaryKey != null) && (partitionKey == null)) { + primaryKey = primaryKey.trim(); + int count1 = StringUtils.countMatches(primaryKey, ')'); + int count2 = StringUtils.countMatches(primaryKey, '('); + if (count1 != count2) { + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + .setError("Create Table Error: primary key '(' and ')' do not match, primary key=" + primaryKey) + .toMap()).build(); + } + + if ( primaryKey.indexOf('(') == -1 || ( count2 == 1 && (primaryKey.lastIndexOf(')') +1) == primaryKey.length() ) ) + { + if (primaryKey.contains(",") ) { + partitionKey= primaryKey.substring(0,primaryKey.indexOf(',')); + partitionKey=partitionKey.replaceAll("[\\(]+",""); + clusterKey=primaryKey.substring(primaryKey.indexOf(',')+1); // make sure index + clusterKey=clusterKey.replaceAll("[)]+", ""); + } else { + partitionKey=primaryKey; + partitionKey=partitionKey.replaceAll("[\\)]+",""); + partitionKey=partitionKey.replaceAll("[\\(]+",""); + clusterKey=""; + } + } else { // not null and has ) before the last char + partitionKey= primaryKey.substring(0,primaryKey.indexOf(')')); + partitionKey=partitionKey.replaceAll("[\\(]+",""); + partitionKey = partitionKey.trim(); + clusterKey= primaryKey.substring(primaryKey.indexOf(')')); + clusterKey=clusterKey.replaceAll("[\\(]+",""); + clusterKey=clusterKey.replaceAll("[\\)]+",""); + clusterKey = clusterKey.trim(); + if (clusterKey.indexOf(',') == 0) clusterKey=clusterKey.substring(1); + clusterKey = clusterKey.trim(); + if (clusterKey.equals(",") ) clusterKey=""; // print error if needed ( ... ),) + } + + if (!(partitionKey.isEmpty() || clusterKey.isEmpty()) + && (partitionKey.equalsIgnoreCase(clusterKey) || + clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) + { + logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey + " and primary key=" + primaryKey ); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError( + "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ") of" + + " primary key=" + primaryKey) + .toMap()).build(); + + } + + if (partitionKey.isEmpty() ) primaryKey=""; + else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")"; + else primaryKey=" (" + partitionKey + ")," + clusterKey; + + + if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )"); + + } // end of length > 0 + else { + if (!(partitionKey.isEmpty() || clusterKey.isEmpty()) + && (partitionKey.equalsIgnoreCase(clusterKey) || + clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) + { + logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError( + "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ")") + .toMap()).build(); + } + + if (partitionKey.isEmpty() ) primaryKey=""; + else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")"; + else primaryKey=" (" + partitionKey + ")," + clusterKey; + + + if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )"); + } fieldsString.append(")"); - else - fieldsString.append(","); - counter = counter + 1; - } + + } // end of last field check + + } // end of for each // information about the name-value style properties Map propertiesMap = tableObj.getProperties(); StringBuilder propertiesString = new StringBuilder(); @@ -413,27 +538,64 @@ public class RestMusicDataAPI { } } + String clusteringOrder = tableObj.getClusteringOrder(); + + if (clusteringOrder != null && !(clusteringOrder.isEmpty())) { + String[] arrayClusterOrder = clusteringOrder.split("[,]+"); + + for (int i = 0; i < arrayClusterOrder.length; i++) { + String[] clusterS = arrayClusterOrder[i].trim().split("[ ]+"); + if ( (clusterS.length ==2) && (clusterS[1].equalsIgnoreCase("ASC") || clusterS[1].equalsIgnoreCase("DESC"))) { + continue; + } else { + return response.status(Status.BAD_REQUEST) + .entity(new JsonResponse(ResultType.FAILURE) + .setError("createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname order; please correct clusteringOrder:"+ clusteringOrder+".") + .toMap()).build(); + } + // add validation for column names in cluster key + } + + if (!(clusterKey.isEmpty())) { + clusteringOrder = "CLUSTERING ORDER BY (" +clusteringOrder +")"; + //cjc check if propertiesString.length() >0 instead propertiesMap + if (propertiesMap != null) { + propertiesString.append(" AND "+ clusteringOrder); + } else { + propertiesString.append(clusteringOrder); + } + } else { + logger.warn("Skipping clustering order=("+clusteringOrder+ ") since clustering key is empty "); + } + } //if non empty + queryObject.appendQueryString( - "CREATE TABLE " + keyspace + "." + tablename + " " + fieldsString); + "CREATE TABLE " + keyspace + "." + tablename + " " + fieldsString); - if (propertiesMap != null) - queryObject.appendQueryString(" WITH " + propertiesString); + if (propertiesString != null && propertiesString.length()>0 ) + queryObject.appendQueryString(" WITH " + propertiesString); queryObject.appendQueryString(";"); ResultType result = ResultType.FAILURE; - try { - result = MusicCore.nonKeyRelatedPut(queryObject, consistency); + result = MusicCore.createTable(keyspace, tablename, queryObject, consistency); } catch (MusicServiceException ex) { - response.setStatus(400); - return new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap(); + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity + .CRITICAL, ErrorTypes.MUSICSERVICEERROR, ex); + response.status(Status.BAD_REQUEST); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); + } + if ( result.equals(ResultType.FAILURE) ) { + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Error Creating Table " + tablename).toMap()).build(); + } + return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("TableName " + tablename.trim() + " Created under keyspace " + keyspace.trim()).toMap()).build(); + } finally { + EELFLoggerDelegate.mdcRemove("keyspace"); } - - return new JsonResponse(result).toMap(); } /** - * + * * @param keyspace * @param tablename * @param fieldName @@ -441,57 +603,64 @@ public class RestMusicDataAPI { * @throws Exception */ @POST - @Path("/{keyspace}/tables/{tablename}/index/{field}") + @Path("/{keyspace: .*}/tables/{tablename: .*}/index/{field: .*}") @ApiOperation(value = "Create Index", response = String.class) @Produces(MediaType.APPLICATION_JSON) - public Map createIndex( - @ApiParam(value = "Major Version", - required = true) @PathParam("version") String version, - @ApiParam(value = "Minor Version", - required = false) @HeaderParam("X-minorVersion") String minorVersion, - @ApiParam(value = "Patch Version", - required = false) @HeaderParam("X-patchVersion") String patchVersion, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, - @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns, - @ApiParam(value = "userId", - required = true) @HeaderParam("userId") String userId, - @ApiParam(value = "Password", - required = true) @HeaderParam("password") String password, - @ApiParam(value = "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, @Context HttpServletResponse response) throws Exception { - Map authMap = MusicCore.autheticateUser(ns, userId, password, keyspace, - aid, "createIndex"); - response.addHeader(xLatestVersion, MusicUtil.getVersion()); - if (authMap.containsKey("aid")) - authMap.remove("aid"); - if (!authMap.isEmpty()) - return new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap(); + 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 { + 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 " + indexName + " if not exists on " + keyspace + "." + 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) { - return new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap(); + 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(); + } + } finally { + EELFLoggerDelegate.mdcRemove("keyspace"); } - - return new JsonResponse(result).toMap(); } /** - * + * * @param insObj * @param keyspace * @param tablename @@ -499,58 +668,49 @@ public class RestMusicDataAPI { * @throws Exception */ @POST - @Path("/{keyspace}/tables/{tablename}/rows") + @Path("/{keyspace: .*}/tables/{tablename: .*}/rows") @ApiOperation(value = "Insert Into Table", response = String.class) @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - public Map insertIntoTable( - @ApiParam(value = "Major Version", - required = true) @PathParam("version") String version, - @ApiParam(value = "Minor Version", - required = false) @HeaderParam("X-minorVersion") String minorVersion, - @ApiParam(value = "Patch Version", - required = false) @HeaderParam("X-patchVersion") String patchVersion, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, - @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns, - @ApiParam(value = "userId", - required = true) @HeaderParam("userId") String userId, - @ApiParam(value = "Password", - required = true) @HeaderParam("password") String password, + 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, - @Context HttpServletResponse response) { - Map authMap = null; + required = true) @PathParam("tablename") String tablename) { try { - authMap = MusicCore.autheticateUser(ns, userId, password, keyspace, - aid, "insertIntoTable"); - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); - return new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap(); + 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(); } - response.addHeader(xLatestVersion, MusicUtil.getVersion()); - if (authMap.containsKey("aid")) - authMap.remove("aid"); - if (!authMap.isEmpty()) { - return new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap(); + 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(); } Map valuesMap = insObj.getValues(); PreparedQueryObject queryObject = new PreparedQueryObject(); TableMetadata tableInfo = null; - try { - tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename); - if(tableInfo == null) { - return new JsonResponse(ResultType.FAILURE) - .setError("Table name doesn't exists. Please check the table name.").toMap(); - } - } catch (MusicServiceException e) { - logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); - return new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap(); - } + 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 = @@ -559,7 +719,7 @@ public class RestMusicDataAPI { queryObject.addValue(vectorTs); int counter = 0; String primaryKey = ""; - + Map objectMap = insObj.getObjectMap(); for (Map.Entry entry : valuesMap.entrySet()) { fieldsString.append("" + entry.getKey()); Object valueObj = entry.getValue(); @@ -571,17 +731,19 @@ public class RestMusicDataAPI { try { colType = tableInfo.getColumn(entry.getKey()).getType(); } catch(NullPointerException ex) { - logger.error(EELFLoggerDelegate.errorLogger, "Invalid column name : "+entry.getKey()); - return new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap(); + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() +" Invalid column name : "+entry.getKey + (), AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR, ex); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap()).build(); } Object formattedValue = null; try { formattedValue = MusicUtil.convertToActualDataType(colType, valueObj); } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger,e); } valueString.append("?"); + queryObject.addValue(formattedValue); if (counter == valuesMap.size() - 1) { @@ -593,12 +755,49 @@ public class RestMusicDataAPI { } counter = counter + 1; } - + + //blobs.. + 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; + /*if (counter == valuesMap.size() - 1) { + fieldsString.append(")"); + valueString.append(")"); + } else {*/ + fieldsString.append(","); + valueString.append(","); + //} + } } + if(primaryKey == null || primaryKey.length() <= 0) { - logger.error(EELFLoggerDelegate.errorLogger, "Some required partition key parts are missing: "+primaryKeyName ); - return new JsonResponse(ResultType.SYNTAXERROR).setError("Some required partition key parts are missing: "+primaryKeyName).toMap(); + logger.error(EELFLoggerDelegate.errorLogger, "Some required partition key parts are missing: "+primaryKeyName ); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Some required partition key parts are missing: "+primaryKeyName).toMap()).build(); } + fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ")"); + valueString.replace(valueString.length()-1, valueString.length(), ")"); + queryObject.appendQueryString("INSERT INTO " + keyspace + "." + tablename + " " + fieldsString + " VALUES " + valueString); @@ -628,6 +827,13 @@ public class RestMusicDataAPI { 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); @@ -636,82 +842,86 @@ public class RestMusicDataAPI { if(lockId == null) { logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); - return new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock " - + "and acquire lock or use ATOMIC instead of CRITICAL").toMap(); + 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); + result = MusicCore.criticalPut(keyspace, tablename, primaryKey, queryObject, lockId,null); } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { - result = MusicCore.atomicPut(keyspace, tablename, primaryKey, queryObject, null); - } - else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) { - result = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, primaryKey, queryObject, null); + result = MusicCore.atomicPut(keyspace, tablename, primaryKey, queryObject, null); } } catch (Exception ex) { - logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); - return new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap(); + 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) { - return new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap(); + 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"); } - return new JsonResponse(result.getResult()).toMap(); } /** - * + * * @param insObj * @param keyspace * @param tablename * @param info * @return + * @throws MusicServiceException + * @throws MusicQueryException * @throws Exception */ @PUT - @Path("/{keyspace}/tables/{tablename}/rows") + @Path("/{keyspace: .*}/tables/{tablename: .*}/rows") @ApiOperation(value = "Update Table", response = String.class) @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - public Map updateTable( + public Response updateTable( @ApiParam(value = "Major Version", required = true) @PathParam("version") String version, @ApiParam(value = "Minor Version", - required = false) @HeaderParam("X-minorVersion") String minorVersion, + required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version", - required = false) @HeaderParam("X-patchVersion") String patchVersion, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + 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 = "userId", - required = true) @HeaderParam("userId") String userId, - @ApiParam(value = "Password", - required = true) @HeaderParam("password") String password, + 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, @Context HttpServletResponse response) { - Map authMap; + @Context UriInfo info) throws MusicQueryException, MusicServiceException { try { - authMap = MusicCore.autheticateUser(ns, userId, password, keyspace, - aid, "updateTable"); - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); - return new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap(); - } - response.addHeader(xLatestVersion, MusicUtil.getVersion()); - if (authMap.containsKey("aid")) - authMap.remove("aid"); - if (!authMap.isEmpty()) { - return new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap(); + 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"); + logger.info(EELFLoggerDelegate.applicationLogger, "--------------Music " + consistency + " update-" + operationId + "-------------------------"); // obtain the field value pairs of the update @@ -720,16 +930,18 @@ public class RestMusicDataAPI { Map valuesMap = updateObj.getValues(); TableMetadata tableInfo; - try { - tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename); - } catch (MusicServiceException e) { - logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); - return new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap(); - } + 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) { - return new JsonResponse(ResultType.FAILURE) + 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(); + + keyspace + "." + tablename).toMap()).build(); } String vectorTs = String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis()); @@ -742,14 +954,14 @@ public class RestMusicDataAPI { try { colType = tableInfo.getColumn(entry.getKey()).getType(); } catch(NullPointerException ex) { - logger.error(EELFLoggerDelegate.errorLogger, "Invalid column name : "+entry.getKey()); - return new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap(); + 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.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger,e); } fieldValueString.append(entry.getKey() + "= ?"); queryObject.addValue(valueString); @@ -785,13 +997,13 @@ public class RestMusicDataAPI { try { rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject); if(rowId == null || rowId.primarKeyValue.isEmpty()) { - - return new JsonResponse(ResultType.FAILURE) - .setError("Mandatory WHERE clause is missing. Please check the input request.").toMap(); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE) + .setError("Mandatory WHERE clause is missing. Please check the input request.").toMap()).build(); } } catch (MusicServiceException ex) { - logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage()); - return new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap(); + 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( @@ -807,12 +1019,19 @@ public class RestMusicDataAPI { selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowId.rowIdString + ";"); selectQuery.addValue(rowId.primarKeyValue); - conditionInfo = new MusicCore.Condition(updateObj.getConditions(), selectQuery); + conditionInfo = new Condition(updateObj.getConditions(), selectQuery); } ReturnType operationResult = null; long jsonParseCompletionTime = System.currentTimeMillis(); + if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && updateObj.getConsistencyInfo().get("consistency") != null) { + if(MusicUtil.isValidConsistency(updateObj.getConsistencyInfo().get("consistency"))) + queryObject.setConsistency(updateObj.getConsistencyInfo().get("consistency")); + else + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build(); + } + queryObject.setOperation("update"); if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) operationResult = MusicCore.eventualPut(queryObject); else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { @@ -820,8 +1039,8 @@ public class RestMusicDataAPI { if(lockId == null) { logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); - return new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock " - + "and acquire lock or use ATOMIC instead of CRITICAL").toMap(); + 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); @@ -831,17 +1050,21 @@ public class RestMusicDataAPI { operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, rowId.primarKeyValue, queryObject, conditionInfo); } catch (MusicLockingException e) { - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); - return new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap(); + 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.getMessage()); - return new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap(); + logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, + ErrorTypes.GENERALSERVICEERROR, e); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build(); } + }else if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) { + operationResult = MusicCore.eventualPut_nb(queryObject, keyspace, tablename, rowId.primarKeyValue); } long actualUpdateCompletionTime = System.currentTimeMillis(); @@ -857,68 +1080,79 @@ public class RestMusicDataAPI { timingString = timingString + lockManagementTime; } logger.info(EELFLoggerDelegate.applicationLogger, timingString); - + if (operationResult==null) { - return new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap(); + 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"); } - return new JsonResponse(operationResult.getResult()).toMap(); } /** - * + * * @param delObj * @param keyspace * @param tablename * @param info * @return + * @throws MusicServiceException + * @throws MusicQueryException * @throws Exception */ @DELETE - @Path("/{keyspace}/tables/{tablename}/rows") + @Path("/{keyspace: .*}/tables/{tablename: .*}/rows") @ApiOperation(value = "Delete From table", response = String.class) @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - public Map deleteFromTable( + public Response deleteFromTable( @ApiParam(value = "Major Version", required = true) @PathParam("version") String version, @ApiParam(value = "Minor Version", - required = false) @HeaderParam("X-minorVersion") String minorVersion, + required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version", - required = false) @HeaderParam("X-patchVersion") String patchVersion, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + 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 = "userId", - required = true) @HeaderParam("userId") String userId, - @ApiParam(value = "Password", - required = true) @HeaderParam("password") String password, + 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, @Context HttpServletResponse response) { - Map authMap = null; - try { - authMap = MusicCore.autheticateUser(ns, userId, password, keyspace, - aid, "deleteFromTable"); - } catch (Exception e) { - return new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap(); - } - response.addHeader(xLatestVersion, MusicUtil.getVersion()); - if (authMap.containsKey("aid")) - authMap.remove("aid"); - if (!authMap.isEmpty()) { - return new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap(); + @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) + .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) { - return new JsonResponse(ResultType.FAILURE).setError("Required HTTP Request body is missing.").toMap(); - } + 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; - ArrayList columnList = delObj.getColumns(); + List columnList = delObj.getColumns(); if (columnList != null) { for (String column : columnList) { columnString.append(column); @@ -933,7 +1167,9 @@ public class RestMusicDataAPI { try { rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject); } catch (MusicServiceException ex) { - return new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap(); + 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(); @@ -961,97 +1197,122 @@ public class RestMusicDataAPI { selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowId.rowIdString + ";"); selectQuery.addValue(rowId.primarKeyValue); - conditionInfo = new MusicCore.Condition(delObj.getConditions(), selectQuery); + conditionInfo = new Condition(delObj.getConditions(), selectQuery); } String consistency = delObj.getConsistencyInfo().get("type"); + + if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && delObj.getConsistencyInfo().get("consistency")!=null) { + + if(MusicUtil.isValidConsistency(delObj.getConsistencyInfo().get("consistency"))) + queryObject.setConsistency(delObj.getConsistencyInfo().get("consistency")); + else + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build(); + } + ReturnType operationResult = null; + queryObject.setOperation("delete"); 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) { + 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 new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock " - + "and acquire lock or use ATOMIC instead of CRITICAL").toMap(); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock " + + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build(); } - operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue, - queryObject, lockId, conditionInfo); - } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { - operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue, - queryObject, conditionInfo); - } - else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) { - operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, rowId.primarKeyValue, - queryObject, conditionInfo); - } + 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); + } } catch (MusicLockingException e) { - return new JsonResponse(ResultType.FAILURE) - .setError("Unable to perform Delete operation. Exception from music").toMap(); - } - if (operationResult.getResult().equals(ResultType.FAILURE)) { - return new JsonResponse(ResultType.FAILURE).setError(operationResult.getMessage()).toMap(); + 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"); } - return new JsonResponse(operationResult.getResult()).toMap(); } /** - * + * * @param tabObj * @param keyspace * @param tablename * @throws Exception */ @DELETE - @Path("/{keyspace}/tables/{tablename}") + @Path("/{keyspace: .*}/tables/{tablename: .*}") @ApiOperation(value = "Drop Table", response = String.class) - @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - public Map dropTable( + public Response dropTable( @ApiParam(value = "Major Version", required = true) @PathParam("version") String version, @ApiParam(value = "Minor Version", - required = false) @HeaderParam("X-minorVersion") String minorVersion, + required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version", - required = false) @HeaderParam("X-patchVersion") String patchVersion, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + 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 = "userId", - required = true) @HeaderParam("userId") String userId, - @ApiParam(value = "Password", - required = true) @HeaderParam("password") String password, - JsonTable tabObj, + 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 HttpServletResponse response) throws Exception { - Map authMap = - MusicCore.autheticateUser(ns, userId, password, keyspace, aid, "dropTable"); - response.addHeader(xLatestVersion, MusicUtil.getVersion()); - if (authMap.containsKey("aid")) - authMap.remove("aid"); - if (!authMap.isEmpty()) { - return new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap(); + 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 + ";"); try { - return new JsonResponse(MusicCore.nonKeyRelatedPut(query, consistency)).toMap(); + return response.status(Status.OK).entity(new JsonResponse(MusicCore.nonKeyRelatedPut(query, consistency)).toMap()).build(); } catch (MusicServiceException ex) { - return new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap(); + 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"); } - } /** - * + * * @param selObj * @param keyspace * @param tablename @@ -1059,39 +1320,42 @@ public class RestMusicDataAPI { * @return */ @PUT - @Path("/{keyspace}/tables/{tablename}/rows/criticalget") + @Path("/{keyspace: .*}/tables/{tablename: .*}/rows/criticalget") @ApiOperation(value = "Select Critical", response = Map.class) @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - public Map selectCritical( + public Response selectCritical( @ApiParam(value = "Major Version", required = true) @PathParam("version") String version, @ApiParam(value = "Minor Version", - required = false) @HeaderParam("X-minorVersion") String minorVersion, + required = false) @HeaderParam(XMINORVERSION) String minorVersion, @ApiParam(value = "Patch Version", - required = false) @HeaderParam("X-patchVersion") String patchVersion, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + 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 = "userId", - required = true) @HeaderParam("userId") String userId, - @ApiParam(value = "Password", - required = true) @HeaderParam("password") String password, + 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, @Context HttpServletResponse response) throws Exception { - Map authMap = MusicCore.autheticateUser(ns, userId, password, keyspace, - aid, "selectCritical"); - response.addHeader(xLatestVersion, MusicUtil.getVersion()); - if (authMap.containsKey("aid")) - authMap.remove("aid"); - if (!authMap.isEmpty()) { - logger.error("Error while authentication... "); - return new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap(); + @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(); @@ -1100,7 +1364,9 @@ public class RestMusicDataAPI { try { rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject); } catch (MusicServiceException ex) { - return new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap(); + 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 + ";"); @@ -1110,27 +1376,29 @@ public class RestMusicDataAPI { String consistency = selObj.getConsistencyInfo().get("type"); if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { - if(lockId == null) { + if(lockId == null) { logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or" + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR); - return new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock " - + "and acquire lock or use ATOMIC instead of CRITICAL").toMap(); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock " + + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build(); } results = MusicCore.criticalGet(keyspace, tablename, rowId.primarKeyValue, queryObject, lockId); } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { results = MusicCore.atomicGet(keyspace, tablename, rowId.primarKeyValue, queryObject); } - - else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) { - results = MusicCore.atomicGetWithDeleteLock(keyspace, tablename, rowId.primarKeyValue, queryObject); + 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(); - return new JsonResponse(ResultType.SUCCESS).setDataResult(MusicCore.marshallResults(results)).toMap(); + } finally { + EELFLoggerDelegate.mdcRemove("keyspace"); + } } /** - * + * * @param keyspace * @param tablename * @param info @@ -1138,37 +1406,40 @@ public class RestMusicDataAPI { * @throws Exception */ @GET - @Path("/{keyspace}/tables/{tablename}/rows") + @Path("/{keyspace: .*}/tables/{tablename: .*}/rows") @ApiOperation(value = "Select All or Select Specific", response = Map.class) @Produces(MediaType.APPLICATION_JSON) - public Map select( - @ApiParam(value = "Major Version", - required = true) @PathParam("version") String version, - @ApiParam(value = "Minor Version", - required = false) @HeaderParam("X-minorVersion") String minorVersion, - @ApiParam(value = "Patch Version", - required = false) @HeaderParam("X-patchVersion") String patchVersion, - @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, - @ApiParam(value = "Application namespace", - required = true) @HeaderParam("ns") String ns, - @ApiParam(value = "userId", - required = true) @HeaderParam("userId") String userId, - @ApiParam(value = "Password", - required = true) @HeaderParam("password") String password, - @ApiParam(value = "Keyspace Name", - required = true) @PathParam("keyspace") String keyspace, - @ApiParam(value = "Table Name", - required = true) @PathParam("tablename") String tablename, - @Context UriInfo info, @Context HttpServletResponse response) throws Exception { - Map authMap = - MusicCore.autheticateUser(ns, userId, password, keyspace, aid, "select"); - response.addHeader(xLatestVersion, MusicUtil.getVersion()); - if (authMap.containsKey("aid")) - authMap.remove("aid"); - if (!authMap.isEmpty()) { - logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); - return new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap(); + 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 { + 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(); if (info.getQueryParameters().isEmpty())// select all @@ -1176,25 +1447,32 @@ public class RestMusicDataAPI { else { int limit = -1; // do not limit the number of results try { - queryObject = selectSpecificQuery(version, minorVersion, patchVersion, aid, ns, - userId, password, keyspace, tablename, info, limit); + queryObject = selectSpecificQuery(keyspace, tablename, info, limit); } catch (MusicServiceException ex) { - return new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap(); + logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, + ErrorTypes.GENERALSERVICEERROR, ex); + return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build(); } } try { ResultSet results = MusicCore.get(queryObject); - return new JsonResponse(ResultType.SUCCESS).setDataResult(MusicCore.marshallResults(results)).toMap(); + 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,"", AppMessages.UNKNOWNERROR ,ErrorSeverity.ERROR, ErrorTypes.MUSICSERVICEERROR); - return new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap(); + 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"); } - } /** - * + * * @param keyspace * @param tablename * @param info @@ -1202,9 +1480,8 @@ public class RestMusicDataAPI { * @return * @throws MusicServiceException */ - public PreparedQueryObject selectSpecificQuery(String version, String minorVersion, - String patchVersion, String aid, String ns, String userId, String password, - String keyspace, String tablename, UriInfo info, int limit) + public PreparedQueryObject selectSpecificQuery(String keyspace, + String tablename, UriInfo info, int limit) throws MusicServiceException { PreparedQueryObject queryObject = new PreparedQueryObject(); @@ -1224,7 +1501,7 @@ public class RestMusicDataAPI { } /** - * + * * @param keyspace * @param tablename * @param rowParams @@ -1237,7 +1514,7 @@ public class RestMusicDataAPI { throws MusicServiceException { StringBuilder rowSpec = new StringBuilder(); int counter = 0; - TableMetadata tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename); + TableMetadata tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename); if (tableInfo == null) { logger.error(EELFLoggerDelegate.errorLogger, "Table information not found. Please check input for table name= " @@ -1251,13 +1528,15 @@ public class RestMusicDataAPI { String keyName = entry.getKey(); List valueList = entry.getValue(); String indValue = valueList.get(0); - DataType colType = tableInfo.getColumn(entry.getKey()).getType(); + DataType colType = null; Object formattedValue = null; try { + colType = tableInfo.getColumn(entry.getKey()).getType(); formattedValue = MusicUtil.convertToActualDataType(colType, indValue); } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger,e); } + if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey())) primaryKey.append(indValue); rowSpec.append(keyName + "= ?"); queryObject.addValue(formattedValue);