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.List;
30 import java.util.UUID;
32 import javax.ws.rs.Consumes;
33 import javax.ws.rs.DELETE;
34 import javax.ws.rs.GET;
35 import javax.ws.rs.HeaderParam;
36 import javax.ws.rs.POST;
37 import javax.ws.rs.PUT;
38 import javax.ws.rs.Path;
39 import javax.ws.rs.PathParam;
40 import javax.ws.rs.Produces;
41 import javax.ws.rs.core.Context;
42 import javax.ws.rs.core.MediaType;
43 import javax.ws.rs.core.MultivaluedMap;
44 import javax.ws.rs.core.Response;
45 import javax.ws.rs.core.Response.ResponseBuilder;
46 import javax.ws.rs.core.Response.Status;
47 import javax.ws.rs.core.UriInfo;
49 import org.apache.commons.lang3.StringUtils;
50 import org.mindrot.jbcrypt.BCrypt;
51 import org.onap.music.authentication.MusicAuthentication;
52 import org.onap.music.datastore.PreparedQueryObject;
53 import org.onap.music.datastore.jsonobjects.JsonDelete;
54 import org.onap.music.datastore.jsonobjects.JsonInsert;
55 import org.onap.music.datastore.jsonobjects.JsonKeySpace;
56 import org.onap.music.datastore.jsonobjects.JsonTable;
57 import org.onap.music.datastore.jsonobjects.JsonUpdate;
58 import org.onap.music.eelf.logging.EELFLoggerDelegate;
59 import org.onap.music.exceptions.MusicLockingException;
60 import org.onap.music.exceptions.MusicQueryException;
61 import org.onap.music.eelf.logging.format.AppMessages;
62 import org.onap.music.eelf.logging.format.ErrorSeverity;
63 import org.onap.music.eelf.logging.format.ErrorTypes;
64 import org.onap.music.exceptions.MusicServiceException;
65 import org.onap.music.main.CachingUtil;
66 import org.onap.music.main.MusicCore;
67 import org.onap.music.datastore.Condition;
68 import org.onap.music.datastore.MusicDataStoreHandle;
69 import org.onap.music.main.MusicUtil;
70 import org.onap.music.main.ResultType;
71 import org.onap.music.main.ReturnType;
72 import org.onap.music.response.jsonobjects.JsonResponse;
74 import com.datastax.driver.core.DataType;
75 import com.datastax.driver.core.ResultSet;
76 import com.datastax.driver.core.Row;
77 import com.datastax.driver.core.TableMetadata;
79 import io.swagger.annotations.Api;
80 import io.swagger.annotations.ApiOperation;
81 import io.swagger.annotations.ApiParam;
82 import io.swagger.annotations.ApiResponses;
83 import io.swagger.annotations.ApiResponse;
86 //@Path("/v{version: [0-9]+}/keyspaces")
87 @Path("/v2/keyspaces")
88 @Api(value = "Data Api")
89 public class RestMusicDataAPI {
91 * Header values for Versioning X-minorVersion *** - Used to request or communicate a MINOR
92 * version back from the client to the server, and from the server back to the client - This
93 * will be the MINOR version requested by the client, or the MINOR version of the last MAJOR
94 * version (if not specified by the client on the request) - Contains a single position value
95 * (e.g. if the full version is 1.24.5, X-minorVersion = "24") - Is optional for the client on
96 * request; however, this header should be provided if the client needs to take advantage of
97 * MINOR incremented version functionality - Is mandatory for the server on response
99 *** X-patchVersion *** - Used only to communicate a PATCH version in a response for
100 * troubleshooting purposes only, and will not be provided by the client on request - This will
101 * be the latest PATCH version of the MINOR requested by the client, or the latest PATCH version
102 * of the MAJOR (if not specified by the client on the request) - Contains a single position
103 * value (e.g. if the full version is 1.24.5, X-patchVersion = "5") - Is mandatory for the
104 * server on response (CURRENTLY NOT USED)
106 *** X-latestVersion *** - Used only to communicate an API's latest version - Is mandatory for the
107 * server on response, and shall include the entire version of the API (e.g. if the full version
108 * is 1.24.5, X-latestVersion = "1.24.5") - Used in the response to inform clients that they are
109 * not using the latest version of the API (CURRENTLY NOT USED)
113 private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicDataAPI.class);
114 private static final String XMINORVERSION = "X-minorVersion";
115 private static final String XPATCHVERSION = "X-patchVersion";
116 private static final String NS = "ns";
117 private static final String VERSION = "v2";
118 // Set to true in env like ONAP. Where access to creating and dropping keyspaces exist.
119 private static final boolean KEYSPACE_ACTIVE = false;
121 private class RowIdentifier {
122 public String primarKeyValue;
123 public StringBuilder rowIdString;
124 @SuppressWarnings("unused")
125 public PreparedQueryObject queryObject;// the string with all the row
126 // identifiers separated by AND
128 public RowIdentifier(String primaryKeyValue, StringBuilder rowIdString,
129 PreparedQueryObject queryObject) {
130 this.primarKeyValue = primaryKeyValue;
131 this.rowIdString = rowIdString;
132 this.queryObject = queryObject;
138 * Create Keyspace REST
141 * @param keyspaceName
147 @ApiOperation(value = "Create Keyspace", response = String.class,hidden = true)
148 @Consumes(MediaType.APPLICATION_JSON)
149 @Produces(MediaType.APPLICATION_JSON)
150 //public Map<String, Object> createKeySpace(
151 public Response createKeySpace(
152 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
153 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
154 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
155 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
156 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
157 @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns,
158 JsonKeySpace kspObject,
159 @ApiParam(value = "Keyspace Name",required = true) @PathParam("name") String keyspaceName) {
161 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
162 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) ");
163 logger.info(EELFLoggerDelegate.applicationLogger,"In Create Keyspace " + keyspaceName);
164 if ( KEYSPACE_ACTIVE ) {
165 logger.info(EELFLoggerDelegate.applicationLogger,"Creating Keyspace " + keyspaceName);
166 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
167 String userId = userCredentials.get(MusicUtil.USERID);
168 String password = userCredentials.get(MusicUtil.PASSWORD);
169 Map<String, Object> authMap = CachingUtil.verifyOnboarding(ns, userId, password);
170 if (!authMap.isEmpty()) {
171 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
172 response.status(Status.UNAUTHORIZED);
173 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
175 if(kspObject == null || kspObject.getReplicationInfo() == null) {
176 response.status(Status.BAD_REQUEST);
177 return response.entity(new JsonResponse(ResultType.FAILURE).setError(ResultType.BODYMISSING.getResult()).toMap()).build();
182 authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspaceName, aid,
184 } catch (Exception e) {
185 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
186 response.status(Status.BAD_REQUEST);
187 return response.entity(new JsonResponse(ResultType.FAILURE).setError("Unable to authenticate.").toMap()).build();
189 String newAid = null;
190 if (!authMap.isEmpty()) {
191 if (authMap.containsKey("aid")) {
192 newAid = (String) authMap.get("aid");
194 logger.error(EELFLoggerDelegate.errorLogger,String.valueOf(authMap.get("Exception")), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
195 response.status(Status.UNAUTHORIZED);
196 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
200 String consistency = MusicUtil.EVENTUAL;// for now this needs only
201 // eventual consistency
203 PreparedQueryObject queryObject = new PreparedQueryObject();
204 if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && kspObject.getConsistencyInfo().get("consistency") != null) {
205 if(MusicUtil.isValidConsistency(kspObject.getConsistencyInfo().get("consistency")))
206 queryObject.setConsistency(kspObject.getConsistencyInfo().get("consistency"));
208 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
210 long start = System.currentTimeMillis();
211 Map<String, Object> replicationInfo = kspObject.getReplicationInfo();
212 String repString = null;
214 repString = "{" + MusicUtil.jsonMaptoSqlString(replicationInfo, ",") + "}";
215 } catch (Exception e) {
216 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
219 queryObject.appendQueryString(
220 "CREATE KEYSPACE " + keyspaceName + " WITH replication = " + repString);
221 if (kspObject.getDurabilityOfWrites() != null) {
222 queryObject.appendQueryString(
223 " AND durable_writes = " + kspObject.getDurabilityOfWrites());
226 queryObject.appendQueryString(";");
227 long end = System.currentTimeMillis();
228 logger.info(EELFLoggerDelegate.applicationLogger,
229 "Time taken for setting up query in create keyspace:" + (end - start));
231 ResultType result = ResultType.FAILURE;
233 result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
234 logger.info(EELFLoggerDelegate.applicationLogger, "result = " + result);
235 } catch ( MusicServiceException ex) {
236 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
237 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("err:" + ex.getMessage()).toMap()).build();
241 queryObject = new PreparedQueryObject();
242 queryObject.appendQueryString("CREATE ROLE IF NOT EXISTS '" + userId
243 + "' WITH PASSWORD = '" + password + "' AND LOGIN = true;");
244 MusicCore.nonKeyRelatedPut(queryObject, consistency);
245 queryObject = new PreparedQueryObject();
246 queryObject.appendQueryString("GRANT ALL PERMISSIONS on KEYSPACE " + keyspaceName
247 + " to '" + userId + "'");
248 queryObject.appendQueryString(";");
249 MusicCore.nonKeyRelatedPut(queryObject, consistency);
250 } catch (Exception e) {
251 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
255 boolean isAAF = Boolean.valueOf(CachingUtil.isAAFApplication(ns));
256 String hashedpwd = BCrypt.hashpw(password, BCrypt.gensalt());
257 queryObject = new PreparedQueryObject();
258 queryObject.appendQueryString(
259 "INSERT into admin.keyspace_master (uuid, keyspace_name, application_name, is_api, "
260 + "password, username, is_aaf) values (?,?,?,?,?,?,?)");
261 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), newAid));
262 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), keyspaceName));
263 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), ns));
264 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "True"));
265 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), hashedpwd));
266 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId));
267 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF));
268 CachingUtil.updateMusicCache(keyspaceName, ns);
269 CachingUtil.updateMusicValidateCache(ns, userId, hashedpwd);
270 MusicCore.eventualPut(queryObject);
271 } catch (Exception e) {
272 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
273 return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
276 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Created").toMap()).build();
278 String vError = "Keyspace Creation no longer supported after versions 3.2.x. Contact DBA to create the keyspace.";
279 logger.info(EELFLoggerDelegate.applicationLogger,vError);
280 logger.error(EELFLoggerDelegate.errorLogger,vError, AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
281 return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(vError).toMap()).build();
284 EELFLoggerDelegate.mdcRemove("keyspace");
292 * @param keyspaceName
298 @ApiOperation(value = "Delete Keyspace", response = String.class,hidden=true)
299 @Produces(MediaType.APPLICATION_JSON)
300 public Response dropKeySpace(
301 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
302 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
303 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
304 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
305 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
306 @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns,
307 @ApiParam(value = "Keyspace Name",required = true) @PathParam("name") String keyspaceName) throws Exception {
309 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
310 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) ");
311 logger.info(EELFLoggerDelegate.applicationLogger,"In Drop Keyspace " + keyspaceName);
312 if ( KEYSPACE_ACTIVE ) {
313 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
314 String userId = userCredentials.get(MusicUtil.USERID);
315 String password = userCredentials.get(MusicUtil.PASSWORD);
316 Map<String, Object> authMap = MusicAuthentication.autheticateUser(ns, userId, password,keyspaceName, aid, "dropKeySpace");
317 if (authMap.containsKey("aid"))
318 authMap.remove("aid");
319 if (!authMap.isEmpty()) {
320 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
321 response.status(Status.UNAUTHORIZED);
322 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
325 String consistency = MusicUtil.EVENTUAL;// for now this needs only
328 String appName = CachingUtil.getAppName(keyspaceName);
329 String uuid = CachingUtil.getUuidFromMusicCache(keyspaceName);
330 PreparedQueryObject pQuery = new PreparedQueryObject();
331 pQuery.appendQueryString(
332 "select count(*) as count from admin.keyspace_master where application_name=? allow filtering;");
333 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName));
334 Row row = MusicCore.get(pQuery).one();
335 long count = row.getLong(0);
338 logger.error(EELFLoggerDelegate.errorLogger,"Keyspace not found. Please make sure keyspace exists.", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
339 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Keyspace not found. Please make sure keyspace exists.").toMap()).build();
341 } else if (count == 1) {
342 pQuery = new PreparedQueryObject();
343 pQuery.appendQueryString(
344 "UPDATE admin.keyspace_master SET keyspace_name=? where uuid = ?;");
345 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(),
346 MusicUtil.DEFAULTKEYSPACENAME));
347 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid));
348 MusicCore.nonKeyRelatedPut(pQuery, consistency);
350 pQuery = new PreparedQueryObject();
351 pQuery.appendQueryString("delete from admin.keyspace_master where uuid = ?");
352 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid));
353 MusicCore.nonKeyRelatedPut(pQuery, consistency);
356 PreparedQueryObject queryObject = new PreparedQueryObject();
357 queryObject.appendQueryString("DROP KEYSPACE " + keyspaceName + ";");
358 ResultType result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
359 if ( result.equals(ResultType.FAILURE) ) {
360 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Error Deleteing Keyspace " + keyspaceName).toMap()).build();
362 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Deleted").toMap()).build();
364 String vError = "Keyspace Droping no longer supported after versions 3.2.x. Contact DBA to drop the keyspace.";
365 logger.info(EELFLoggerDelegate.applicationLogger,vError);
366 logger.error(EELFLoggerDelegate.errorLogger,vError, AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
367 return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(vError).toMap()).build();
370 EELFLoggerDelegate.mdcRemove("keyspace");
385 @Path("/{keyspace: .*}/tables/{tablename: .*}")
386 @ApiOperation(value = "Create Table", response = String.class)
387 @Consumes(MediaType.APPLICATION_JSON)
388 @Produces(MediaType.APPLICATION_JSON)
389 @ApiResponses(value={
390 @ApiResponse(code= 400, message = "Will return JSON response with message"),
391 @ApiResponse(code= 401, message = "Unautorized User")
393 public Response createTable(
394 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
395 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
396 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
397 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
398 @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns,
399 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
401 @ApiParam(value = "Keyspace Name",required = true) @PathParam("keyspace") String keyspace,
402 @ApiParam(value = "Table Name",required = true) @PathParam("tablename") String tablename) throws Exception {
404 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
405 if(keyspace == null || keyspace.isEmpty() || tablename == null || tablename.isEmpty()){
406 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
407 .setError("One or more path parameters are not set, please check and try again."
408 + "Parameter values: keyspace='" + keyspace + "' tablename='" + tablename + "'")
411 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
412 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
413 String userId = userCredentials.get(MusicUtil.USERID);
414 String password = userCredentials.get(MusicUtil.PASSWORD);
415 Map<String, Object> authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspace,
417 if (authMap.containsKey("aid"))
418 authMap.remove("aid");
419 if (!authMap.isEmpty()) {
420 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGINFO ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
421 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
423 String consistency = MusicUtil.EVENTUAL;
424 // for now this needs only eventual consistency
426 String primaryKey = null;
427 String partitionKey = tableObj.getPartitionKey();
428 String clusterKey = tableObj.getClusteringKey();
429 String filteringKey = tableObj.getFilteringKey();
430 if(filteringKey != null) {
431 clusterKey = clusterKey + "," + filteringKey;
433 primaryKey = tableObj.getPrimaryKey(); // get primaryKey if available
435 PreparedQueryObject queryObject = new PreparedQueryObject();
436 // first read the information about the table fields
437 Map<String, String> fields = tableObj.getFields();
438 StringBuilder fieldsString = new StringBuilder("(vector_ts text,");
440 for (Map.Entry<String, String> entry : fields.entrySet()) {
441 if (entry.getKey().equals("PRIMARY KEY")) {
442 primaryKey = entry.getValue(); // replaces primaryKey
443 primaryKey = primaryKey.trim();
445 if (counter == 0 ) fieldsString.append("" + entry.getKey() + " " + entry.getValue() + "");
446 else fieldsString.append("," + entry.getKey() + " " + entry.getValue() + "");
449 if (counter != (fields.size() - 1) ) {
451 counter = counter + 1;
454 if((primaryKey != null) && (partitionKey == null)) {
455 primaryKey = primaryKey.trim();
456 int count1 = StringUtils.countMatches(primaryKey, ')');
457 int count2 = StringUtils.countMatches(primaryKey, '(');
458 if (count1 != count2) {
459 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
460 .setError("Create Table Error: primary key '(' and ')' do not match, primary key=" + primaryKey)
464 if ( primaryKey.indexOf('(') == -1 || ( count2 == 1 && (primaryKey.lastIndexOf(')') +1) == primaryKey.length() ) )
466 if (primaryKey.contains(",") ) {
467 partitionKey= primaryKey.substring(0,primaryKey.indexOf(','));
468 partitionKey=partitionKey.replaceAll("[\\(]+","");
469 clusterKey=primaryKey.substring(primaryKey.indexOf(',')+1); // make sure index
470 clusterKey=clusterKey.replaceAll("[)]+", "");
472 partitionKey=primaryKey;
473 partitionKey=partitionKey.replaceAll("[\\)]+","");
474 partitionKey=partitionKey.replaceAll("[\\(]+","");
477 } else { // not null and has ) before the last char
478 partitionKey= primaryKey.substring(0,primaryKey.indexOf(')'));
479 partitionKey=partitionKey.replaceAll("[\\(]+","");
480 partitionKey = partitionKey.trim();
481 clusterKey= primaryKey.substring(primaryKey.indexOf(')'));
482 clusterKey=clusterKey.replaceAll("[\\(]+","");
483 clusterKey=clusterKey.replaceAll("[\\)]+","");
484 clusterKey = clusterKey.trim();
485 if (clusterKey.indexOf(',') == 0) clusterKey=clusterKey.substring(1);
486 clusterKey = clusterKey.trim();
487 if (clusterKey.equals(",") ) clusterKey=""; // print error if needed ( ... ),)
490 if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
491 && (partitionKey.equalsIgnoreCase(clusterKey) ||
492 clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) )
494 logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey + " and primary key=" + primaryKey );
495 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
496 "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ") of"
497 + " primary key=" + primaryKey)
502 if (partitionKey.isEmpty() ) primaryKey="";
503 else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")";
504 else primaryKey=" (" + partitionKey + ")," + clusterKey;
507 if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
509 } // end of length > 0
511 if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
512 && (partitionKey.equalsIgnoreCase(clusterKey) ||
513 clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) )
515 logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey);
516 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
517 "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ")")
521 if (partitionKey.isEmpty() ) primaryKey="";
522 else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")";
523 else primaryKey=" (" + partitionKey + ")," + clusterKey;
526 if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
528 fieldsString.append(")");
530 } // end of last field check
533 // information about the name-value style properties
534 Map<String, Object> propertiesMap = tableObj.getProperties();
535 StringBuilder propertiesString = new StringBuilder();
536 if (propertiesMap != null) {
538 for (Map.Entry<String, Object> entry : propertiesMap.entrySet()) {
539 Object ot = entry.getValue();
540 String value = ot + "";
541 if (ot instanceof String) {
542 value = "'" + value + "'";
543 } else if (ot instanceof Map) {
544 @SuppressWarnings("unchecked")
545 Map<String, Object> otMap = (Map<String, Object>) ot;
546 value = "{" + MusicUtil.jsonMaptoSqlString(otMap, ",") + "}";
549 propertiesString.append(entry.getKey() + "=" + value + "");
550 if (counter != propertiesMap.size() - 1)
551 propertiesString.append(" AND ");
553 counter = counter + 1;
557 String clusteringOrder = tableObj.getClusteringOrder();
559 if (clusteringOrder != null && !(clusteringOrder.isEmpty())) {
560 String[] arrayClusterOrder = clusteringOrder.split("[,]+");
562 for (int i = 0; i < arrayClusterOrder.length; i++) {
563 String[] clusterS = arrayClusterOrder[i].trim().split("[ ]+");
564 if ( (clusterS.length ==2) && (clusterS[1].equalsIgnoreCase("ASC") || clusterS[1].equalsIgnoreCase("DESC"))) {
567 return response.status(Status.BAD_REQUEST)
568 .entity(new JsonResponse(ResultType.FAILURE)
569 .setError("createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname order; please correct clusteringOrder:"+ clusteringOrder+".")
572 // add validation for column names in cluster key
575 if (!(clusterKey.isEmpty())) {
576 clusteringOrder = "CLUSTERING ORDER BY (" +clusteringOrder +")";
577 //cjc check if propertiesString.length() >0 instead propertiesMap
578 if (propertiesMap != null) {
579 propertiesString.append(" AND "+ clusteringOrder);
581 propertiesString.append(clusteringOrder);
584 logger.warn("Skipping clustering order=("+clusteringOrder+ ") since clustering key is empty ");
588 queryObject.appendQueryString(
589 "CREATE TABLE " + keyspace + "." + tablename + " " + fieldsString);
592 if (propertiesString != null && propertiesString.length()>0 )
593 queryObject.appendQueryString(" WITH " + propertiesString);
594 queryObject.appendQueryString(";");
595 ResultType result = ResultType.FAILURE;
597 result = MusicCore.createTable(keyspace, tablename, queryObject, consistency);
598 } catch (MusicServiceException ex) {
599 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.MUSICSERVICEERROR);
600 response.status(Status.BAD_REQUEST);
601 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
603 if ( result.equals(ResultType.FAILURE) ) {
604 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Error Creating Table " + tablename).toMap()).build();
606 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("TableName " + tablename.trim() + " Created under keyspace " + keyspace.trim()).toMap()).build();
608 EELFLoggerDelegate.mdcRemove("keyspace");
621 @Path("/{keyspace: .*}/tables/{tablename: .*}/index/{field: .*}")
622 @ApiOperation(value = "Create Index", response = String.class)
623 @Produces(MediaType.APPLICATION_JSON)
624 public Response createIndex(
625 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
626 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
627 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
628 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
629 @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns,
630 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
631 @ApiParam(value = "Keyspace Name",required = true) @PathParam("keyspace") String keyspace,
632 @ApiParam(value = "Table Name",required = true) @PathParam("tablename") String tablename,
633 @ApiParam(value = "Field Name",required = true) @PathParam("field") String fieldName,
634 @Context UriInfo info) throws Exception {
636 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
637 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty()) || (fieldName == null || fieldName.isEmpty())){
638 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
639 .setError("one or more path parameters are not set, please check and try again")
642 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
643 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
644 String userId = userCredentials.get(MusicUtil.USERID);
645 String password = userCredentials.get(MusicUtil.PASSWORD);
646 Map<String, Object> authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspace,aid, "createIndex");
647 if (authMap.containsKey("aid"))
648 authMap.remove("aid");
649 if (!authMap.isEmpty()) {
650 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGINFO ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
651 response.status(Status.UNAUTHORIZED);
652 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
654 MultivaluedMap<String, String> rowParams = info.getQueryParameters();
655 String indexName = "";
656 if (rowParams.getFirst("index_name") != null)
657 indexName = rowParams.getFirst("index_name");
658 PreparedQueryObject query = new PreparedQueryObject();
659 query.appendQueryString("Create index if not exists " + indexName + " on " + keyspace + "."
660 + tablename + " (" + fieldName + ");");
662 ResultType result = ResultType.FAILURE;
664 result = MusicCore.nonKeyRelatedPut(query, "eventual");
665 } catch (MusicServiceException ex) {
666 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
667 response.status(Status.BAD_REQUEST);
668 return response.entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
670 if ( result.equals(ResultType.SUCCESS) ) {
671 return response.status(Status.OK).entity(new JsonResponse(result).setMessage("Index Created on " + keyspace+"."+tablename+"."+fieldName).toMap()).build();
673 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Unknown Error in create index.").toMap()).build();
676 EELFLoggerDelegate.mdcRemove("keyspace");
689 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
690 @ApiOperation(value = "Insert Into Table", response = String.class)
691 @Consumes(MediaType.APPLICATION_JSON)
692 @Produces(MediaType.APPLICATION_JSON)
693 public Response insertIntoTable(
694 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
695 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
696 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
697 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
698 @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns,
699 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
701 @ApiParam(value = "Keyspace Name",
702 required = true) @PathParam("keyspace") String keyspace,
703 @ApiParam(value = "Table Name",
704 required = true) @PathParam("tablename") String tablename) {
706 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
707 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
708 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
709 .setError("one or more path parameters are not set, please check and try again")
712 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
713 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
714 String userId = userCredentials.get(MusicUtil.USERID);
715 String password = userCredentials.get(MusicUtil.PASSWORD);
716 Map<String, Object> authMap = null;
719 authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspace,
720 aid, "insertIntoTable");
721 } catch (Exception e) {
722 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGINFO ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
723 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
725 if (authMap.containsKey("aid"))
726 authMap.remove("aid");
727 if (!authMap.isEmpty()) {
728 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGINFO ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
729 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
732 Map<String, Object> valuesMap = insObj.getValues();
733 PreparedQueryObject queryObject = new PreparedQueryObject();
734 TableMetadata tableInfo = null;
736 tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
737 if(tableInfo == null) {
738 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Table name doesn't exists. Please check the table name.").toMap()).build();
740 } catch (MusicServiceException e) {
741 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
742 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
744 String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName();
745 StringBuilder fieldsString = new StringBuilder("(vector_ts,");
747 String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis());
748 StringBuilder valueString = new StringBuilder("(" + "?" + ",");
749 queryObject.addValue(vectorTs);
751 String primaryKey = "";
752 Map<String, byte[]> objectMap = insObj.getObjectMap();
753 for (Map.Entry<String, Object> entry : valuesMap.entrySet()) {
754 fieldsString.append("" + entry.getKey());
755 Object valueObj = entry.getValue();
756 if (primaryKeyName.equals(entry.getKey())) {
757 primaryKey = entry.getValue() + "";
758 primaryKey = primaryKey.replace("'", "''");
760 DataType colType = null;
762 colType = tableInfo.getColumn(entry.getKey()).getType();
763 } catch(NullPointerException ex) {
764 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() +" Invalid column name : "+entry.getKey(), AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
765 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap()).build();
768 Object formattedValue = null;
770 formattedValue = MusicUtil.convertToActualDataType(colType, valueObj);
771 } catch (Exception e) {
772 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
774 valueString.append("?");
776 queryObject.addValue(formattedValue);
778 if (counter == valuesMap.size() - 1) {
779 fieldsString.append(")");
780 valueString.append(")");
782 fieldsString.append(",");
783 valueString.append(",");
785 counter = counter + 1;
789 if(objectMap != null) {
790 for (Map.Entry<String, byte[]> entry : objectMap.entrySet()) {
792 fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ",");
793 valueString.replace(valueString.length()-1, valueString.length(), ",");
795 fieldsString.append("" + entry.getKey());
796 byte[] valueObj = entry.getValue();
797 if (primaryKeyName.equals(entry.getKey())) {
798 primaryKey = entry.getValue() + "";
799 primaryKey = primaryKey.replace("'", "''");
802 DataType colType = tableInfo.getColumn(entry.getKey()).getType();
804 ByteBuffer formattedValue = null;
806 if(colType.toString().toLowerCase().contains("blob"))
807 formattedValue = MusicUtil.convertToActualDataType(colType, valueObj);
809 valueString.append("?");
811 queryObject.addValue(formattedValue);
812 counter = counter + 1;
813 /*if (counter == valuesMap.size() - 1) {
814 fieldsString.append(")");
815 valueString.append(")");
817 fieldsString.append(",");
818 valueString.append(",");
822 if(primaryKey == null || primaryKey.length() <= 0) {
823 logger.error(EELFLoggerDelegate.errorLogger, "Some required partition key parts are missing: "+primaryKeyName );
824 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Some required partition key parts are missing: "+primaryKeyName).toMap()).build();
827 fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ")");
828 valueString.replace(valueString.length()-1, valueString.length(), ")");
830 queryObject.appendQueryString("INSERT INTO " + keyspace + "." + tablename + " "
831 + fieldsString + " VALUES " + valueString);
833 String ttl = insObj.getTtl();
834 String timestamp = insObj.getTimestamp();
836 if ((ttl != null) && (timestamp != null)) {
837 logger.info(EELFLoggerDelegate.applicationLogger, "both there");
838 queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?");
839 queryObject.addValue(Integer.parseInt(ttl));
840 queryObject.addValue(Long.parseLong(timestamp));
843 if ((ttl != null) && (timestamp == null)) {
844 logger.info(EELFLoggerDelegate.applicationLogger, "ONLY TTL there");
845 queryObject.appendQueryString(" USING TTL ?");
846 queryObject.addValue(Integer.parseInt(ttl));
849 if ((ttl == null) && (timestamp != null)) {
850 logger.info(EELFLoggerDelegate.applicationLogger, "ONLY timestamp there");
851 queryObject.appendQueryString(" USING TIMESTAMP ?");
852 queryObject.addValue(Long.parseLong(timestamp));
855 queryObject.appendQueryString(";");
857 ReturnType result = null;
858 String consistency = insObj.getConsistencyInfo().get("type");
859 if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && insObj.getConsistencyInfo().get("consistency") != null) {
860 if(MusicUtil.isValidConsistency(insObj.getConsistencyInfo().get("consistency")))
861 queryObject.setConsistency(insObj.getConsistencyInfo().get("consistency"));
863 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
865 queryObject.setOperation("insert");
867 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) {
868 result = MusicCore.eventualPut(queryObject);
869 } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
870 String lockId = insObj.getConsistencyInfo().get("lockId");
872 logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
873 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
874 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
875 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
877 result = MusicCore.criticalPut(keyspace, tablename, primaryKey, queryObject, lockId,null);
878 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
880 result = MusicCore.atomicPut(keyspace, tablename, primaryKey, queryObject, null);
883 else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) {
884 result = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, primaryKey, queryObject, null);
887 } catch (Exception ex) {
888 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
889 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
893 logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
894 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build();
895 }else if(result.getResult() == ResultType.FAILURE) {
896 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result.getResult()).setError(result.getMessage()).toMap()).build();
898 return response.status(Status.OK).entity(new JsonResponse(result.getResult()).setMessage("Insert Successful").toMap()).build();
900 EELFLoggerDelegate.mdcRemove("keyspace");
911 * @throws MusicServiceException
912 * @throws MusicQueryException
916 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
917 @ApiOperation(value = "Update Table", response = String.class)
918 @Consumes(MediaType.APPLICATION_JSON)
919 @Produces(MediaType.APPLICATION_JSON)
920 public Response updateTable(
921 @ApiParam(value = "Major Version",
922 required = true) @PathParam("version") String version,
923 @ApiParam(value = "Minor Version",
924 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
925 @ApiParam(value = "Patch Version",
926 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
927 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
928 @ApiParam(value = "Application namespace",
929 required = true) @HeaderParam(NS) String ns,
930 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
931 JsonUpdate updateObj,
932 @ApiParam(value = "Keyspace Name",
933 required = true) @PathParam("keyspace") String keyspace,
934 @ApiParam(value = "Table Name",
935 required = true) @PathParam("tablename") String tablename,
936 @Context UriInfo info) throws MusicQueryException, MusicServiceException {
938 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
939 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
940 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
941 .setError("one or more path parameters are not set, please check and try again")
944 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
945 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
946 String userId = userCredentials.get(MusicUtil.USERID);
947 String password = userCredentials.get(MusicUtil.PASSWORD);
948 Map<String, Object> authMap;
950 authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspace,
952 } catch (Exception e) {
953 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
954 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
956 if (authMap.containsKey("aid"))
957 authMap.remove("aid");
958 if (!authMap.isEmpty()) {
959 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
960 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
962 long startTime = System.currentTimeMillis();
963 String operationId = UUID.randomUUID().toString();// just for infoging
965 String consistency = updateObj.getConsistencyInfo().get("type");
967 logger.info(EELFLoggerDelegate.applicationLogger, "--------------Music " + consistency
968 + " update-" + operationId + "-------------------------");
969 // obtain the field value pairs of the update
971 PreparedQueryObject queryObject = new PreparedQueryObject();
972 Map<String, Object> valuesMap = updateObj.getValues();
974 TableMetadata tableInfo;
976 tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
977 } catch (MusicServiceException e) {
978 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
979 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
981 if (tableInfo == null) {
982 logger.error(EELFLoggerDelegate.errorLogger,"Table information not found. Please check input for table name= "+tablename, AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
983 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
984 .setError("Table information not found. Please check input for table name= "
985 + keyspace + "." + tablename).toMap()).build();
988 String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis());
989 StringBuilder fieldValueString = new StringBuilder("vector_ts=?,");
990 queryObject.addValue(vectorTs);
992 for (Map.Entry<String, Object> entry : valuesMap.entrySet()) {
993 Object valueObj = entry.getValue();
994 DataType colType = null;
996 colType = tableInfo.getColumn(entry.getKey()).getType();
997 } catch(NullPointerException ex) {
998 logger.error(EELFLoggerDelegate.errorLogger, "Invalid column name : "+entry.getKey());
999 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap()).build();
1001 Object valueString = null;
1003 valueString = MusicUtil.convertToActualDataType(colType, valueObj);
1004 } catch (Exception e) {
1005 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
1007 fieldValueString.append(entry.getKey() + "= ?");
1008 queryObject.addValue(valueString);
1009 if (counter != valuesMap.size() - 1)
1010 fieldValueString.append(",");
1011 counter = counter + 1;
1013 String ttl = updateObj.getTtl();
1014 String timestamp = updateObj.getTimestamp();
1016 queryObject.appendQueryString("UPDATE " + keyspace + "." + tablename + " ");
1017 if ((ttl != null) && (timestamp != null)) {
1019 logger.info("both there");
1020 queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?");
1021 queryObject.addValue(Integer.parseInt(ttl));
1022 queryObject.addValue(Long.parseLong(timestamp));
1025 if ((ttl != null) && (timestamp == null)) {
1026 logger.info("ONLY TTL there");
1027 queryObject.appendQueryString(" USING TTL ?");
1028 queryObject.addValue(Integer.parseInt(ttl));
1031 if ((ttl == null) && (timestamp != null)) {
1032 logger.info("ONLY timestamp there");
1033 queryObject.appendQueryString(" USING TIMESTAMP ?");
1034 queryObject.addValue(Long.parseLong(timestamp));
1036 // get the row specifier
1037 RowIdentifier rowId = null;
1039 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
1040 if(rowId == null || rowId.primarKeyValue.isEmpty()) {
1041 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1042 .setError("Mandatory WHERE clause is missing. Please check the input request.").toMap()).build();
1044 } catch (MusicServiceException ex) {
1045 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1046 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1049 queryObject.appendQueryString(
1050 " SET " + fieldValueString + " WHERE " + rowId.rowIdString + ";");
1052 // get the conditional, if any
1053 Condition conditionInfo;
1054 if (updateObj.getConditions() == null)
1055 conditionInfo = null;
1056 else {// to avoid parsing repeatedly, just send the select query to
1058 PreparedQueryObject selectQuery = new PreparedQueryObject();
1059 selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE "
1060 + rowId.rowIdString + ";");
1061 selectQuery.addValue(rowId.primarKeyValue);
1062 conditionInfo = new Condition(updateObj.getConditions(), selectQuery);
1065 ReturnType operationResult = null;
1066 long jsonParseCompletionTime = System.currentTimeMillis();
1068 if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && updateObj.getConsistencyInfo().get("consistency") != null) {
1069 if(MusicUtil.isValidConsistency(updateObj.getConsistencyInfo().get("consistency")))
1070 queryObject.setConsistency(updateObj.getConsistencyInfo().get("consistency"));
1072 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
1074 queryObject.setOperation("update");
1075 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL))
1076 operationResult = MusicCore.eventualPut(queryObject);
1077 else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
1078 String lockId = updateObj.getConsistencyInfo().get("lockId");
1079 if(lockId == null) {
1080 logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
1081 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
1082 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
1083 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
1085 operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue,
1086 queryObject, lockId, conditionInfo);
1087 } else if (consistency.equalsIgnoreCase("atomic_delete_lock")) {
1088 // this function is mainly for the benchmarks
1090 operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename,
1091 rowId.primarKeyValue, queryObject, conditionInfo);
1092 } catch (MusicLockingException e) {
1093 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1094 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
1096 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
1098 operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue,
1099 queryObject, conditionInfo);
1100 } catch (MusicLockingException e) {
1101 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1102 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
1104 }else if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) {
1105 operationResult = MusicCore.eventualPut_nb(queryObject, keyspace, tablename, rowId.primarKeyValue);
1107 long actualUpdateCompletionTime = System.currentTimeMillis();
1109 long endTime = System.currentTimeMillis();
1110 String timingString = "Time taken in ms for Music " + consistency + " update-" + operationId
1111 + ":" + "|total operation time:" + (endTime - startTime)
1112 + "|json parsing time:" + (jsonParseCompletionTime - startTime)
1113 + "|update time:" + (actualUpdateCompletionTime - jsonParseCompletionTime)
1116 if (operationResult != null && operationResult.getTimingInfo() != null) {
1117 String lockManagementTime = operationResult.getTimingInfo();
1118 timingString = timingString + lockManagementTime;
1120 logger.info(EELFLoggerDelegate.applicationLogger, timingString);
1122 if (operationResult==null) {
1123 logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1124 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build();
1126 if ( operationResult.getResult() == ResultType.SUCCESS ) {
1127 return response.status(Status.OK).entity(new JsonResponse(operationResult.getResult()).setMessage(operationResult.getMessage()).toMap()).build();
1129 logger.error(EELFLoggerDelegate.errorLogger,operationResult.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1130 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(operationResult.getResult()).setError(operationResult.getMessage()).toMap()).build();
1133 EELFLoggerDelegate.mdcRemove("keyspace");
1144 * @throws MusicServiceException
1145 * @throws MusicQueryException
1149 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
1150 @ApiOperation(value = "Delete From table", response = String.class)
1151 @Consumes(MediaType.APPLICATION_JSON)
1152 @Produces(MediaType.APPLICATION_JSON)
1153 public Response deleteFromTable(
1154 @ApiParam(value = "Major Version",
1155 required = true) @PathParam("version") String version,
1156 @ApiParam(value = "Minor Version",
1157 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1158 @ApiParam(value = "Patch Version",
1159 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1160 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
1161 @ApiParam(value = "Application namespace",
1162 required = true) @HeaderParam(NS) String ns,
1163 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1165 @ApiParam(value = "Keyspace Name",
1166 required = true) @PathParam("keyspace") String keyspace,
1167 @ApiParam(value = "Table Name",
1168 required = true) @PathParam("tablename") String tablename,
1169 @Context UriInfo info) throws MusicQueryException, MusicServiceException {
1171 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1172 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1173 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1174 .setError("one or more path parameters are not set, please check and try again")
1177 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
1178 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
1179 String userId = userCredentials.get(MusicUtil.USERID);
1180 String password = userCredentials.get(MusicUtil.PASSWORD);
1181 Map<String, Object> authMap = null;
1183 authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspace,
1184 aid, "deleteFromTable");
1185 } catch (Exception e) {
1186 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
1187 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
1189 if (authMap.containsKey("aid"))
1190 authMap.remove("aid");
1191 if (!authMap.isEmpty()) {
1192 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
1193 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
1195 if(delObj == null) {
1196 logger.error(EELFLoggerDelegate.errorLogger,"Required HTTP Request body is missing.", AppMessages.MISSINGDATA ,ErrorSeverity.WARN, ErrorTypes.DATAERROR);
1197 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Required HTTP Request body is missing.").toMap()).build();
1199 PreparedQueryObject queryObject = new PreparedQueryObject();
1200 StringBuilder columnString = new StringBuilder();
1203 List<String> columnList = delObj.getColumns();
1204 if (columnList != null) {
1205 for (String column : columnList) {
1206 columnString.append(column);
1207 if (counter != columnList.size() - 1)
1208 columnString.append(",");
1209 counter = counter + 1;
1213 // get the row specifier
1214 RowIdentifier rowId = null;
1216 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
1217 } catch (MusicServiceException ex) {
1218 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1219 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1221 String rowSpec = rowId.rowIdString.toString();
1223 if ((columnList != null) && (!rowSpec.isEmpty())) {
1224 queryObject.appendQueryString("DELETE " + columnString + " FROM " + keyspace + "."
1225 + tablename + " WHERE " + rowSpec + ";");
1228 if ((columnList == null) && (!rowSpec.isEmpty())) {
1229 queryObject.appendQueryString("DELETE FROM " + keyspace + "." + tablename + " WHERE "
1233 if ((columnList != null) && (rowSpec.isEmpty())) {
1234 queryObject.appendQueryString(
1235 "DELETE " + columnString + " FROM " + keyspace + "." + rowSpec + ";");
1237 // get the conditional, if any
1238 Condition conditionInfo;
1239 if (delObj.getConditions() == null)
1240 conditionInfo = null;
1241 else {// to avoid parsing repeatedly, just send the select query to
1243 PreparedQueryObject selectQuery = new PreparedQueryObject();
1244 selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE "
1245 + rowId.rowIdString + ";");
1246 selectQuery.addValue(rowId.primarKeyValue);
1247 conditionInfo = new Condition(delObj.getConditions(), selectQuery);
1250 String consistency = delObj.getConsistencyInfo().get("type");
1253 if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && delObj.getConsistencyInfo().get("consistency")!=null) {
1255 if(MusicUtil.isValidConsistency(delObj.getConsistencyInfo().get("consistency")))
1256 queryObject.setConsistency(delObj.getConsistencyInfo().get("consistency"));
1258 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
1261 ReturnType operationResult = null;
1262 queryObject.setOperation("delete");
1264 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL))
1265 operationResult = MusicCore.eventualPut(queryObject);
1266 else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
1267 String lockId = delObj.getConsistencyInfo().get("lockId");
1268 if(lockId == null) {
1269 logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
1270 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
1271 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
1272 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
1274 operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue,
1275 queryObject, lockId, conditionInfo);
1276 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
1277 operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue,
1278 queryObject, conditionInfo);
1280 else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) {
1281 operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, rowId.primarKeyValue,
1282 queryObject, conditionInfo);
1283 }else if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) {
1285 operationResult = MusicCore.eventualPut_nb(queryObject, keyspace, tablename, rowId.primarKeyValue);
1287 } catch (MusicLockingException e) {
1288 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1289 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1290 .setError("Unable to perform Delete operation. Exception from music").toMap()).build();
1292 if (operationResult==null) {
1293 logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1294 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build();
1296 if (operationResult.getResult().equals(ResultType.SUCCESS)) {
1297 return response.status(Status.OK).entity(new JsonResponse(operationResult.getResult()).setMessage(operationResult.getMessage()).toMap()).build();
1299 logger.error(EELFLoggerDelegate.errorLogger,operationResult.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1300 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(operationResult.getMessage()).toMap()).build();
1303 EELFLoggerDelegate.mdcRemove("keyspace");
1315 @Path("/{keyspace: .*}/tables/{tablename: .*}")
1316 @ApiOperation(value = "Drop Table", response = String.class)
1317 @Produces(MediaType.APPLICATION_JSON)
1318 public Response dropTable(
1319 @ApiParam(value = "Major Version",
1320 required = true) @PathParam("version") String version,
1321 @ApiParam(value = "Minor Version",
1322 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1323 @ApiParam(value = "Patch Version",
1324 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1325 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
1326 @ApiParam(value = "Application namespace",
1327 required = true) @HeaderParam(NS) String ns,
1328 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1329 @ApiParam(value = "Keyspace Name",
1330 required = true) @PathParam("keyspace") String keyspace,
1331 @ApiParam(value = "Table Name",
1332 required = true) @PathParam("tablename") String tablename) throws Exception {
1334 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1335 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1336 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1337 .setError("one or more path parameters are not set, please check and try again")
1340 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
1341 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
1342 String userId = userCredentials.get(MusicUtil.USERID);
1343 String password = userCredentials.get(MusicUtil.PASSWORD);
1344 Map<String, Object> authMap =
1345 MusicAuthentication.autheticateUser(ns, userId, password, keyspace, aid, "dropTable");
1346 if (authMap.containsKey("aid"))
1347 authMap.remove("aid");
1348 if (!authMap.isEmpty()) {
1349 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
1350 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
1352 String consistency = "eventual";// for now this needs only eventual
1354 PreparedQueryObject query = new PreparedQueryObject();
1355 query.appendQueryString("DROP TABLE " + keyspace + "." + tablename + ";");
1357 return response.status(Status.OK).entity(new JsonResponse(MusicCore.nonKeyRelatedPut(query, consistency)).toMap()).build();
1358 } catch (MusicServiceException ex) {
1359 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1360 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1363 EELFLoggerDelegate.mdcRemove("keyspace");
1376 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows/criticalget")
1377 @ApiOperation(value = "Select Critical", response = Map.class)
1378 @Consumes(MediaType.APPLICATION_JSON)
1379 @Produces(MediaType.APPLICATION_JSON)
1380 public Response selectCritical(
1381 @ApiParam(value = "Major Version",
1382 required = true) @PathParam("version") String version,
1383 @ApiParam(value = "Minor Version",
1384 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1385 @ApiParam(value = "Patch Version",
1386 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1387 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
1388 @ApiParam(value = "Application namespace",
1389 required = true) @HeaderParam(NS) String ns,
1390 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1392 @ApiParam(value = "Keyspace Name",
1393 required = true) @PathParam("keyspace") String keyspace,
1394 @ApiParam(value = "Table Name",
1395 required = true) @PathParam("tablename") String tablename,
1396 @Context UriInfo info) throws Exception {
1398 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1399 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1400 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1401 .setError("one or more path parameters are not set, please check and try again")
1404 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
1405 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
1406 String userId = userCredentials.get(MusicUtil.USERID);
1407 String password = userCredentials.get(MusicUtil.PASSWORD);
1408 Map<String, Object> authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspace,aid, "selectCritical");
1409 if (authMap.containsKey("aid"))
1410 authMap.remove("aid");
1411 if (!authMap.isEmpty()) {
1412 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
1413 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
1415 String lockId = selObj.getConsistencyInfo().get("lockId");
1417 PreparedQueryObject queryObject = new PreparedQueryObject();
1419 RowIdentifier rowId = null;
1421 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
1422 } catch (MusicServiceException ex) {
1423 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1424 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1426 queryObject.appendQueryString(
1427 "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowId.rowIdString + ";");
1429 ResultSet results = null;
1431 String consistency = selObj.getConsistencyInfo().get("type");
1433 if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
1434 if(lockId == null) {
1435 logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
1436 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
1437 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
1438 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
1440 results = MusicCore.criticalGet(keyspace, tablename, rowId.primarKeyValue, queryObject,
1442 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
1443 results = MusicCore.atomicGet(keyspace, tablename, rowId.primarKeyValue, queryObject);
1446 else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) {
1447 results = MusicCore.atomicGetWithDeleteLock(keyspace, tablename, rowId.primarKeyValue, queryObject);
1449 if(results!=null && results.getAvailableWithoutFetching() >0) {
1450 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build();
1452 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setError("No data found").toMap()).build();
1455 EELFLoggerDelegate.mdcRemove("keyspace");
1468 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
1469 @ApiOperation(value = "Select All or Select Specific", response = Map.class)
1470 @Produces(MediaType.APPLICATION_JSON)
1471 public Response select(
1472 @ApiParam(value = "Major Version",
1473 required = true) @PathParam("version") String version,
1474 @ApiParam(value = "Minor Version",
1475 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1476 @ApiParam(value = "Patch Version",
1477 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1478 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
1479 @ApiParam(value = "Application namespace",
1480 required = true) @HeaderParam(NS) String ns,
1481 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1482 @ApiParam(value = "Keyspace Name",
1483 required = true) @PathParam("keyspace") String keyspace,
1484 @ApiParam(value = "Table Name",
1485 required = true) @PathParam("tablename") String tablename,
1486 @Context UriInfo info) throws Exception {
1488 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1489 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1490 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1491 .setError("one or more path parameters are not set, please check and try again")
1494 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
1495 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
1496 String userId = userCredentials.get(MusicUtil.USERID);
1497 String password = userCredentials.get(MusicUtil.PASSWORD);
1498 Map<String, Object> authMap =
1499 MusicAuthentication.autheticateUser(ns, userId, password, keyspace, aid, "select");
1500 if (authMap.containsKey("aid"))
1501 authMap.remove("aid");
1502 if (!authMap.isEmpty()) {
1503 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
1504 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
1506 PreparedQueryObject queryObject = new PreparedQueryObject();
1508 if (info.getQueryParameters().isEmpty())// select all
1509 queryObject.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + ";");
1511 int limit = -1; // do not limit the number of results
1513 queryObject = selectSpecificQuery(VERSION, minorVersion, patchVersion, aid, ns,
1514 userId, password, keyspace, tablename, info, limit);
1515 } catch (MusicServiceException ex) {
1516 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1517 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1522 ResultSet results = MusicCore.get(queryObject);
1523 if(results.getAvailableWithoutFetching() >0) {
1524 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build();
1526 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).setError("No data found").toMap()).build();
1527 } catch (MusicServiceException ex) {
1528 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.ERROR, ErrorTypes.MUSICSERVICEERROR);
1529 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1532 EELFLoggerDelegate.mdcRemove("keyspace");
1543 * @throws MusicServiceException
1545 public PreparedQueryObject selectSpecificQuery(String version, String minorVersion,
1546 String patchVersion, String aid, String ns, String userId, String password,
1547 String keyspace, String tablename, UriInfo info, int limit)
1548 throws MusicServiceException {
1550 PreparedQueryObject queryObject = new PreparedQueryObject();
1551 StringBuilder rowIdString = getRowIdentifier(keyspace, tablename, info.getQueryParameters(),
1552 queryObject).rowIdString;
1554 queryObject.appendQueryString(
1555 "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowIdString);
1558 queryObject.appendQueryString(" LIMIT " + limit);
1561 queryObject.appendQueryString(";");
1571 * @param queryObject
1573 * @throws MusicServiceException
1575 private RowIdentifier getRowIdentifier(String keyspace, String tablename,
1576 MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject)
1577 throws MusicServiceException {
1578 StringBuilder rowSpec = new StringBuilder();
1580 TableMetadata tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
1581 if (tableInfo == null) {
1582 logger.error(EELFLoggerDelegate.errorLogger,
1583 "Table information not found. Please check input for table name= "
1584 + keyspace + "." + tablename);
1585 throw new MusicServiceException(
1586 "Table information not found. Please check input for table name= "
1587 + keyspace + "." + tablename);
1589 StringBuilder primaryKey = new StringBuilder();
1590 for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) {
1591 String keyName = entry.getKey();
1592 List<String> valueList = entry.getValue();
1593 String indValue = valueList.get(0);
1594 DataType colType = null;
1595 Object formattedValue = null;
1597 colType = tableInfo.getColumn(entry.getKey()).getType();
1598 formattedValue = MusicUtil.convertToActualDataType(colType, indValue);
1599 } catch (Exception e) {
1600 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
1602 if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey()))
1603 primaryKey.append(indValue);
1604 rowSpec.append(keyName + "= ?");
1605 queryObject.addValue(formattedValue);
1606 if (counter != rowParams.size() - 1)
1607 rowSpec.append(" AND ");
1608 counter = counter + 1;
1610 return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject);