2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright (c) 2017 AT&T Intellectual Property
6 * ===================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 * ============LICENSE_END=============================================
20 * ====================================================================
23 package org.onap.music.rest;
25 import java.nio.ByteBuffer;
26 import java.util.ArrayList;
27 import java.util.List;
29 import java.util.UUID;
31 import javax.servlet.http.HttpServletResponse;
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.HttpHeaders;
43 import javax.ws.rs.core.MediaType;
44 import javax.ws.rs.core.MultivaluedMap;
45 import javax.ws.rs.core.Response;
46 import javax.ws.rs.core.Response.ResponseBuilder;
47 import javax.ws.rs.core.Response.Status;
48 import javax.ws.rs.core.UriInfo;
50 import org.apache.commons.lang3.StringUtils;
51 import org.mindrot.jbcrypt.BCrypt;
52 import org.onap.music.authentication.MusicAuthentication;
53 import org.onap.music.datastore.PreparedQueryObject;
54 import org.onap.music.datastore.jsonobjects.JsonDelete;
55 import org.onap.music.datastore.jsonobjects.JsonInsert;
56 import org.onap.music.datastore.jsonobjects.JsonKeySpace;
57 import org.onap.music.datastore.jsonobjects.JsonTable;
58 import org.onap.music.datastore.jsonobjects.JsonUpdate;
59 import org.onap.music.eelf.logging.EELFLoggerDelegate;
60 import org.onap.music.exceptions.MusicLockingException;
61 import org.onap.music.exceptions.MusicQueryException;
62 import org.onap.music.eelf.logging.format.AppMessages;
63 import org.onap.music.eelf.logging.format.ErrorSeverity;
64 import org.onap.music.eelf.logging.format.ErrorTypes;
65 import org.onap.music.exceptions.MusicServiceException;
66 import org.onap.music.main.CachingUtil;
67 import org.onap.music.main.MusicCore;
68 import org.onap.music.datastore.Condition;
69 import org.onap.music.datastore.MusicDataStoreHandle;
70 import org.onap.music.main.MusicUtil;
71 import org.onap.music.main.ResultType;
72 import org.onap.music.main.ReturnType;
73 import org.onap.music.response.jsonobjects.JsonResponse;
74 import org.onap.music.service.impl.MusicZKCore;
76 import com.datastax.driver.core.DataType;
77 import com.datastax.driver.core.ResultSet;
78 import com.datastax.driver.core.Row;
79 import com.datastax.driver.core.TableMetadata;
81 import io.swagger.annotations.Api;
82 import io.swagger.annotations.ApiOperation;
83 import io.swagger.annotations.ApiParam;
84 import io.swagger.annotations.ApiResponses;
85 import io.swagger.annotations.ApiResponse;
88 //@Path("/v{version: [0-9]+}/keyspaces")
89 @Path("/v2/keyspaces")
90 @Api(value = "Data Api")
91 public class RestMusicDataAPI {
93 * Header values for Versioning X-minorVersion *** - Used to request or communicate a MINOR
94 * version back from the client to the server, and from the server back to the client - This
95 * will be the MINOR version requested by the client, or the MINOR version of the last MAJOR
96 * version (if not specified by the client on the request) - Contains a single position value
97 * (e.g. if the full version is 1.24.5, X-minorVersion = "24") - Is optional for the client on
98 * request; however, this header should be provided if the client needs to take advantage of
99 * MINOR incremented version functionality - Is mandatory for the server on response
101 *** X-patchVersion *** - Used only to communicate a PATCH version in a response for
102 * troubleshooting purposes only, and will not be provided by the client on request - This will
103 * be the latest PATCH version of the MINOR requested by the client, or the latest PATCH version
104 * of the MAJOR (if not specified by the client on the request) - Contains a single position
105 * value (e.g. if the full version is 1.24.5, X-patchVersion = "5") - Is mandatory for the
106 * server on response (CURRENTLY NOT USED)
108 *** X-latestVersion *** - Used only to communicate an API's latest version - Is mandatory for the
109 * server on response, and shall include the entire version of the API (e.g. if the full version
110 * is 1.24.5, X-latestVersion = "1.24.5") - Used in the response to inform clients that they are
111 * not using the latest version of the API (CURRENTLY NOT USED)
115 private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicDataAPI.class);
116 private static final String XMINORVERSION = "X-minorVersion";
117 private static final String XPATCHVERSION = "X-patchVersion";
118 private static final String NS = "ns";
119 private static final String VERSION = "v2";
120 // Set to true in env like ONAP. Where access to creating and dropping keyspaces exist.
121 private static final boolean KEYSPACE_ACTIVE = false;
123 private class RowIdentifier {
124 public String primarKeyValue;
125 public StringBuilder rowIdString;
126 @SuppressWarnings("unused")
127 public PreparedQueryObject queryObject;// the string with all the row
128 // identifiers separated by AND
130 public RowIdentifier(String primaryKeyValue, StringBuilder rowIdString,
131 PreparedQueryObject queryObject) {
132 this.primarKeyValue = primaryKeyValue;
133 this.rowIdString = rowIdString;
134 this.queryObject = queryObject;
140 * Create Keyspace REST
143 * @param keyspaceName
149 @ApiOperation(value = "Create Keyspace", response = String.class,hidden = true)
150 @Consumes(MediaType.APPLICATION_JSON)
151 @Produces(MediaType.APPLICATION_JSON)
152 //public Map<String, Object> createKeySpace(
153 public Response createKeySpace(
154 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
155 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
156 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
157 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
158 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
159 @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns,
160 JsonKeySpace kspObject,
161 @ApiParam(value = "Keyspace Name",required = true) @PathParam("name") String keyspaceName) {
163 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
164 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) ");
165 logger.info(EELFLoggerDelegate.applicationLogger,"In Create Keyspace " + keyspaceName);
166 if ( KEYSPACE_ACTIVE ) {
167 logger.info(EELFLoggerDelegate.applicationLogger,"Creating Keyspace " + keyspaceName);
168 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
169 String userId = userCredentials.get(MusicUtil.USERID);
170 String password = userCredentials.get(MusicUtil.PASSWORD);
171 Map<String, Object> authMap = CachingUtil.verifyOnboarding(ns, userId, password);
172 if (!authMap.isEmpty()) {
173 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
174 response.status(Status.UNAUTHORIZED);
175 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
177 if(kspObject == null || kspObject.getReplicationInfo() == null) {
178 response.status(Status.BAD_REQUEST);
179 return response.entity(new JsonResponse(ResultType.FAILURE).setError(ResultType.BODYMISSING.getResult()).toMap()).build();
184 authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspaceName, aid,
186 } catch (Exception e) {
187 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
188 response.status(Status.BAD_REQUEST);
189 return response.entity(new JsonResponse(ResultType.FAILURE).setError("Unable to authenticate.").toMap()).build();
191 String newAid = null;
192 if (!authMap.isEmpty()) {
193 if (authMap.containsKey("aid")) {
194 newAid = (String) authMap.get("aid");
196 logger.error(EELFLoggerDelegate.errorLogger,String.valueOf(authMap.get("Exception")), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
197 response.status(Status.UNAUTHORIZED);
198 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
202 String consistency = MusicUtil.EVENTUAL;// for now this needs only
203 // eventual consistency
205 PreparedQueryObject queryObject = new PreparedQueryObject();
206 if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && kspObject.getConsistencyInfo().get("consistency") != null) {
207 if(MusicUtil.isValidConsistency(kspObject.getConsistencyInfo().get("consistency")))
208 queryObject.setConsistency(kspObject.getConsistencyInfo().get("consistency"));
210 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
212 long start = System.currentTimeMillis();
213 Map<String, Object> replicationInfo = kspObject.getReplicationInfo();
214 String repString = null;
216 repString = "{" + MusicUtil.jsonMaptoSqlString(replicationInfo, ",") + "}";
217 } catch (Exception e) {
218 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
221 queryObject.appendQueryString(
222 "CREATE KEYSPACE " + keyspaceName + " WITH replication = " + repString);
223 if (kspObject.getDurabilityOfWrites() != null) {
224 queryObject.appendQueryString(
225 " AND durable_writes = " + kspObject.getDurabilityOfWrites());
228 queryObject.appendQueryString(";");
229 long end = System.currentTimeMillis();
230 logger.info(EELFLoggerDelegate.applicationLogger,
231 "Time taken for setting up query in create keyspace:" + (end - start));
233 ResultType result = ResultType.FAILURE;
235 result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
236 logger.info(EELFLoggerDelegate.applicationLogger, "result = " + result);
237 } catch ( MusicServiceException ex) {
238 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
239 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("err:" + ex.getMessage()).toMap()).build();
243 queryObject = new PreparedQueryObject();
244 queryObject.appendQueryString("CREATE ROLE IF NOT EXISTS '" + userId
245 + "' WITH PASSWORD = '" + password + "' AND LOGIN = true;");
246 MusicCore.nonKeyRelatedPut(queryObject, consistency);
247 queryObject = new PreparedQueryObject();
248 queryObject.appendQueryString("GRANT ALL PERMISSIONS on KEYSPACE " + keyspaceName
249 + " to '" + userId + "'");
250 queryObject.appendQueryString(";");
251 MusicCore.nonKeyRelatedPut(queryObject, consistency);
252 } catch (Exception e) {
253 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
257 boolean isAAF = Boolean.valueOf(CachingUtil.isAAFApplication(ns));
258 String hashedpwd = BCrypt.hashpw(password, BCrypt.gensalt());
259 queryObject = new PreparedQueryObject();
260 queryObject.appendQueryString(
261 "INSERT into admin.keyspace_master (uuid, keyspace_name, application_name, is_api, "
262 + "password, username, is_aaf) values (?,?,?,?,?,?,?)");
263 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), newAid));
264 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), keyspaceName));
265 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), ns));
266 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "True"));
267 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), hashedpwd));
268 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId));
269 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF));
270 CachingUtil.updateMusicCache(keyspaceName, ns);
271 CachingUtil.updateMusicValidateCache(ns, userId, hashedpwd);
272 MusicCore.eventualPut(queryObject);
273 } catch (Exception e) {
274 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
275 return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
278 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Created").toMap()).build();
280 String vError = "Keyspace Creation no longer supported after versions 3.2.x. Contact DBA to create the keyspace.";
281 logger.info(EELFLoggerDelegate.applicationLogger,vError);
282 logger.error(EELFLoggerDelegate.errorLogger,vError, AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
283 return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(vError).toMap()).build();
286 EELFLoggerDelegate.mdcRemove("keyspace");
294 * @param keyspaceName
300 @ApiOperation(value = "Delete Keyspace", response = String.class,hidden=true)
301 @Produces(MediaType.APPLICATION_JSON)
302 public Response dropKeySpace(
303 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
304 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
305 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
306 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
307 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
308 @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns,
309 @ApiParam(value = "Keyspace Name",required = true) @PathParam("name") String keyspaceName) throws Exception {
311 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
312 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) ");
313 logger.info(EELFLoggerDelegate.applicationLogger,"In Drop Keyspace " + keyspaceName);
314 if ( KEYSPACE_ACTIVE ) {
315 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
316 String userId = userCredentials.get(MusicUtil.USERID);
317 String password = userCredentials.get(MusicUtil.PASSWORD);
318 Map<String, Object> authMap = MusicAuthentication.autheticateUser(ns, userId, password,keyspaceName, aid, "dropKeySpace");
319 if (authMap.containsKey("aid"))
320 authMap.remove("aid");
321 if (!authMap.isEmpty()) {
322 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
323 response.status(Status.UNAUTHORIZED);
324 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
327 String consistency = MusicUtil.EVENTUAL;// for now this needs only
330 String appName = CachingUtil.getAppName(keyspaceName);
331 String uuid = CachingUtil.getUuidFromMusicCache(keyspaceName);
332 PreparedQueryObject pQuery = new PreparedQueryObject();
333 pQuery.appendQueryString(
334 "select count(*) as count from admin.keyspace_master where application_name=? allow filtering;");
335 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName));
336 Row row = MusicCore.get(pQuery).one();
337 long count = row.getLong(0);
340 logger.error(EELFLoggerDelegate.errorLogger,"Keyspace not found. Please make sure keyspace exists.", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
341 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Keyspace not found. Please make sure keyspace exists.").toMap()).build();
343 } else if (count == 1) {
344 pQuery = new PreparedQueryObject();
345 pQuery.appendQueryString(
346 "UPDATE admin.keyspace_master SET keyspace_name=? where uuid = ?;");
347 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(),
348 MusicUtil.DEFAULTKEYSPACENAME));
349 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid));
350 MusicCore.nonKeyRelatedPut(pQuery, consistency);
352 pQuery = new PreparedQueryObject();
353 pQuery.appendQueryString("delete from admin.keyspace_master where uuid = ?");
354 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid));
355 MusicCore.nonKeyRelatedPut(pQuery, consistency);
358 PreparedQueryObject queryObject = new PreparedQueryObject();
359 queryObject.appendQueryString("DROP KEYSPACE " + keyspaceName + ";");
360 ResultType result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
361 if ( result.equals(ResultType.FAILURE) ) {
362 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Error Deleteing Keyspace " + keyspaceName).toMap()).build();
364 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Deleted").toMap()).build();
366 String vError = "Keyspace Droping no longer supported after versions 3.2.x. Contact DBA to drop the keyspace.";
367 logger.info(EELFLoggerDelegate.applicationLogger,vError);
368 logger.error(EELFLoggerDelegate.errorLogger,vError, AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
369 return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(vError).toMap()).build();
372 EELFLoggerDelegate.mdcRemove("keyspace");
387 @Path("/{keyspace: .*}/tables/{tablename: .*}")
388 @ApiOperation(value = "Create Table", response = String.class)
389 @Consumes(MediaType.APPLICATION_JSON)
390 @Produces(MediaType.APPLICATION_JSON)
391 @ApiResponses(value={
392 @ApiResponse(code= 400, message = "Will return JSON response with message"),
393 @ApiResponse(code= 401, message = "Unautorized User")
395 public Response createTable(
396 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
397 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
398 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
399 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
400 @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns,
401 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
403 @ApiParam(value = "Keyspace Name",required = true) @PathParam("keyspace") String keyspace,
404 @ApiParam(value = "Table Name",required = true) @PathParam("tablename") String tablename) throws Exception {
406 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
407 if((keyspace == null || keyspace == null) || (tablename.isEmpty() || tablename.isEmpty())){
408 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
409 .setError("one or more path parameters are not set, please check and try again")
412 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
413 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
414 String userId = userCredentials.get(MusicUtil.USERID);
415 String password = userCredentials.get(MusicUtil.PASSWORD);
416 Map<String, Object> authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspace,
418 if (authMap.containsKey("aid"))
419 authMap.remove("aid");
420 if (!authMap.isEmpty()) {
421 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGINFO ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
422 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
424 String consistency = MusicUtil.EVENTUAL;
425 // for now this needs only eventual consistency
427 String primaryKey = null;
428 String partitionKey = tableObj.getPartitionKey();
429 String clusterKey = tableObj.getClusteringKey();
430 String filteringKey = tableObj.getFilteringKey();
431 if(filteringKey != null) {
432 clusterKey = clusterKey + "," + filteringKey;
434 primaryKey = tableObj.getPrimaryKey(); // get primaryKey if available
436 PreparedQueryObject queryObject = new PreparedQueryObject();
437 // first read the information about the table fields
438 Map<String, String> fields = tableObj.getFields();
439 StringBuilder fieldsString = new StringBuilder("(vector_ts text,");
441 for (Map.Entry<String, String> entry : fields.entrySet()) {
442 if (entry.getKey().equals("PRIMARY KEY")) {
443 primaryKey = entry.getValue(); // replaces primaryKey
444 primaryKey = primaryKey.trim();
446 if (counter == 0 ) fieldsString.append("" + entry.getKey() + " " + entry.getValue() + "");
447 else fieldsString.append("," + entry.getKey() + " " + entry.getValue() + "");
450 if (counter != (fields.size() - 1) ) {
452 counter = counter + 1;
455 if((primaryKey != null) && (partitionKey == null)) {
456 primaryKey = primaryKey.trim();
457 int count1 = StringUtils.countMatches(primaryKey, ')');
458 int count2 = StringUtils.countMatches(primaryKey, '(');
459 if (count1 != count2) {
460 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
461 .setError("Create Table Error: primary key '(' and ')' do not match, primary key=" + primaryKey)
465 if ( primaryKey.indexOf('(') == -1 || ( count2 == 1 && (primaryKey.lastIndexOf(')') +1) == primaryKey.length() ) )
467 if (primaryKey.contains(",") ) {
468 partitionKey= primaryKey.substring(0,primaryKey.indexOf(','));
469 partitionKey=partitionKey.replaceAll("[\\(]+","");
470 clusterKey=primaryKey.substring(primaryKey.indexOf(',')+1); // make sure index
471 clusterKey=clusterKey.replaceAll("[)]+", "");
473 partitionKey=primaryKey;
474 partitionKey=partitionKey.replaceAll("[\\)]+","");
475 partitionKey=partitionKey.replaceAll("[\\(]+","");
478 } else { // not null and has ) before the last char
479 partitionKey= primaryKey.substring(0,primaryKey.indexOf(')'));
480 partitionKey=partitionKey.replaceAll("[\\(]+","");
481 partitionKey = partitionKey.trim();
482 clusterKey= primaryKey.substring(primaryKey.indexOf(')'));
483 clusterKey=clusterKey.replaceAll("[\\(]+","");
484 clusterKey=clusterKey.replaceAll("[\\)]+","");
485 clusterKey = clusterKey.trim();
486 if (clusterKey.indexOf(',') == 0) clusterKey=clusterKey.substring(1);
487 clusterKey = clusterKey.trim();
488 if (clusterKey.equals(",") ) clusterKey=""; // print error if needed ( ... ),)
491 if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
492 && (partitionKey.equalsIgnoreCase(clusterKey) ||
493 clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) )
495 logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey + " and primary key=" + primaryKey );
496 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
497 "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ") of"
498 + " primary key=" + primaryKey)
503 if (partitionKey.isEmpty() ) primaryKey="";
504 else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")";
505 else primaryKey=" (" + partitionKey + ")," + clusterKey;
508 if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
510 } // end of length > 0
512 if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
513 && (partitionKey.equalsIgnoreCase(clusterKey) ||
514 clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) )
516 logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey);
517 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
518 "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ")")
522 if (partitionKey.isEmpty() ) primaryKey="";
523 else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")";
524 else primaryKey=" (" + partitionKey + ")," + clusterKey;
527 if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
529 fieldsString.append(")");
531 } // end of last field check
534 // information about the name-value style properties
535 Map<String, Object> propertiesMap = tableObj.getProperties();
536 StringBuilder propertiesString = new StringBuilder();
537 if (propertiesMap != null) {
539 for (Map.Entry<String, Object> entry : propertiesMap.entrySet()) {
540 Object ot = entry.getValue();
541 String value = ot + "";
542 if (ot instanceof String) {
543 value = "'" + value + "'";
544 } else if (ot instanceof Map) {
545 @SuppressWarnings("unchecked")
546 Map<String, Object> otMap = (Map<String, Object>) ot;
547 value = "{" + MusicUtil.jsonMaptoSqlString(otMap, ",") + "}";
550 propertiesString.append(entry.getKey() + "=" + value + "");
551 if (counter != propertiesMap.size() - 1)
552 propertiesString.append(" AND ");
554 counter = counter + 1;
558 String clusteringOrder = tableObj.getClusteringOrder();
560 if (clusteringOrder != null && !(clusteringOrder.isEmpty())) {
561 String[] arrayClusterOrder = clusteringOrder.split("[,]+");
563 for (int i = 0; i < arrayClusterOrder.length; i++) {
564 String[] clusterS = arrayClusterOrder[i].trim().split("[ ]+");
565 if ( (clusterS.length ==2) && (clusterS[1].equalsIgnoreCase("ASC") || clusterS[1].equalsIgnoreCase("DESC"))) {
568 return response.status(Status.BAD_REQUEST)
569 .entity(new JsonResponse(ResultType.FAILURE)
570 .setError("createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname order; please correct clusteringOrder:"+ clusteringOrder+".")
573 // add validation for column names in cluster key
576 if (!(clusterKey.isEmpty())) {
577 clusteringOrder = "CLUSTERING ORDER BY (" +clusteringOrder +")";
578 //cjc check if propertiesString.length() >0 instead propertiesMap
579 if (propertiesMap != null) {
580 propertiesString.append(" AND "+ clusteringOrder);
582 propertiesString.append(clusteringOrder);
585 logger.warn("Skipping clustering order=("+clusteringOrder+ ") since clustering key is empty ");
589 queryObject.appendQueryString(
590 "CREATE TABLE " + keyspace + "." + tablename + " " + fieldsString);
593 if (propertiesString != null && propertiesString.length()>0 )
594 queryObject.appendQueryString(" WITH " + propertiesString);
595 queryObject.appendQueryString(";");
596 ResultType result = ResultType.FAILURE;
598 result = MusicCore.createTable(keyspace, tablename, queryObject, consistency);
599 } catch (MusicServiceException ex) {
600 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.MUSICSERVICEERROR);
601 response.status(Status.BAD_REQUEST);
602 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
604 if ( result.equals(ResultType.FAILURE) ) {
605 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Error Creating Table " + tablename).toMap()).build();
607 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("TableName " + tablename.trim() + " Created under keyspace " + keyspace.trim()).toMap()).build();
609 EELFLoggerDelegate.mdcRemove("keyspace");
622 @Path("/{keyspace: .*}/tables/{tablename: .*}/index/{field: .*}")
623 @ApiOperation(value = "Create Index", response = String.class)
624 @Produces(MediaType.APPLICATION_JSON)
625 public Response createIndex(
626 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
627 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
628 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
629 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
630 @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns,
631 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
632 @ApiParam(value = "Keyspace Name",required = true) @PathParam("keyspace") String keyspace,
633 @ApiParam(value = "Table Name",required = true) @PathParam("tablename") String tablename,
634 @ApiParam(value = "Field Name",required = true) @PathParam("field") String fieldName,
635 @Context UriInfo info) throws Exception {
637 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
638 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty()) || (fieldName == null || fieldName.isEmpty())){
639 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
640 .setError("one or more path parameters are not set, please check and try again")
643 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
644 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
645 String userId = userCredentials.get(MusicUtil.USERID);
646 String password = userCredentials.get(MusicUtil.PASSWORD);
647 Map<String, Object> authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspace,aid, "createIndex");
648 if (authMap.containsKey("aid"))
649 authMap.remove("aid");
650 if (!authMap.isEmpty()) {
651 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGINFO ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
652 response.status(Status.UNAUTHORIZED);
653 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
655 MultivaluedMap<String, String> rowParams = info.getQueryParameters();
656 String indexName = "";
657 if (rowParams.getFirst("index_name") != null)
658 indexName = rowParams.getFirst("index_name");
659 PreparedQueryObject query = new PreparedQueryObject();
660 query.appendQueryString("Create index if not exists " + indexName + " on " + keyspace + "."
661 + tablename + " (" + fieldName + ");");
663 ResultType result = ResultType.FAILURE;
665 result = MusicCore.nonKeyRelatedPut(query, "eventual");
666 } catch (MusicServiceException ex) {
667 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
668 response.status(Status.BAD_REQUEST);
669 return response.entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
671 if ( result.equals(ResultType.SUCCESS) ) {
672 return response.status(Status.OK).entity(new JsonResponse(result).setMessage("Index Created on " + keyspace+"."+tablename+"."+fieldName).toMap()).build();
674 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Unknown Error in create index.").toMap()).build();
677 EELFLoggerDelegate.mdcRemove("keyspace");
690 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
691 @ApiOperation(value = "Insert Into Table", response = String.class)
692 @Consumes(MediaType.APPLICATION_JSON)
693 @Produces(MediaType.APPLICATION_JSON)
694 public Response insertIntoTable(
695 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
696 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
697 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
698 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
699 @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns,
700 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
702 @ApiParam(value = "Keyspace Name",
703 required = true) @PathParam("keyspace") String keyspace,
704 @ApiParam(value = "Table Name",
705 required = true) @PathParam("tablename") String tablename) {
707 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
708 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
709 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
710 .setError("one or more path parameters are not set, please check and try again")
713 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
714 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
715 String userId = userCredentials.get(MusicUtil.USERID);
716 String password = userCredentials.get(MusicUtil.PASSWORD);
717 Map<String, Object> authMap = null;
720 authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspace,
721 aid, "insertIntoTable");
722 } catch (Exception e) {
723 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGINFO ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
724 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
726 if (authMap.containsKey("aid"))
727 authMap.remove("aid");
728 if (!authMap.isEmpty()) {
729 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGINFO ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
730 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
733 Map<String, Object> valuesMap = insObj.getValues();
734 PreparedQueryObject queryObject = new PreparedQueryObject();
735 TableMetadata tableInfo = null;
737 tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
738 if(tableInfo == null) {
739 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Table name doesn't exists. Please check the table name.").toMap()).build();
741 } catch (MusicServiceException e) {
742 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
743 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
745 String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName();
746 StringBuilder fieldsString = new StringBuilder("(vector_ts,");
748 String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis());
749 StringBuilder valueString = new StringBuilder("(" + "?" + ",");
750 queryObject.addValue(vectorTs);
752 String primaryKey = "";
753 Map<String, byte[]> objectMap = insObj.getObjectMap();
754 for (Map.Entry<String, Object> entry : valuesMap.entrySet()) {
755 fieldsString.append("" + entry.getKey());
756 Object valueObj = entry.getValue();
757 if (primaryKeyName.equals(entry.getKey())) {
758 primaryKey = entry.getValue() + "";
759 primaryKey = primaryKey.replace("'", "''");
761 DataType colType = null;
763 colType = tableInfo.getColumn(entry.getKey()).getType();
764 } catch(NullPointerException ex) {
765 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() +" Invalid column name : "+entry.getKey(), AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
766 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap()).build();
769 Object formattedValue = null;
771 formattedValue = MusicUtil.convertToActualDataType(colType, valueObj);
772 } catch (Exception e) {
773 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
775 valueString.append("?");
777 queryObject.addValue(formattedValue);
779 if (counter == valuesMap.size() - 1) {
780 fieldsString.append(")");
781 valueString.append(")");
783 fieldsString.append(",");
784 valueString.append(",");
786 counter = counter + 1;
790 if(objectMap != null) {
791 for (Map.Entry<String, byte[]> entry : objectMap.entrySet()) {
793 fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ",");
794 valueString.replace(valueString.length()-1, valueString.length(), ",");
796 fieldsString.append("" + entry.getKey());
797 byte[] valueObj = entry.getValue();
798 if (primaryKeyName.equals(entry.getKey())) {
799 primaryKey = entry.getValue() + "";
800 primaryKey = primaryKey.replace("'", "''");
803 DataType colType = tableInfo.getColumn(entry.getKey()).getType();
805 ByteBuffer formattedValue = null;
807 if(colType.toString().toLowerCase().contains("blob"))
808 formattedValue = MusicUtil.convertToActualDataType(colType, valueObj);
810 valueString.append("?");
812 queryObject.addValue(formattedValue);
813 counter = counter + 1;
814 /*if (counter == valuesMap.size() - 1) {
815 fieldsString.append(")");
816 valueString.append(")");
818 fieldsString.append(",");
819 valueString.append(",");
823 if(primaryKey == null || primaryKey.length() <= 0) {
824 logger.error(EELFLoggerDelegate.errorLogger, "Some required partition key parts are missing: "+primaryKeyName );
825 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Some required partition key parts are missing: "+primaryKeyName).toMap()).build();
828 fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ")");
829 valueString.replace(valueString.length()-1, valueString.length(), ")");
831 queryObject.appendQueryString("INSERT INTO " + keyspace + "." + tablename + " "
832 + fieldsString + " VALUES " + valueString);
834 String ttl = insObj.getTtl();
835 String timestamp = insObj.getTimestamp();
837 if ((ttl != null) && (timestamp != null)) {
838 logger.info(EELFLoggerDelegate.applicationLogger, "both there");
839 queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?");
840 queryObject.addValue(Integer.parseInt(ttl));
841 queryObject.addValue(Long.parseLong(timestamp));
844 if ((ttl != null) && (timestamp == null)) {
845 logger.info(EELFLoggerDelegate.applicationLogger, "ONLY TTL there");
846 queryObject.appendQueryString(" USING TTL ?");
847 queryObject.addValue(Integer.parseInt(ttl));
850 if ((ttl == null) && (timestamp != null)) {
851 logger.info(EELFLoggerDelegate.applicationLogger, "ONLY timestamp there");
852 queryObject.appendQueryString(" USING TIMESTAMP ?");
853 queryObject.addValue(Long.parseLong(timestamp));
856 queryObject.appendQueryString(";");
858 ReturnType result = null;
859 String consistency = insObj.getConsistencyInfo().get("type");
860 if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && insObj.getConsistencyInfo().get("consistency") != null) {
861 if(MusicUtil.isValidConsistency(insObj.getConsistencyInfo().get("consistency")))
862 queryObject.setConsistency(insObj.getConsistencyInfo().get("consistency"));
864 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
866 queryObject.setOperation("insert");
868 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) {
869 result = MusicCore.eventualPut(queryObject);
870 } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
871 String lockId = insObj.getConsistencyInfo().get("lockId");
873 logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
874 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
875 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
876 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
878 result = MusicCore.criticalPut(keyspace, tablename, primaryKey, queryObject, lockId,null);
879 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
881 result = MusicCore.atomicPut(keyspace, tablename, primaryKey, queryObject, null);
884 else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) {
885 result = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, primaryKey, queryObject, null);
888 } catch (Exception ex) {
889 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
890 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
894 logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
895 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build();
896 }else if(result.getResult() == ResultType.FAILURE) {
897 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result.getResult()).setError(result.getMessage()).toMap()).build();
899 return response.status(Status.OK).entity(new JsonResponse(result.getResult()).setMessage("Insert Successful").toMap()).build();
901 EELFLoggerDelegate.mdcRemove("keyspace");
912 * @throws MusicServiceException
913 * @throws MusicQueryException
917 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
918 @ApiOperation(value = "Update Table", response = String.class)
919 @Consumes(MediaType.APPLICATION_JSON)
920 @Produces(MediaType.APPLICATION_JSON)
921 public Response updateTable(
922 @ApiParam(value = "Major Version",
923 required = true) @PathParam("version") String version,
924 @ApiParam(value = "Minor Version",
925 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
926 @ApiParam(value = "Patch Version",
927 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
928 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
929 @ApiParam(value = "Application namespace",
930 required = true) @HeaderParam(NS) String ns,
931 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
932 JsonUpdate updateObj,
933 @ApiParam(value = "Keyspace Name",
934 required = true) @PathParam("keyspace") String keyspace,
935 @ApiParam(value = "Table Name",
936 required = true) @PathParam("tablename") String tablename,
937 @Context UriInfo info) throws MusicQueryException, MusicServiceException {
939 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
940 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
941 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
942 .setError("one or more path parameters are not set, please check and try again")
945 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
946 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
947 String userId = userCredentials.get(MusicUtil.USERID);
948 String password = userCredentials.get(MusicUtil.PASSWORD);
949 Map<String, Object> authMap;
951 authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspace,
953 } catch (Exception e) {
954 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
955 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
957 if (authMap.containsKey("aid"))
958 authMap.remove("aid");
959 if (!authMap.isEmpty()) {
960 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
961 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
963 long startTime = System.currentTimeMillis();
964 String operationId = UUID.randomUUID().toString();// just for infoging
966 String consistency = updateObj.getConsistencyInfo().get("type");
968 logger.info(EELFLoggerDelegate.applicationLogger, "--------------Music " + consistency
969 + " update-" + operationId + "-------------------------");
970 // obtain the field value pairs of the update
972 PreparedQueryObject queryObject = new PreparedQueryObject();
973 Map<String, Object> valuesMap = updateObj.getValues();
975 TableMetadata tableInfo;
977 tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
978 } catch (MusicServiceException e) {
979 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
980 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
982 if (tableInfo == null) {
983 logger.error(EELFLoggerDelegate.errorLogger,"Table information not found. Please check input for table name= "+tablename, AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
984 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
985 .setError("Table information not found. Please check input for table name= "
986 + keyspace + "." + tablename).toMap()).build();
989 String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis());
990 StringBuilder fieldValueString = new StringBuilder("vector_ts=?,");
991 queryObject.addValue(vectorTs);
993 for (Map.Entry<String, Object> entry : valuesMap.entrySet()) {
994 Object valueObj = entry.getValue();
995 DataType colType = null;
997 colType = tableInfo.getColumn(entry.getKey()).getType();
998 } catch(NullPointerException ex) {
999 logger.error(EELFLoggerDelegate.errorLogger, "Invalid column name : "+entry.getKey());
1000 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap()).build();
1002 Object valueString = null;
1004 valueString = MusicUtil.convertToActualDataType(colType, valueObj);
1005 } catch (Exception e) {
1006 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
1008 fieldValueString.append(entry.getKey() + "= ?");
1009 queryObject.addValue(valueString);
1010 if (counter != valuesMap.size() - 1)
1011 fieldValueString.append(",");
1012 counter = counter + 1;
1014 String ttl = updateObj.getTtl();
1015 String timestamp = updateObj.getTimestamp();
1017 queryObject.appendQueryString("UPDATE " + keyspace + "." + tablename + " ");
1018 if ((ttl != null) && (timestamp != null)) {
1020 logger.info("both there");
1021 queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?");
1022 queryObject.addValue(Integer.parseInt(ttl));
1023 queryObject.addValue(Long.parseLong(timestamp));
1026 if ((ttl != null) && (timestamp == null)) {
1027 logger.info("ONLY TTL there");
1028 queryObject.appendQueryString(" USING TTL ?");
1029 queryObject.addValue(Integer.parseInt(ttl));
1032 if ((ttl == null) && (timestamp != null)) {
1033 logger.info("ONLY timestamp there");
1034 queryObject.appendQueryString(" USING TIMESTAMP ?");
1035 queryObject.addValue(Long.parseLong(timestamp));
1037 // get the row specifier
1038 RowIdentifier rowId = null;
1040 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
1041 if(rowId == null || rowId.primarKeyValue.isEmpty()) {
1042 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1043 .setError("Mandatory WHERE clause is missing. Please check the input request.").toMap()).build();
1045 } catch (MusicServiceException ex) {
1046 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1047 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1050 queryObject.appendQueryString(
1051 " SET " + fieldValueString + " WHERE " + rowId.rowIdString + ";");
1053 // get the conditional, if any
1054 Condition conditionInfo;
1055 if (updateObj.getConditions() == null)
1056 conditionInfo = null;
1057 else {// to avoid parsing repeatedly, just send the select query to
1059 PreparedQueryObject selectQuery = new PreparedQueryObject();
1060 selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE "
1061 + rowId.rowIdString + ";");
1062 selectQuery.addValue(rowId.primarKeyValue);
1063 conditionInfo = new Condition(updateObj.getConditions(), selectQuery);
1066 ReturnType operationResult = null;
1067 long jsonParseCompletionTime = System.currentTimeMillis();
1069 if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && updateObj.getConsistencyInfo().get("consistency") != null) {
1070 if(MusicUtil.isValidConsistency(updateObj.getConsistencyInfo().get("consistency")))
1071 queryObject.setConsistency(updateObj.getConsistencyInfo().get("consistency"));
1073 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
1075 queryObject.setOperation("update");
1076 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL))
1077 operationResult = MusicCore.eventualPut(queryObject);
1078 else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
1079 String lockId = updateObj.getConsistencyInfo().get("lockId");
1080 if(lockId == null) {
1081 logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
1082 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
1083 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
1084 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
1086 operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue,
1087 queryObject, lockId, conditionInfo);
1088 } else if (consistency.equalsIgnoreCase("atomic_delete_lock")) {
1089 // this function is mainly for the benchmarks
1091 operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename,
1092 rowId.primarKeyValue, queryObject, conditionInfo);
1093 } catch (MusicLockingException e) {
1094 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1095 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
1097 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
1099 operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue,
1100 queryObject, conditionInfo);
1101 } catch (MusicLockingException e) {
1102 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1103 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
1105 }else if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) {
1106 operationResult = MusicCore.eventualPut_nb(queryObject, keyspace, tablename, rowId.primarKeyValue);
1108 long actualUpdateCompletionTime = System.currentTimeMillis();
1110 long endTime = System.currentTimeMillis();
1111 String timingString = "Time taken in ms for Music " + consistency + " update-" + operationId
1112 + ":" + "|total operation time:" + (endTime - startTime)
1113 + "|json parsing time:" + (jsonParseCompletionTime - startTime)
1114 + "|update time:" + (actualUpdateCompletionTime - jsonParseCompletionTime)
1117 if (operationResult != null && operationResult.getTimingInfo() != null) {
1118 String lockManagementTime = operationResult.getTimingInfo();
1119 timingString = timingString + lockManagementTime;
1121 logger.info(EELFLoggerDelegate.applicationLogger, timingString);
1123 if (operationResult==null) {
1124 logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1125 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build();
1127 if ( operationResult.getResult() == ResultType.SUCCESS ) {
1128 return response.status(Status.OK).entity(new JsonResponse(operationResult.getResult()).setMessage(operationResult.getMessage()).toMap()).build();
1130 logger.error(EELFLoggerDelegate.errorLogger,operationResult.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1131 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(operationResult.getResult()).setError(operationResult.getMessage()).toMap()).build();
1134 EELFLoggerDelegate.mdcRemove("keyspace");
1145 * @throws MusicServiceException
1146 * @throws MusicQueryException
1150 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
1151 @ApiOperation(value = "Delete From table", response = String.class)
1152 @Consumes(MediaType.APPLICATION_JSON)
1153 @Produces(MediaType.APPLICATION_JSON)
1154 public Response deleteFromTable(
1155 @ApiParam(value = "Major Version",
1156 required = true) @PathParam("version") String version,
1157 @ApiParam(value = "Minor Version",
1158 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1159 @ApiParam(value = "Patch Version",
1160 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1161 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
1162 @ApiParam(value = "Application namespace",
1163 required = true) @HeaderParam(NS) String ns,
1164 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1166 @ApiParam(value = "Keyspace Name",
1167 required = true) @PathParam("keyspace") String keyspace,
1168 @ApiParam(value = "Table Name",
1169 required = true) @PathParam("tablename") String tablename,
1170 @Context UriInfo info) throws MusicQueryException, MusicServiceException {
1172 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1173 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1174 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1175 .setError("one or more path parameters are not set, please check and try again")
1178 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
1179 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
1180 String userId = userCredentials.get(MusicUtil.USERID);
1181 String password = userCredentials.get(MusicUtil.PASSWORD);
1182 Map<String, Object> authMap = null;
1184 authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspace,
1185 aid, "deleteFromTable");
1186 } catch (Exception e) {
1187 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
1188 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
1190 if (authMap.containsKey("aid"))
1191 authMap.remove("aid");
1192 if (!authMap.isEmpty()) {
1193 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
1194 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
1196 if(delObj == null) {
1197 logger.error(EELFLoggerDelegate.errorLogger,"Required HTTP Request body is missing.", AppMessages.MISSINGDATA ,ErrorSeverity.WARN, ErrorTypes.DATAERROR);
1198 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Required HTTP Request body is missing.").toMap()).build();
1200 PreparedQueryObject queryObject = new PreparedQueryObject();
1201 StringBuilder columnString = new StringBuilder();
1204 ArrayList<String> columnList = delObj.getColumns();
1205 if (columnList != null) {
1206 for (String column : columnList) {
1207 columnString.append(column);
1208 if (counter != columnList.size() - 1)
1209 columnString.append(",");
1210 counter = counter + 1;
1214 // get the row specifier
1215 RowIdentifier rowId = null;
1217 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
1218 } catch (MusicServiceException ex) {
1219 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1220 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1222 String rowSpec = rowId.rowIdString.toString();
1224 if ((columnList != null) && (!rowSpec.isEmpty())) {
1225 queryObject.appendQueryString("DELETE " + columnString + " FROM " + keyspace + "."
1226 + tablename + " WHERE " + rowSpec + ";");
1229 if ((columnList == null) && (!rowSpec.isEmpty())) {
1230 queryObject.appendQueryString("DELETE FROM " + keyspace + "." + tablename + " WHERE "
1234 if ((columnList != null) && (rowSpec.isEmpty())) {
1235 queryObject.appendQueryString(
1236 "DELETE " + columnString + " FROM " + keyspace + "." + rowSpec + ";");
1238 // get the conditional, if any
1239 Condition conditionInfo;
1240 if (delObj.getConditions() == null)
1241 conditionInfo = null;
1242 else {// to avoid parsing repeatedly, just send the select query to
1244 PreparedQueryObject selectQuery = new PreparedQueryObject();
1245 selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE "
1246 + rowId.rowIdString + ";");
1247 selectQuery.addValue(rowId.primarKeyValue);
1248 conditionInfo = new Condition(delObj.getConditions(), selectQuery);
1251 String consistency = delObj.getConsistencyInfo().get("type");
1254 if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && delObj.getConsistencyInfo().get("consistency")!=null) {
1256 if(MusicUtil.isValidConsistency(delObj.getConsistencyInfo().get("consistency")))
1257 queryObject.setConsistency(delObj.getConsistencyInfo().get("consistency"));
1259 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
1262 ReturnType operationResult = null;
1263 queryObject.setOperation("delete");
1265 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL))
1266 operationResult = MusicCore.eventualPut(queryObject);
1267 else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
1268 String lockId = delObj.getConsistencyInfo().get("lockId");
1269 if(lockId == null) {
1270 logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
1271 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
1272 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
1273 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
1275 operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue,
1276 queryObject, lockId, conditionInfo);
1277 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
1278 operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue,
1279 queryObject, conditionInfo);
1281 else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) {
1282 operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, rowId.primarKeyValue,
1283 queryObject, conditionInfo);
1284 }else if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) {
1286 operationResult = MusicCore.eventualPut_nb(queryObject, keyspace, tablename, rowId.primarKeyValue);
1288 } catch (MusicLockingException e) {
1289 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1290 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1291 .setError("Unable to perform Delete operation. Exception from music").toMap()).build();
1293 if (operationResult==null) {
1294 logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1295 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build();
1297 if (operationResult.getResult().equals(ResultType.SUCCESS)) {
1298 return response.status(Status.OK).entity(new JsonResponse(operationResult.getResult()).setMessage(operationResult.getMessage()).toMap()).build();
1300 logger.error(EELFLoggerDelegate.errorLogger,operationResult.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1301 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(operationResult.getMessage()).toMap()).build();
1304 EELFLoggerDelegate.mdcRemove("keyspace");
1316 @Path("/{keyspace: .*}/tables/{tablename: .*}")
1317 @ApiOperation(value = "Drop Table", response = String.class)
1318 @Produces(MediaType.APPLICATION_JSON)
1319 public Response dropTable(
1320 @ApiParam(value = "Major Version",
1321 required = true) @PathParam("version") String version,
1322 @ApiParam(value = "Minor Version",
1323 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1324 @ApiParam(value = "Patch Version",
1325 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1326 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
1327 @ApiParam(value = "Application namespace",
1328 required = true) @HeaderParam(NS) String ns,
1329 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1330 @ApiParam(value = "Keyspace Name",
1331 required = true) @PathParam("keyspace") String keyspace,
1332 @ApiParam(value = "Table Name",
1333 required = true) @PathParam("tablename") String tablename) throws Exception {
1335 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1336 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1337 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1338 .setError("one or more path parameters are not set, please check and try again")
1341 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
1342 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
1343 String userId = userCredentials.get(MusicUtil.USERID);
1344 String password = userCredentials.get(MusicUtil.PASSWORD);
1345 Map<String, Object> authMap =
1346 MusicAuthentication.autheticateUser(ns, userId, password, keyspace, aid, "dropTable");
1347 if (authMap.containsKey("aid"))
1348 authMap.remove("aid");
1349 if (!authMap.isEmpty()) {
1350 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
1351 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
1353 String consistency = "eventual";// for now this needs only eventual
1355 PreparedQueryObject query = new PreparedQueryObject();
1356 query.appendQueryString("DROP TABLE " + keyspace + "." + tablename + ";");
1358 return response.status(Status.OK).entity(new JsonResponse(MusicCore.nonKeyRelatedPut(query, consistency)).toMap()).build();
1359 } catch (MusicServiceException ex) {
1360 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1361 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1364 EELFLoggerDelegate.mdcRemove("keyspace");
1377 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows/criticalget")
1378 @ApiOperation(value = "Select Critical", response = Map.class)
1379 @Consumes(MediaType.APPLICATION_JSON)
1380 @Produces(MediaType.APPLICATION_JSON)
1381 public Response selectCritical(
1382 @ApiParam(value = "Major Version",
1383 required = true) @PathParam("version") String version,
1384 @ApiParam(value = "Minor Version",
1385 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1386 @ApiParam(value = "Patch Version",
1387 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1388 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
1389 @ApiParam(value = "Application namespace",
1390 required = true) @HeaderParam(NS) String ns,
1391 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1393 @ApiParam(value = "Keyspace Name",
1394 required = true) @PathParam("keyspace") String keyspace,
1395 @ApiParam(value = "Table Name",
1396 required = true) @PathParam("tablename") String tablename,
1397 @Context UriInfo info) throws Exception {
1399 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1400 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1401 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1402 .setError("one or more path parameters are not set, please check and try again")
1405 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
1406 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
1407 String userId = userCredentials.get(MusicUtil.USERID);
1408 String password = userCredentials.get(MusicUtil.PASSWORD);
1409 Map<String, Object> authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspace,aid, "selectCritical");
1410 if (authMap.containsKey("aid"))
1411 authMap.remove("aid");
1412 if (!authMap.isEmpty()) {
1413 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
1414 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
1416 String lockId = selObj.getConsistencyInfo().get("lockId");
1418 PreparedQueryObject queryObject = new PreparedQueryObject();
1420 RowIdentifier rowId = null;
1422 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
1423 } catch (MusicServiceException ex) {
1424 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1425 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1427 queryObject.appendQueryString(
1428 "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowId.rowIdString + ";");
1430 ResultSet results = null;
1432 String consistency = selObj.getConsistencyInfo().get("type");
1434 if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
1435 if(lockId == null) {
1436 logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
1437 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
1438 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
1439 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
1441 results = MusicCore.criticalGet(keyspace, tablename, rowId.primarKeyValue, queryObject,
1443 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
1444 results = MusicCore.atomicGet(keyspace, tablename, rowId.primarKeyValue, queryObject);
1447 else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) {
1448 results = MusicCore.atomicGetWithDeleteLock(keyspace, tablename, rowId.primarKeyValue, queryObject);
1450 if(results!=null && results.getAvailableWithoutFetching() >0) {
1451 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build();
1453 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setError("No data found").toMap()).build();
1456 EELFLoggerDelegate.mdcRemove("keyspace");
1469 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
1470 @ApiOperation(value = "Select All or Select Specific", response = Map.class)
1471 @Produces(MediaType.APPLICATION_JSON)
1472 public Response select(
1473 @ApiParam(value = "Major Version",
1474 required = true) @PathParam("version") String version,
1475 @ApiParam(value = "Minor Version",
1476 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1477 @ApiParam(value = "Patch Version",
1478 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1479 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
1480 @ApiParam(value = "Application namespace",
1481 required = true) @HeaderParam(NS) String ns,
1482 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1483 @ApiParam(value = "Keyspace Name",
1484 required = true) @PathParam("keyspace") String keyspace,
1485 @ApiParam(value = "Table Name",
1486 required = true) @PathParam("tablename") String tablename,
1487 @Context UriInfo info) throws Exception {
1489 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1490 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1491 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1492 .setError("one or more path parameters are not set, please check and try again")
1495 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
1496 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
1497 String userId = userCredentials.get(MusicUtil.USERID);
1498 String password = userCredentials.get(MusicUtil.PASSWORD);
1499 Map<String, Object> authMap =
1500 MusicAuthentication.autheticateUser(ns, userId, password, keyspace, aid, "select");
1501 if (authMap.containsKey("aid"))
1502 authMap.remove("aid");
1503 if (!authMap.isEmpty()) {
1504 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
1505 return response.status(Status.UNAUTHORIZED).entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
1507 PreparedQueryObject queryObject = new PreparedQueryObject();
1509 if (info.getQueryParameters().isEmpty())// select all
1510 queryObject.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + ";");
1512 int limit = -1; // do not limit the number of results
1514 queryObject = selectSpecificQuery(VERSION, minorVersion, patchVersion, aid, ns,
1515 userId, password, keyspace, tablename, info, limit);
1516 } catch (MusicServiceException ex) {
1517 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1518 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1523 ResultSet results = MusicCore.get(queryObject);
1524 if(results.getAvailableWithoutFetching() >0) {
1525 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build();
1527 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).setError("No data found").toMap()).build();
1528 } catch (MusicServiceException ex) {
1529 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.ERROR, ErrorTypes.MUSICSERVICEERROR);
1530 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1533 EELFLoggerDelegate.mdcRemove("keyspace");
1544 * @throws MusicServiceException
1546 public PreparedQueryObject selectSpecificQuery(String version, String minorVersion,
1547 String patchVersion, String aid, String ns, String userId, String password,
1548 String keyspace, String tablename, UriInfo info, int limit)
1549 throws MusicServiceException {
1551 PreparedQueryObject queryObject = new PreparedQueryObject();
1552 StringBuilder rowIdString = getRowIdentifier(keyspace, tablename, info.getQueryParameters(),
1553 queryObject).rowIdString;
1555 queryObject.appendQueryString(
1556 "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowIdString);
1559 queryObject.appendQueryString(" LIMIT " + limit);
1562 queryObject.appendQueryString(";");
1572 * @param queryObject
1574 * @throws MusicServiceException
1576 private RowIdentifier getRowIdentifier(String keyspace, String tablename,
1577 MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject)
1578 throws MusicServiceException {
1579 StringBuilder rowSpec = new StringBuilder();
1581 TableMetadata tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
1582 if (tableInfo == null) {
1583 logger.error(EELFLoggerDelegate.errorLogger,
1584 "Table information not found. Please check input for table name= "
1585 + keyspace + "." + tablename);
1586 throw new MusicServiceException(
1587 "Table information not found. Please check input for table name= "
1588 + keyspace + "." + tablename);
1590 StringBuilder primaryKey = new StringBuilder();
1591 for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) {
1592 String keyName = entry.getKey();
1593 List<String> valueList = entry.getValue();
1594 String indValue = valueList.get(0);
1595 DataType colType = null;
1596 Object formattedValue = null;
1598 colType = tableInfo.getColumn(entry.getKey()).getType();
1599 formattedValue = MusicUtil.convertToActualDataType(colType, indValue);
1600 } catch (Exception e) {
1601 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
1603 if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey()))
1604 primaryKey.append(indValue);
1605 rowSpec.append(keyName + "= ?");
1606 queryObject.addValue(formattedValue);
1607 if (counter != rowParams.size() - 1)
1608 rowSpec.append(" AND ");
1609 counter = counter + 1;
1611 return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject);