2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright (c) 2017 AT&T Intellectual Property
6 * ===================================================================
7 * Modifications Copyright (c) 2019 Samsung
8 * ===================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
21 * ============LICENSE_END=============================================
22 * ====================================================================
25 package org.onap.music.rest;
27 import java.nio.ByteBuffer;
28 import java.util.ArrayList;
29 import java.util.List;
31 import java.util.UUID;
33 import javax.servlet.http.HttpServletResponse;
34 import javax.ws.rs.Consumes;
35 import javax.ws.rs.DELETE;
36 import javax.ws.rs.GET;
37 import javax.ws.rs.HeaderParam;
38 import javax.ws.rs.POST;
39 import javax.ws.rs.PUT;
40 import javax.ws.rs.Path;
41 import javax.ws.rs.PathParam;
42 import javax.ws.rs.Produces;
43 import javax.ws.rs.core.Context;
44 import javax.ws.rs.core.HttpHeaders;
45 import javax.ws.rs.core.MediaType;
46 import javax.ws.rs.core.MultivaluedMap;
47 import javax.ws.rs.core.Response;
48 import javax.ws.rs.core.Response.ResponseBuilder;
49 import javax.ws.rs.core.Response.Status;
50 import javax.ws.rs.core.UriInfo;
52 import org.apache.commons.lang3.StringUtils;
53 import org.mindrot.jbcrypt.BCrypt;
54 import org.onap.music.authentication.MusicAuthentication;
55 import org.onap.music.datastore.PreparedQueryObject;
56 import org.onap.music.datastore.jsonobjects.JsonDelete;
57 import org.onap.music.datastore.jsonobjects.JsonInsert;
58 import org.onap.music.datastore.jsonobjects.JsonKeySpace;
59 import org.onap.music.datastore.jsonobjects.JsonTable;
60 import org.onap.music.datastore.jsonobjects.JsonUpdate;
61 import org.onap.music.eelf.logging.EELFLoggerDelegate;
62 import org.onap.music.exceptions.MusicLockingException;
63 import org.onap.music.exceptions.MusicQueryException;
64 import org.onap.music.eelf.logging.format.AppMessages;
65 import org.onap.music.eelf.logging.format.ErrorSeverity;
66 import org.onap.music.eelf.logging.format.ErrorTypes;
67 import org.onap.music.exceptions.MusicServiceException;
68 import org.onap.music.main.CachingUtil;
69 import org.onap.music.main.MusicCore;
70 import org.onap.music.datastore.Condition;
71 import org.onap.music.datastore.MusicDataStoreHandle;
72 import org.onap.music.main.MusicUtil;
73 import org.onap.music.main.ResultType;
74 import org.onap.music.main.ReturnType;
75 import org.onap.music.response.jsonobjects.JsonResponse;
76 import org.onap.music.service.impl.MusicZKCore;
78 import com.datastax.driver.core.DataType;
79 import com.datastax.driver.core.ResultSet;
80 import com.datastax.driver.core.Row;
81 import com.datastax.driver.core.TableMetadata;
83 import io.swagger.annotations.Api;
84 import io.swagger.annotations.ApiOperation;
85 import io.swagger.annotations.ApiParam;
86 import io.swagger.annotations.ApiResponses;
87 import io.swagger.annotations.ApiResponse;
90 //@Path("/v{version: [0-9]+}/keyspaces")
91 @Path("/v2/keyspaces")
92 @Api(value = "Data Api")
93 public class RestMusicDataAPI {
95 * Header values for Versioning X-minorVersion *** - Used to request or communicate a MINOR
96 * version back from the client to the server, and from the server back to the client - This
97 * will be the MINOR version requested by the client, or the MINOR version of the last MAJOR
98 * version (if not specified by the client on the request) - Contains a single position value
99 * (e.g. if the full version is 1.24.5, X-minorVersion = "24") - Is optional for the client on
100 * request; however, this header should be provided if the client needs to take advantage of
101 * MINOR incremented version functionality - Is mandatory for the server on response
103 *** X-patchVersion *** - Used only to communicate a PATCH version in a response for
104 * troubleshooting purposes only, and will not be provided by the client on request - This will
105 * be the latest PATCH version of the MINOR requested by the client, or the latest PATCH version
106 * of the MAJOR (if not specified by the client on the request) - Contains a single position
107 * value (e.g. if the full version is 1.24.5, X-patchVersion = "5") - Is mandatory for the
108 * server on response (CURRENTLY NOT USED)
110 *** X-latestVersion *** - Used only to communicate an API's latest version - Is mandatory for the
111 * server on response, and shall include the entire version of the API (e.g. if the full version
112 * is 1.24.5, X-latestVersion = "1.24.5") - Used in the response to inform clients that they are
113 * not using the latest version of the API (CURRENTLY NOT USED)
117 private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicDataAPI.class);
118 private static final String XMINORVERSION = "X-minorVersion";
119 private static final String XPATCHVERSION = "X-patchVersion";
120 private static final String NS = "ns";
121 private static final String VERSION = "v2";
122 // Set to true in env like ONAP. Where access to creating and dropping keyspaces exist.
123 private static final boolean KEYSPACE_ACTIVE = false;
125 private class RowIdentifier {
126 public String primarKeyValue;
127 public StringBuilder rowIdString;
128 @SuppressWarnings("unused")
129 public PreparedQueryObject queryObject;// the string with all the row
130 // identifiers separated by AND
132 public RowIdentifier(String primaryKeyValue, StringBuilder rowIdString,
133 PreparedQueryObject queryObject) {
134 this.primarKeyValue = primaryKeyValue;
135 this.rowIdString = rowIdString;
136 this.queryObject = queryObject;
142 * Create Keyspace REST
145 * @param keyspaceName
151 @ApiOperation(value = "Create Keyspace", response = String.class,hidden = true)
152 @Consumes(MediaType.APPLICATION_JSON)
153 @Produces(MediaType.APPLICATION_JSON)
154 //public Map<String, Object> createKeySpace(
155 public Response createKeySpace(
156 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
157 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
158 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
159 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
160 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
161 @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns,
162 JsonKeySpace kspObject,
163 @ApiParam(value = "Keyspace Name",required = true) @PathParam("name") String keyspaceName) {
165 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
166 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) ");
167 logger.info(EELFLoggerDelegate.applicationLogger,"In Create Keyspace " + keyspaceName);
168 if ( KEYSPACE_ACTIVE ) {
169 logger.info(EELFLoggerDelegate.applicationLogger,"Creating Keyspace " + keyspaceName);
170 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
171 String userId = userCredentials.get(MusicUtil.USERID);
172 String password = userCredentials.get(MusicUtil.PASSWORD);
173 Map<String, Object> authMap = CachingUtil.verifyOnboarding(ns, userId, password);
174 if (!authMap.isEmpty()) {
175 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
176 response.status(Status.UNAUTHORIZED);
177 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
179 if(kspObject == null || kspObject.getReplicationInfo() == null) {
180 response.status(Status.BAD_REQUEST);
181 return response.entity(new JsonResponse(ResultType.FAILURE).setError(ResultType.BODYMISSING.getResult()).toMap()).build();
186 authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspaceName, aid,
188 } catch (Exception e) {
189 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
190 response.status(Status.BAD_REQUEST);
191 return response.entity(new JsonResponse(ResultType.FAILURE).setError("Unable to authenticate.").toMap()).build();
193 String newAid = null;
194 if (!authMap.isEmpty()) {
195 if (authMap.containsKey("aid")) {
196 newAid = (String) authMap.get("aid");
198 logger.error(EELFLoggerDelegate.errorLogger,String.valueOf(authMap.get("Exception")), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
199 response.status(Status.UNAUTHORIZED);
200 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
204 String consistency = MusicUtil.EVENTUAL;// for now this needs only
205 // eventual consistency
207 PreparedQueryObject queryObject = new PreparedQueryObject();
208 if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && kspObject.getConsistencyInfo().get("consistency") != null) {
209 if(MusicUtil.isValidConsistency(kspObject.getConsistencyInfo().get("consistency")))
210 queryObject.setConsistency(kspObject.getConsistencyInfo().get("consistency"));
212 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
214 long start = System.currentTimeMillis();
215 Map<String, Object> replicationInfo = kspObject.getReplicationInfo();
216 String repString = null;
218 repString = "{" + MusicUtil.jsonMaptoSqlString(replicationInfo, ",") + "}";
219 } catch (Exception e) {
220 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
223 queryObject.appendQueryString(
224 "CREATE KEYSPACE " + keyspaceName + " WITH replication = " + repString);
225 if (kspObject.getDurabilityOfWrites() != null) {
226 queryObject.appendQueryString(
227 " AND durable_writes = " + kspObject.getDurabilityOfWrites());
230 queryObject.appendQueryString(";");
231 long end = System.currentTimeMillis();
232 logger.info(EELFLoggerDelegate.applicationLogger,
233 "Time taken for setting up query in create keyspace:" + (end - start));
235 ResultType result = ResultType.FAILURE;
237 result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
238 logger.info(EELFLoggerDelegate.applicationLogger, "result = " + result);
239 } catch ( MusicServiceException ex) {
240 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
241 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("err:" + ex.getMessage()).toMap()).build();
245 queryObject = new PreparedQueryObject();
246 queryObject.appendQueryString("CREATE ROLE IF NOT EXISTS '" + userId
247 + "' WITH PASSWORD = '" + password + "' AND LOGIN = true;");
248 MusicCore.nonKeyRelatedPut(queryObject, consistency);
249 queryObject = new PreparedQueryObject();
250 queryObject.appendQueryString("GRANT ALL PERMISSIONS on KEYSPACE " + keyspaceName
251 + " to '" + userId + "'");
252 queryObject.appendQueryString(";");
253 MusicCore.nonKeyRelatedPut(queryObject, consistency);
254 } catch (Exception e) {
255 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
259 boolean isAAF = Boolean.valueOf(CachingUtil.isAAFApplication(ns));
260 String hashedpwd = BCrypt.hashpw(password, BCrypt.gensalt());
261 queryObject = new PreparedQueryObject();
262 queryObject.appendQueryString(
263 "INSERT into admin.keyspace_master (uuid, keyspace_name, application_name, is_api, "
264 + "password, username, is_aaf) values (?,?,?,?,?,?,?)");
265 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), newAid));
266 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), keyspaceName));
267 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), ns));
268 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "True"));
269 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), hashedpwd));
270 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId));
271 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF));
272 CachingUtil.updateMusicCache(keyspaceName, ns);
273 CachingUtil.updateMusicValidateCache(ns, userId, hashedpwd);
274 MusicCore.eventualPut(queryObject);
275 } catch (Exception e) {
276 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
277 return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
280 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Created").toMap()).build();
282 String vError = "Keyspace Creation no longer supported after versions 3.2.x. Contact DBA to create the keyspace.";
283 logger.info(EELFLoggerDelegate.applicationLogger,vError);
284 logger.error(EELFLoggerDelegate.errorLogger,vError, AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
285 return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(vError).toMap()).build();
288 EELFLoggerDelegate.mdcRemove("keyspace");
296 * @param keyspaceName
302 @ApiOperation(value = "Delete Keyspace", response = String.class,hidden=true)
303 @Produces(MediaType.APPLICATION_JSON)
304 public Response dropKeySpace(
305 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
306 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
307 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
308 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
309 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
310 @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns,
311 @ApiParam(value = "Keyspace Name",required = true) @PathParam("name") String keyspaceName) throws Exception {
313 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
314 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) ");
315 logger.info(EELFLoggerDelegate.applicationLogger,"In Drop Keyspace " + keyspaceName);
316 if ( KEYSPACE_ACTIVE ) {
317 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
318 String userId = userCredentials.get(MusicUtil.USERID);
319 String password = userCredentials.get(MusicUtil.PASSWORD);
320 Map<String, Object> authMap = MusicAuthentication.autheticateUser(ns, userId, password,keyspaceName, aid, "dropKeySpace");
321 if (authMap.containsKey("aid"))
322 authMap.remove("aid");
323 if (!authMap.isEmpty()) {
324 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
325 response.status(Status.UNAUTHORIZED);
326 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
329 String consistency = MusicUtil.EVENTUAL;// for now this needs only
332 String appName = CachingUtil.getAppName(keyspaceName);
333 String uuid = CachingUtil.getUuidFromMusicCache(keyspaceName);
334 PreparedQueryObject pQuery = new PreparedQueryObject();
335 pQuery.appendQueryString(
336 "select count(*) as count from admin.keyspace_master where application_name=? allow filtering;");
337 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName));
338 Row row = MusicCore.get(pQuery).one();
339 long count = row.getLong(0);
342 logger.error(EELFLoggerDelegate.errorLogger,"Keyspace not found. Please make sure keyspace exists.", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
343 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Keyspace not found. Please make sure keyspace exists.").toMap()).build();
345 } else if (count == 1) {
346 pQuery = new PreparedQueryObject();
347 pQuery.appendQueryString(
348 "UPDATE admin.keyspace_master SET keyspace_name=? where uuid = ?;");
349 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(),
350 MusicUtil.DEFAULTKEYSPACENAME));
351 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid));
352 MusicCore.nonKeyRelatedPut(pQuery, consistency);
354 pQuery = new PreparedQueryObject();
355 pQuery.appendQueryString("delete from admin.keyspace_master where uuid = ?");
356 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid));
357 MusicCore.nonKeyRelatedPut(pQuery, consistency);
360 PreparedQueryObject queryObject = new PreparedQueryObject();
361 queryObject.appendQueryString("DROP KEYSPACE " + keyspaceName + ";");
362 ResultType result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
363 if ( result.equals(ResultType.FAILURE) ) {
364 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Error Deleteing Keyspace " + keyspaceName).toMap()).build();
366 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Deleted").toMap()).build();
368 String vError = "Keyspace Droping no longer supported after versions 3.2.x. Contact DBA to drop the keyspace.";
369 logger.info(EELFLoggerDelegate.applicationLogger,vError);
370 logger.error(EELFLoggerDelegate.errorLogger,vError, AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
371 return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(vError).toMap()).build();
374 EELFLoggerDelegate.mdcRemove("keyspace");
389 @Path("/{keyspace: .*}/tables/{tablename: .*}")
390 @ApiOperation(value = "Create Table", response = String.class)
391 @Consumes(MediaType.APPLICATION_JSON)
392 @Produces(MediaType.APPLICATION_JSON)
393 @ApiResponses(value={
394 @ApiResponse(code= 400, message = "Will return JSON response with message"),
395 @ApiResponse(code= 401, message = "Unautorized User")
397 public Response createTable(
398 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
399 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
400 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
401 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
402 @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns,
403 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
405 @ApiParam(value = "Keyspace Name",required = true) @PathParam("keyspace") String keyspace,
406 @ApiParam(value = "Table Name",required = true) @PathParam("tablename") String tablename) throws Exception {
408 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
409 if(keyspace == null || keyspace.isEmpty() || tablename == null || tablename.isEmpty()){
410 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
411 .setError("One or more path parameters are not set, please check and try again."
412 + "Parameter values: keyspace='" + keyspace + "' tablename='" + tablename + "'")
415 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
416 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
417 String userId = userCredentials.get(MusicUtil.USERID);
418 String password = userCredentials.get(MusicUtil.PASSWORD);
419 Map<String, Object> authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspace,
421 if (authMap.containsKey("aid"))
422 authMap.remove("aid");
423 if (!authMap.isEmpty()) {
424 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGINFO ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
425 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
427 String consistency = MusicUtil.EVENTUAL;
428 // for now this needs only eventual consistency
430 String primaryKey = null;
431 String partitionKey = tableObj.getPartitionKey();
432 String clusterKey = tableObj.getClusteringKey();
433 String filteringKey = tableObj.getFilteringKey();
434 if(filteringKey != null) {
435 clusterKey = clusterKey + "," + filteringKey;
437 primaryKey = tableObj.getPrimaryKey(); // get primaryKey if available
439 PreparedQueryObject queryObject = new PreparedQueryObject();
440 // first read the information about the table fields
441 Map<String, String> fields = tableObj.getFields();
442 StringBuilder fieldsString = new StringBuilder("(vector_ts text,");
444 for (Map.Entry<String, String> entry : fields.entrySet()) {
445 if (entry.getKey().equals("PRIMARY KEY")) {
446 primaryKey = entry.getValue(); // replaces primaryKey
447 primaryKey = primaryKey.trim();
449 if (counter == 0 ) fieldsString.append("" + entry.getKey() + " " + entry.getValue() + "");
450 else fieldsString.append("," + entry.getKey() + " " + entry.getValue() + "");
453 if (counter != (fields.size() - 1) ) {
455 counter = counter + 1;
458 if((primaryKey != null) && (partitionKey == null)) {
459 primaryKey = primaryKey.trim();
460 int count1 = StringUtils.countMatches(primaryKey, ')');
461 int count2 = StringUtils.countMatches(primaryKey, '(');
462 if (count1 != count2) {
463 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
464 .setError("Create Table Error: primary key '(' and ')' do not match, primary key=" + primaryKey)
468 if ( primaryKey.indexOf('(') == -1 || ( count2 == 1 && (primaryKey.lastIndexOf(')') +1) == primaryKey.length() ) )
470 if (primaryKey.contains(",") ) {
471 partitionKey= primaryKey.substring(0,primaryKey.indexOf(','));
472 partitionKey=partitionKey.replaceAll("[\\(]+","");
473 clusterKey=primaryKey.substring(primaryKey.indexOf(',')+1); // make sure index
474 clusterKey=clusterKey.replaceAll("[)]+", "");
476 partitionKey=primaryKey;
477 partitionKey=partitionKey.replaceAll("[\\)]+","");
478 partitionKey=partitionKey.replaceAll("[\\(]+","");
481 } else { // not null and has ) before the last char
482 partitionKey= primaryKey.substring(0,primaryKey.indexOf(')'));
483 partitionKey=partitionKey.replaceAll("[\\(]+","");
484 partitionKey = partitionKey.trim();
485 clusterKey= primaryKey.substring(primaryKey.indexOf(')'));
486 clusterKey=clusterKey.replaceAll("[\\(]+","");
487 clusterKey=clusterKey.replaceAll("[\\)]+","");
488 clusterKey = clusterKey.trim();
489 if (clusterKey.indexOf(',') == 0) clusterKey=clusterKey.substring(1);
490 clusterKey = clusterKey.trim();
491 if (clusterKey.equals(",") ) clusterKey=""; // print error if needed ( ... ),)
494 if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
495 && (partitionKey.equalsIgnoreCase(clusterKey) ||
496 clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) )
498 logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey + " and primary key=" + primaryKey );
499 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
500 "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ") of"
501 + " primary key=" + primaryKey)
506 if (partitionKey.isEmpty() ) primaryKey="";
507 else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")";
508 else primaryKey=" (" + partitionKey + ")," + clusterKey;
511 if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
513 } // end of length > 0
515 if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
516 && (partitionKey.equalsIgnoreCase(clusterKey) ||
517 clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) )
519 logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey);
520 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
521 "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ")")
525 if (partitionKey.isEmpty() ) primaryKey="";
526 else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")";
527 else primaryKey=" (" + partitionKey + ")," + clusterKey;
530 if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
532 fieldsString.append(")");
534 } // end of last field check
537 // information about the name-value style properties
538 Map<String, Object> propertiesMap = tableObj.getProperties();
539 StringBuilder propertiesString = new StringBuilder();
540 if (propertiesMap != null) {
542 for (Map.Entry<String, Object> entry : propertiesMap.entrySet()) {
543 Object ot = entry.getValue();
544 String value = ot + "";
545 if (ot instanceof String) {
546 value = "'" + value + "'";
547 } else if (ot instanceof Map) {
548 @SuppressWarnings("unchecked")
549 Map<String, Object> otMap = (Map<String, Object>) ot;
550 value = "{" + MusicUtil.jsonMaptoSqlString(otMap, ",") + "}";
553 propertiesString.append(entry.getKey() + "=" + value + "");
554 if (counter != propertiesMap.size() - 1)
555 propertiesString.append(" AND ");
557 counter = counter + 1;
561 String clusteringOrder = tableObj.getClusteringOrder();
563 if (clusteringOrder != null && !(clusteringOrder.isEmpty())) {
564 String[] arrayClusterOrder = clusteringOrder.split("[,]+");
566 for (int i = 0; i < arrayClusterOrder.length; i++) {
567 String[] clusterS = arrayClusterOrder[i].trim().split("[ ]+");
568 if ( (clusterS.length ==2) && (clusterS[1].equalsIgnoreCase("ASC") || clusterS[1].equalsIgnoreCase("DESC"))) {
571 return response.status(Status.BAD_REQUEST)
572 .entity(new JsonResponse(ResultType.FAILURE)
573 .setError("createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname order; please correct clusteringOrder:"+ clusteringOrder+".")
576 // add validation for column names in cluster key
579 if (!(clusterKey.isEmpty())) {
580 clusteringOrder = "CLUSTERING ORDER BY (" +clusteringOrder +")";
581 //cjc check if propertiesString.length() >0 instead propertiesMap
582 if (propertiesMap != null) {
583 propertiesString.append(" AND "+ clusteringOrder);
585 propertiesString.append(clusteringOrder);
588 logger.warn("Skipping clustering order=("+clusteringOrder+ ") since clustering key is empty ");
592 queryObject.appendQueryString(
593 "CREATE TABLE " + keyspace + "." + tablename + " " + fieldsString);
596 if (propertiesString != null && propertiesString.length()>0 )
597 queryObject.appendQueryString(" WITH " + propertiesString);
598 queryObject.appendQueryString(";");
599 ResultType result = ResultType.FAILURE;
601 result = MusicCore.createTable(keyspace, tablename, queryObject, consistency);
602 } catch (MusicServiceException ex) {
603 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.MUSICSERVICEERROR);
604 response.status(Status.BAD_REQUEST);
605 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
607 if ( result.equals(ResultType.FAILURE) ) {
608 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Error Creating Table " + tablename).toMap()).build();
610 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("TableName " + tablename.trim() + " Created under keyspace " + keyspace.trim()).toMap()).build();
612 EELFLoggerDelegate.mdcRemove("keyspace");
625 @Path("/{keyspace: .*}/tables/{tablename: .*}/index/{field: .*}")
626 @ApiOperation(value = "Create Index", response = String.class)
627 @Produces(MediaType.APPLICATION_JSON)
628 public Response createIndex(
629 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
630 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
631 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
632 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
633 @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns,
634 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
635 @ApiParam(value = "Keyspace Name",required = true) @PathParam("keyspace") String keyspace,
636 @ApiParam(value = "Table Name",required = true) @PathParam("tablename") String tablename,
637 @ApiParam(value = "Field Name",required = true) @PathParam("field") String fieldName,
638 @Context UriInfo info) throws Exception {
640 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
641 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty()) || (fieldName == null || fieldName.isEmpty())){
642 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
643 .setError("one or more path parameters are not set, please check and try again")
646 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
647 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
648 String userId = userCredentials.get(MusicUtil.USERID);
649 String password = userCredentials.get(MusicUtil.PASSWORD);
650 Map<String, Object> authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspace,aid, "createIndex");
651 if (authMap.containsKey("aid"))
652 authMap.remove("aid");
653 if (!authMap.isEmpty()) {
654 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGINFO ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
655 response.status(Status.UNAUTHORIZED);
656 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
658 MultivaluedMap<String, String> rowParams = info.getQueryParameters();
659 String indexName = "";
660 if (rowParams.getFirst("index_name") != null)
661 indexName = rowParams.getFirst("index_name");
662 PreparedQueryObject query = new PreparedQueryObject();
663 query.appendQueryString("Create index if not exists " + indexName + " on " + keyspace + "."
664 + tablename + " (" + fieldName + ");");
666 ResultType result = ResultType.FAILURE;
668 result = MusicCore.nonKeyRelatedPut(query, "eventual");
669 } catch (MusicServiceException ex) {
670 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
671 response.status(Status.BAD_REQUEST);
672 return response.entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
674 if ( result.equals(ResultType.SUCCESS) ) {
675 return response.status(Status.OK).entity(new JsonResponse(result).setMessage("Index Created on " + keyspace+"."+tablename+"."+fieldName).toMap()).build();
677 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Unknown Error in create index.").toMap()).build();
680 EELFLoggerDelegate.mdcRemove("keyspace");
693 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
694 @ApiOperation(value = "Insert Into Table", response = String.class)
695 @Consumes(MediaType.APPLICATION_JSON)
696 @Produces(MediaType.APPLICATION_JSON)
697 public Response insertIntoTable(
698 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
699 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
700 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
701 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
702 @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns,
703 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
705 @ApiParam(value = "Keyspace Name",
706 required = true) @PathParam("keyspace") String keyspace,
707 @ApiParam(value = "Table Name",
708 required = true) @PathParam("tablename") String tablename) {
710 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
711 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
712 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
713 .setError("one or more path parameters are not set, please check and try again")
716 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
717 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
718 String userId = userCredentials.get(MusicUtil.USERID);
719 String password = userCredentials.get(MusicUtil.PASSWORD);
720 Map<String, Object> authMap = null;
723 authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspace,
724 aid, "insertIntoTable");
725 } catch (Exception e) {
726 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGINFO ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
727 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
729 if (authMap.containsKey("aid"))
730 authMap.remove("aid");
731 if (!authMap.isEmpty()) {
732 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGINFO ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
733 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
736 Map<String, Object> valuesMap = insObj.getValues();
737 PreparedQueryObject queryObject = new PreparedQueryObject();
738 TableMetadata tableInfo = null;
740 tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
741 if(tableInfo == null) {
742 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Table name doesn't exists. Please check the table name.").toMap()).build();
744 } catch (MusicServiceException e) {
745 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
746 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
748 String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName();
749 StringBuilder fieldsString = new StringBuilder("(vector_ts,");
751 String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis());
752 StringBuilder valueString = new StringBuilder("(" + "?" + ",");
753 queryObject.addValue(vectorTs);
755 String primaryKey = "";
756 Map<String, byte[]> objectMap = insObj.getObjectMap();
757 for (Map.Entry<String, Object> entry : valuesMap.entrySet()) {
758 fieldsString.append("" + entry.getKey());
759 Object valueObj = entry.getValue();
760 if (primaryKeyName.equals(entry.getKey())) {
761 primaryKey = entry.getValue() + "";
762 primaryKey = primaryKey.replace("'", "''");
764 DataType colType = null;
766 colType = tableInfo.getColumn(entry.getKey()).getType();
767 } catch(NullPointerException ex) {
768 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() +" Invalid column name : "+entry.getKey(), AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
769 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap()).build();
772 Object formattedValue = null;
774 formattedValue = MusicUtil.convertToActualDataType(colType, valueObj);
775 } catch (Exception e) {
776 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
778 valueString.append("?");
780 queryObject.addValue(formattedValue);
782 if (counter == valuesMap.size() - 1) {
783 fieldsString.append(")");
784 valueString.append(")");
786 fieldsString.append(",");
787 valueString.append(",");
789 counter = counter + 1;
793 if(objectMap != null) {
794 for (Map.Entry<String, byte[]> entry : objectMap.entrySet()) {
796 fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ",");
797 valueString.replace(valueString.length()-1, valueString.length(), ",");
799 fieldsString.append("" + entry.getKey());
800 byte[] valueObj = entry.getValue();
801 if (primaryKeyName.equals(entry.getKey())) {
802 primaryKey = entry.getValue() + "";
803 primaryKey = primaryKey.replace("'", "''");
806 DataType colType = tableInfo.getColumn(entry.getKey()).getType();
808 ByteBuffer formattedValue = null;
810 if(colType.toString().toLowerCase().contains("blob"))
811 formattedValue = MusicUtil.convertToActualDataType(colType, valueObj);
813 valueString.append("?");
815 queryObject.addValue(formattedValue);
816 counter = counter + 1;
817 /*if (counter == valuesMap.size() - 1) {
818 fieldsString.append(")");
819 valueString.append(")");
821 fieldsString.append(",");
822 valueString.append(",");
826 if(primaryKey == null || primaryKey.length() <= 0) {
827 logger.error(EELFLoggerDelegate.errorLogger, "Some required partition key parts are missing: "+primaryKeyName );
828 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Some required partition key parts are missing: "+primaryKeyName).toMap()).build();
831 fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ")");
832 valueString.replace(valueString.length()-1, valueString.length(), ")");
834 queryObject.appendQueryString("INSERT INTO " + keyspace + "." + tablename + " "
835 + fieldsString + " VALUES " + valueString);
837 String ttl = insObj.getTtl();
838 String timestamp = insObj.getTimestamp();
840 if ((ttl != null) && (timestamp != null)) {
841 logger.info(EELFLoggerDelegate.applicationLogger, "both there");
842 queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?");
843 queryObject.addValue(Integer.parseInt(ttl));
844 queryObject.addValue(Long.parseLong(timestamp));
847 if ((ttl != null) && (timestamp == null)) {
848 logger.info(EELFLoggerDelegate.applicationLogger, "ONLY TTL there");
849 queryObject.appendQueryString(" USING TTL ?");
850 queryObject.addValue(Integer.parseInt(ttl));
853 if ((ttl == null) && (timestamp != null)) {
854 logger.info(EELFLoggerDelegate.applicationLogger, "ONLY timestamp there");
855 queryObject.appendQueryString(" USING TIMESTAMP ?");
856 queryObject.addValue(Long.parseLong(timestamp));
859 queryObject.appendQueryString(";");
861 ReturnType result = null;
862 String consistency = insObj.getConsistencyInfo().get("type");
863 if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && insObj.getConsistencyInfo().get("consistency") != null) {
864 if(MusicUtil.isValidConsistency(insObj.getConsistencyInfo().get("consistency")))
865 queryObject.setConsistency(insObj.getConsistencyInfo().get("consistency"));
867 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
869 queryObject.setOperation("insert");
871 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) {
872 result = MusicCore.eventualPut(queryObject);
873 } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
874 String lockId = insObj.getConsistencyInfo().get("lockId");
876 logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
877 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
878 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
879 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
881 result = MusicCore.criticalPut(keyspace, tablename, primaryKey, queryObject, lockId,null);
882 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
884 result = MusicCore.atomicPut(keyspace, tablename, primaryKey, queryObject, null);
887 else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) {
888 result = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, primaryKey, queryObject, null);
891 } catch (Exception ex) {
892 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
893 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
897 logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
898 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build();
899 }else if(result.getResult() == ResultType.FAILURE) {
900 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result.getResult()).setError(result.getMessage()).toMap()).build();
902 return response.status(Status.OK).entity(new JsonResponse(result.getResult()).setMessage("Insert Successful").toMap()).build();
904 EELFLoggerDelegate.mdcRemove("keyspace");
915 * @throws MusicServiceException
916 * @throws MusicQueryException
920 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
921 @ApiOperation(value = "Update Table", response = String.class)
922 @Consumes(MediaType.APPLICATION_JSON)
923 @Produces(MediaType.APPLICATION_JSON)
924 public Response updateTable(
925 @ApiParam(value = "Major Version",
926 required = true) @PathParam("version") String version,
927 @ApiParam(value = "Minor Version",
928 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
929 @ApiParam(value = "Patch Version",
930 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
931 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
932 @ApiParam(value = "Application namespace",
933 required = true) @HeaderParam(NS) String ns,
934 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
935 JsonUpdate updateObj,
936 @ApiParam(value = "Keyspace Name",
937 required = true) @PathParam("keyspace") String keyspace,
938 @ApiParam(value = "Table Name",
939 required = true) @PathParam("tablename") String tablename,
940 @Context UriInfo info) throws MusicQueryException, MusicServiceException {
942 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
943 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
944 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
945 .setError("one or more path parameters are not set, please check and try again")
948 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
949 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
950 String userId = userCredentials.get(MusicUtil.USERID);
951 String password = userCredentials.get(MusicUtil.PASSWORD);
952 Map<String, Object> authMap;
954 authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspace,
956 } catch (Exception e) {
957 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
958 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
960 if (authMap.containsKey("aid"))
961 authMap.remove("aid");
962 if (!authMap.isEmpty()) {
963 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
964 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
966 long startTime = System.currentTimeMillis();
967 String operationId = UUID.randomUUID().toString();// just for infoging
969 String consistency = updateObj.getConsistencyInfo().get("type");
971 logger.info(EELFLoggerDelegate.applicationLogger, "--------------Music " + consistency
972 + " update-" + operationId + "-------------------------");
973 // obtain the field value pairs of the update
975 PreparedQueryObject queryObject = new PreparedQueryObject();
976 Map<String, Object> valuesMap = updateObj.getValues();
978 TableMetadata tableInfo;
980 tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
981 } catch (MusicServiceException e) {
982 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
983 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
985 if (tableInfo == null) {
986 logger.error(EELFLoggerDelegate.errorLogger,"Table information not found. Please check input for table name= "+tablename, AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
987 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
988 .setError("Table information not found. Please check input for table name= "
989 + keyspace + "." + tablename).toMap()).build();
992 String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis());
993 StringBuilder fieldValueString = new StringBuilder("vector_ts=?,");
994 queryObject.addValue(vectorTs);
996 for (Map.Entry<String, Object> entry : valuesMap.entrySet()) {
997 Object valueObj = entry.getValue();
998 DataType colType = null;
1000 colType = tableInfo.getColumn(entry.getKey()).getType();
1001 } catch(NullPointerException ex) {
1002 logger.error(EELFLoggerDelegate.errorLogger, "Invalid column name : "+entry.getKey());
1003 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap()).build();
1005 Object valueString = null;
1007 valueString = MusicUtil.convertToActualDataType(colType, valueObj);
1008 } catch (Exception e) {
1009 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
1011 fieldValueString.append(entry.getKey() + "= ?");
1012 queryObject.addValue(valueString);
1013 if (counter != valuesMap.size() - 1)
1014 fieldValueString.append(",");
1015 counter = counter + 1;
1017 String ttl = updateObj.getTtl();
1018 String timestamp = updateObj.getTimestamp();
1020 queryObject.appendQueryString("UPDATE " + keyspace + "." + tablename + " ");
1021 if ((ttl != null) && (timestamp != null)) {
1023 logger.info("both there");
1024 queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?");
1025 queryObject.addValue(Integer.parseInt(ttl));
1026 queryObject.addValue(Long.parseLong(timestamp));
1029 if ((ttl != null) && (timestamp == null)) {
1030 logger.info("ONLY TTL there");
1031 queryObject.appendQueryString(" USING TTL ?");
1032 queryObject.addValue(Integer.parseInt(ttl));
1035 if ((ttl == null) && (timestamp != null)) {
1036 logger.info("ONLY timestamp there");
1037 queryObject.appendQueryString(" USING TIMESTAMP ?");
1038 queryObject.addValue(Long.parseLong(timestamp));
1040 // get the row specifier
1041 RowIdentifier rowId = null;
1043 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
1044 if(rowId == null || rowId.primarKeyValue.isEmpty()) {
1045 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1046 .setError("Mandatory WHERE clause is missing. Please check the input request.").toMap()).build();
1048 } catch (MusicServiceException ex) {
1049 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1050 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1053 queryObject.appendQueryString(
1054 " SET " + fieldValueString + " WHERE " + rowId.rowIdString + ";");
1056 // get the conditional, if any
1057 Condition conditionInfo;
1058 if (updateObj.getConditions() == null)
1059 conditionInfo = null;
1060 else {// to avoid parsing repeatedly, just send the select query to
1062 PreparedQueryObject selectQuery = new PreparedQueryObject();
1063 selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE "
1064 + rowId.rowIdString + ";");
1065 selectQuery.addValue(rowId.primarKeyValue);
1066 conditionInfo = new Condition(updateObj.getConditions(), selectQuery);
1069 ReturnType operationResult = null;
1070 long jsonParseCompletionTime = System.currentTimeMillis();
1072 if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && updateObj.getConsistencyInfo().get("consistency") != null) {
1073 if(MusicUtil.isValidConsistency(updateObj.getConsistencyInfo().get("consistency")))
1074 queryObject.setConsistency(updateObj.getConsistencyInfo().get("consistency"));
1076 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
1078 queryObject.setOperation("update");
1079 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL))
1080 operationResult = MusicCore.eventualPut(queryObject);
1081 else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
1082 String lockId = updateObj.getConsistencyInfo().get("lockId");
1083 if(lockId == null) {
1084 logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
1085 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
1086 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
1087 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
1089 operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue,
1090 queryObject, lockId, conditionInfo);
1091 } else if (consistency.equalsIgnoreCase("atomic_delete_lock")) {
1092 // this function is mainly for the benchmarks
1094 operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename,
1095 rowId.primarKeyValue, queryObject, conditionInfo);
1096 } catch (MusicLockingException e) {
1097 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1098 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
1100 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
1102 operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue,
1103 queryObject, conditionInfo);
1104 } catch (MusicLockingException e) {
1105 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1106 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
1108 }else if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) {
1109 operationResult = MusicCore.eventualPut_nb(queryObject, keyspace, tablename, rowId.primarKeyValue);
1111 long actualUpdateCompletionTime = System.currentTimeMillis();
1113 long endTime = System.currentTimeMillis();
1114 String timingString = "Time taken in ms for Music " + consistency + " update-" + operationId
1115 + ":" + "|total operation time:" + (endTime - startTime)
1116 + "|json parsing time:" + (jsonParseCompletionTime - startTime)
1117 + "|update time:" + (actualUpdateCompletionTime - jsonParseCompletionTime)
1120 if (operationResult != null && operationResult.getTimingInfo() != null) {
1121 String lockManagementTime = operationResult.getTimingInfo();
1122 timingString = timingString + lockManagementTime;
1124 logger.info(EELFLoggerDelegate.applicationLogger, timingString);
1126 if (operationResult==null) {
1127 logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1128 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build();
1130 if ( operationResult.getResult() == ResultType.SUCCESS ) {
1131 return response.status(Status.OK).entity(new JsonResponse(operationResult.getResult()).setMessage(operationResult.getMessage()).toMap()).build();
1133 logger.error(EELFLoggerDelegate.errorLogger,operationResult.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1134 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(operationResult.getResult()).setError(operationResult.getMessage()).toMap()).build();
1137 EELFLoggerDelegate.mdcRemove("keyspace");
1148 * @throws MusicServiceException
1149 * @throws MusicQueryException
1153 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
1154 @ApiOperation(value = "Delete From table", response = String.class)
1155 @Consumes(MediaType.APPLICATION_JSON)
1156 @Produces(MediaType.APPLICATION_JSON)
1157 public Response deleteFromTable(
1158 @ApiParam(value = "Major Version",
1159 required = true) @PathParam("version") String version,
1160 @ApiParam(value = "Minor Version",
1161 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1162 @ApiParam(value = "Patch Version",
1163 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1164 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
1165 @ApiParam(value = "Application namespace",
1166 required = true) @HeaderParam(NS) String ns,
1167 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1169 @ApiParam(value = "Keyspace Name",
1170 required = true) @PathParam("keyspace") String keyspace,
1171 @ApiParam(value = "Table Name",
1172 required = true) @PathParam("tablename") String tablename,
1173 @Context UriInfo info) throws MusicQueryException, MusicServiceException {
1175 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1176 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1177 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1178 .setError("one or more path parameters are not set, please check and try again")
1181 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
1182 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
1183 String userId = userCredentials.get(MusicUtil.USERID);
1184 String password = userCredentials.get(MusicUtil.PASSWORD);
1185 Map<String, Object> authMap = null;
1187 authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspace,
1188 aid, "deleteFromTable");
1189 } catch (Exception e) {
1190 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
1191 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
1193 if (authMap.containsKey("aid"))
1194 authMap.remove("aid");
1195 if (!authMap.isEmpty()) {
1196 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
1197 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
1199 if(delObj == null) {
1200 logger.error(EELFLoggerDelegate.errorLogger,"Required HTTP Request body is missing.", AppMessages.MISSINGDATA ,ErrorSeverity.WARN, ErrorTypes.DATAERROR);
1201 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Required HTTP Request body is missing.").toMap()).build();
1203 PreparedQueryObject queryObject = new PreparedQueryObject();
1204 StringBuilder columnString = new StringBuilder();
1207 ArrayList<String> columnList = delObj.getColumns();
1208 if (columnList != null) {
1209 for (String column : columnList) {
1210 columnString.append(column);
1211 if (counter != columnList.size() - 1)
1212 columnString.append(",");
1213 counter = counter + 1;
1217 // get the row specifier
1218 RowIdentifier rowId = null;
1220 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
1221 } catch (MusicServiceException ex) {
1222 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1223 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1225 String rowSpec = rowId.rowIdString.toString();
1227 if ((columnList != null) && (!rowSpec.isEmpty())) {
1228 queryObject.appendQueryString("DELETE " + columnString + " FROM " + keyspace + "."
1229 + tablename + " WHERE " + rowSpec + ";");
1232 if ((columnList == null) && (!rowSpec.isEmpty())) {
1233 queryObject.appendQueryString("DELETE FROM " + keyspace + "." + tablename + " WHERE "
1237 if ((columnList != null) && (rowSpec.isEmpty())) {
1238 queryObject.appendQueryString(
1239 "DELETE " + columnString + " FROM " + keyspace + "." + rowSpec + ";");
1241 // get the conditional, if any
1242 Condition conditionInfo;
1243 if (delObj.getConditions() == null)
1244 conditionInfo = null;
1245 else {// to avoid parsing repeatedly, just send the select query to
1247 PreparedQueryObject selectQuery = new PreparedQueryObject();
1248 selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE "
1249 + rowId.rowIdString + ";");
1250 selectQuery.addValue(rowId.primarKeyValue);
1251 conditionInfo = new Condition(delObj.getConditions(), selectQuery);
1254 String consistency = delObj.getConsistencyInfo().get("type");
1257 if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && delObj.getConsistencyInfo().get("consistency")!=null) {
1259 if(MusicUtil.isValidConsistency(delObj.getConsistencyInfo().get("consistency")))
1260 queryObject.setConsistency(delObj.getConsistencyInfo().get("consistency"));
1262 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
1265 ReturnType operationResult = null;
1266 queryObject.setOperation("delete");
1268 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL))
1269 operationResult = MusicCore.eventualPut(queryObject);
1270 else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
1271 String lockId = delObj.getConsistencyInfo().get("lockId");
1272 if(lockId == null) {
1273 logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
1274 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
1275 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
1276 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
1278 operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue,
1279 queryObject, lockId, conditionInfo);
1280 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
1281 operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue,
1282 queryObject, conditionInfo);
1284 else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) {
1285 operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, rowId.primarKeyValue,
1286 queryObject, conditionInfo);
1287 }else if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) {
1289 operationResult = MusicCore.eventualPut_nb(queryObject, keyspace, tablename, rowId.primarKeyValue);
1291 } catch (MusicLockingException e) {
1292 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1293 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1294 .setError("Unable to perform Delete operation. Exception from music").toMap()).build();
1296 if (operationResult==null) {
1297 logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1298 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build();
1300 if (operationResult.getResult().equals(ResultType.SUCCESS)) {
1301 return response.status(Status.OK).entity(new JsonResponse(operationResult.getResult()).setMessage(operationResult.getMessage()).toMap()).build();
1303 logger.error(EELFLoggerDelegate.errorLogger,operationResult.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1304 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(operationResult.getMessage()).toMap()).build();
1307 EELFLoggerDelegate.mdcRemove("keyspace");
1319 @Path("/{keyspace: .*}/tables/{tablename: .*}")
1320 @ApiOperation(value = "Drop Table", response = String.class)
1321 @Produces(MediaType.APPLICATION_JSON)
1322 public Response dropTable(
1323 @ApiParam(value = "Major Version",
1324 required = true) @PathParam("version") String version,
1325 @ApiParam(value = "Minor Version",
1326 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1327 @ApiParam(value = "Patch Version",
1328 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1329 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
1330 @ApiParam(value = "Application namespace",
1331 required = true) @HeaderParam(NS) String ns,
1332 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1333 @ApiParam(value = "Keyspace Name",
1334 required = true) @PathParam("keyspace") String keyspace,
1335 @ApiParam(value = "Table Name",
1336 required = true) @PathParam("tablename") String tablename) throws Exception {
1338 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1339 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1340 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1341 .setError("one or more path parameters are not set, please check and try again")
1344 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
1345 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
1346 String userId = userCredentials.get(MusicUtil.USERID);
1347 String password = userCredentials.get(MusicUtil.PASSWORD);
1348 Map<String, Object> authMap =
1349 MusicAuthentication.autheticateUser(ns, userId, password, keyspace, aid, "dropTable");
1350 if (authMap.containsKey("aid"))
1351 authMap.remove("aid");
1352 if (!authMap.isEmpty()) {
1353 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
1354 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
1356 String consistency = "eventual";// for now this needs only eventual
1358 PreparedQueryObject query = new PreparedQueryObject();
1359 query.appendQueryString("DROP TABLE " + keyspace + "." + tablename + ";");
1361 return response.status(Status.OK).entity(new JsonResponse(MusicCore.nonKeyRelatedPut(query, consistency)).toMap()).build();
1362 } catch (MusicServiceException ex) {
1363 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1364 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1367 EELFLoggerDelegate.mdcRemove("keyspace");
1380 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows/criticalget")
1381 @ApiOperation(value = "Select Critical", response = Map.class)
1382 @Consumes(MediaType.APPLICATION_JSON)
1383 @Produces(MediaType.APPLICATION_JSON)
1384 public Response selectCritical(
1385 @ApiParam(value = "Major Version",
1386 required = true) @PathParam("version") String version,
1387 @ApiParam(value = "Minor Version",
1388 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1389 @ApiParam(value = "Patch Version",
1390 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1391 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
1392 @ApiParam(value = "Application namespace",
1393 required = true) @HeaderParam(NS) String ns,
1394 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1396 @ApiParam(value = "Keyspace Name",
1397 required = true) @PathParam("keyspace") String keyspace,
1398 @ApiParam(value = "Table Name",
1399 required = true) @PathParam("tablename") String tablename,
1400 @Context UriInfo info) throws Exception {
1402 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1403 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1404 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1405 .setError("one or more path parameters are not set, please check and try again")
1408 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
1409 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
1410 String userId = userCredentials.get(MusicUtil.USERID);
1411 String password = userCredentials.get(MusicUtil.PASSWORD);
1412 Map<String, Object> authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspace,aid, "selectCritical");
1413 if (authMap.containsKey("aid"))
1414 authMap.remove("aid");
1415 if (!authMap.isEmpty()) {
1416 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
1417 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
1419 String lockId = selObj.getConsistencyInfo().get("lockId");
1421 PreparedQueryObject queryObject = new PreparedQueryObject();
1423 RowIdentifier rowId = null;
1425 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
1426 } catch (MusicServiceException ex) {
1427 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1428 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1430 queryObject.appendQueryString(
1431 "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowId.rowIdString + ";");
1433 ResultSet results = null;
1435 String consistency = selObj.getConsistencyInfo().get("type");
1437 if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
1438 if(lockId == null) {
1439 logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
1440 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
1441 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
1442 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
1444 results = MusicCore.criticalGet(keyspace, tablename, rowId.primarKeyValue, queryObject,
1446 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
1447 results = MusicCore.atomicGet(keyspace, tablename, rowId.primarKeyValue, queryObject);
1450 else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) {
1451 results = MusicCore.atomicGetWithDeleteLock(keyspace, tablename, rowId.primarKeyValue, queryObject);
1453 if(results!=null && results.getAvailableWithoutFetching() >0) {
1454 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build();
1456 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setError("No data found").toMap()).build();
1459 EELFLoggerDelegate.mdcRemove("keyspace");
1472 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
1473 @ApiOperation(value = "Select All or Select Specific", response = Map.class)
1474 @Produces(MediaType.APPLICATION_JSON)
1475 public Response select(
1476 @ApiParam(value = "Major Version",
1477 required = true) @PathParam("version") String version,
1478 @ApiParam(value = "Minor Version",
1479 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1480 @ApiParam(value = "Patch Version",
1481 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1482 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
1483 @ApiParam(value = "Application namespace",
1484 required = true) @HeaderParam(NS) String ns,
1485 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1486 @ApiParam(value = "Keyspace Name",
1487 required = true) @PathParam("keyspace") String keyspace,
1488 @ApiParam(value = "Table Name",
1489 required = true) @PathParam("tablename") String tablename,
1490 @Context UriInfo info) throws Exception {
1492 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1493 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1494 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1495 .setError("one or more path parameters are not set, please check and try again")
1498 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
1499 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
1500 String userId = userCredentials.get(MusicUtil.USERID);
1501 String password = userCredentials.get(MusicUtil.PASSWORD);
1502 Map<String, Object> authMap =
1503 MusicAuthentication.autheticateUser(ns, userId, password, keyspace, aid, "select");
1504 if (authMap.containsKey("aid"))
1505 authMap.remove("aid");
1506 if (!authMap.isEmpty()) {
1507 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
1508 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
1510 PreparedQueryObject queryObject = new PreparedQueryObject();
1512 if (info.getQueryParameters().isEmpty())// select all
1513 queryObject.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + ";");
1515 int limit = -1; // do not limit the number of results
1517 queryObject = selectSpecificQuery(VERSION, minorVersion, patchVersion, aid, ns,
1518 userId, password, keyspace, tablename, info, limit);
1519 } catch (MusicServiceException ex) {
1520 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1521 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1526 ResultSet results = MusicCore.get(queryObject);
1527 if(results.getAvailableWithoutFetching() >0) {
1528 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build();
1530 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).setError("No data found").toMap()).build();
1531 } catch (MusicServiceException ex) {
1532 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.ERROR, ErrorTypes.MUSICSERVICEERROR);
1533 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1536 EELFLoggerDelegate.mdcRemove("keyspace");
1547 * @throws MusicServiceException
1549 public PreparedQueryObject selectSpecificQuery(String version, String minorVersion,
1550 String patchVersion, String aid, String ns, String userId, String password,
1551 String keyspace, String tablename, UriInfo info, int limit)
1552 throws MusicServiceException {
1554 PreparedQueryObject queryObject = new PreparedQueryObject();
1555 StringBuilder rowIdString = getRowIdentifier(keyspace, tablename, info.getQueryParameters(),
1556 queryObject).rowIdString;
1558 queryObject.appendQueryString(
1559 "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowIdString);
1562 queryObject.appendQueryString(" LIMIT " + limit);
1565 queryObject.appendQueryString(";");
1575 * @param queryObject
1577 * @throws MusicServiceException
1579 private RowIdentifier getRowIdentifier(String keyspace, String tablename,
1580 MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject)
1581 throws MusicServiceException {
1582 StringBuilder rowSpec = new StringBuilder();
1584 TableMetadata tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
1585 if (tableInfo == null) {
1586 logger.error(EELFLoggerDelegate.errorLogger,
1587 "Table information not found. Please check input for table name= "
1588 + keyspace + "." + tablename);
1589 throw new MusicServiceException(
1590 "Table information not found. Please check input for table name= "
1591 + keyspace + "." + tablename);
1593 StringBuilder primaryKey = new StringBuilder();
1594 for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) {
1595 String keyName = entry.getKey();
1596 List<String> valueList = entry.getValue();
1597 String indValue = valueList.get(0);
1598 DataType colType = null;
1599 Object formattedValue = null;
1601 colType = tableInfo.getColumn(entry.getKey()).getType();
1602 formattedValue = MusicUtil.convertToActualDataType(colType, indValue);
1603 } catch (Exception e) {
1604 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
1606 if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey()))
1607 primaryKey.append(indValue);
1608 rowSpec.append(keyName + "= ?");
1609 queryObject.addValue(formattedValue);
1610 if (counter != rowParams.size() - 1)
1611 rowSpec.append(" AND ");
1612 counter = counter + 1;
1614 return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject);