diff options
Diffstat (limited to 'src/main/java/org/onap/music/rest')
7 files changed, 2300 insertions, 0 deletions
diff --git a/src/main/java/org/onap/music/rest/RestMusicAdminAPI.java b/src/main/java/org/onap/music/rest/RestMusicAdminAPI.java new file mode 100755 index 00000000..87a3a1ba --- /dev/null +++ b/src/main/java/org/onap/music/rest/RestMusicAdminAPI.java @@ -0,0 +1,305 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.rest; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.datastore.jsonobjects.JsonOnboard; +import org.onap.music.main.CachingUtil; +import org.onap.music.main.MusicCore; +import org.onap.music.main.MusicUtil; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; + +@Path("/v{version: [0-9]+}/admin") +// @Path("/admin") +@Api(value = "Admin Api", hidden = true) +public class RestMusicAdminAPI { + private static EELFLogger logger = EELFManager.getInstance().getLogger(RestMusicAdminAPI.class); + + /* + * API to onboard an application with MUSIC. This is the mandatory first step. + * + */ + @POST + @Path("/onboardAppWithMusic") + @ApiOperation(value = "Onboard application", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Map<String, Object> onboardAppWithMusic(JsonOnboard jsonObj, + @Context HttpServletResponse response) throws Exception { + Map<String, Object> resultMap = new HashMap<>(); + String appName = jsonObj.getAppname(); + String userId = jsonObj.getUserId(); + String isAAF = jsonObj.getIsAAF(); + String password = jsonObj.getPassword(); + response.addHeader("X-latestVersion", MusicUtil.getVersion()); + if (appName == null || userId == null || isAAF == null || password == null) { + resultMap.put("Exception", + "Please check the request parameters. Some of the required values appName(ns), userId, password, isAAF are missing."); + return resultMap; + } + + PreparedQueryObject pQuery = new PreparedQueryObject(); + pQuery.appendQueryString( + "select uuid from admin.keyspace_master where application_name = ? allow filtering"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); + ResultSet rs = MusicCore.get(pQuery); + if (!rs.all().isEmpty()) { + resultMap.put("Exception", "Your application " + appName + + " has already been onboarded. Please contact admin."); + return resultMap; + } + + pQuery = new PreparedQueryObject(); + String uuid = CachingUtil.generateUUID(); + pQuery.appendQueryString( + "INSERT INTO admin.keyspace_master (uuid, keyspace_name, application_name, is_api, " + + "password, username, is_aaf) VALUES (?,?,?,?,?,?,?)"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), + MusicUtil.DEFAULTKEYSPACENAME)); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "True")); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), password)); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF)); + + String returnStr = MusicCore.eventualPut(pQuery).toString(); + if (returnStr.contains("Failure")) { + resultMap.put("Exception", + "Oops. Something wrong with onboarding process. Please retry later or contact admin."); + return resultMap; + } + CachingUtil.updateisAAFCache(appName, isAAF); + resultMap.put("Success", "Your application " + appName + " has been onboarded with MUSIC."); + resultMap.put("Generated AID", uuid); + return resultMap; + } + + + /* + * API to onboard an application with MUSIC. This is the mandatory first step. + * + */ + @GET + @Path("/onboardAppWithMusic") + @ApiOperation(value = "Onboard application", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Map<String, Object> getOnboardedInfo( + @ApiParam(value = "AID", required = true) @HeaderParam("aid") String uuid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam("ns") String appName, + @Context HttpServletResponse response) throws Exception { + Map<String, Object> resultMap = new HashMap<>(); + + response.addHeader("X-latestVersion", MusicUtil.getVersion()); + if (appName == null && uuid == null) { + resultMap.put("Exception", + "Please check the request parameters. Some of the required values appName(ns), aid are missing."); + return resultMap; + } + + PreparedQueryObject pQuery = new PreparedQueryObject(); + + String cql = "select uuid, keyspace_name from admin.keyspace_master where "; + if (appName != null) + cql = cql + "application_name = ?"; + else if (uuid != null) + cql = cql + "uuid = ?"; + cql = cql + " allow filtering"; + System.out.println("Get OnboardingInfo CQL: " + cql); + pQuery.appendQueryString(cql); + if (appName != null) + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); + else if (uuid != null) + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); + ResultSet rs = MusicCore.get(pQuery); + Iterator<Row> it = rs.iterator(); + while (it.hasNext()) { + Row row = (Row) it.next(); + resultMap.put(row.getString("keyspace_name"), row.getUUID("uuid")); + } + if (resultMap.isEmpty()) + resultMap.put("ERROR", "Application is not onboarded. Please contact admin."); + return resultMap; + } + + + @DELETE + @Path("/onboardAppWithMusic") + @ApiOperation(value = "Delete Onboard application", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Map<String, Object> deleteOnboardApp(JsonOnboard jsonObj, + @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @Context HttpServletResponse response) throws Exception { + Map<String, Object> resultMap = new HashMap<>(); + response.addHeader("X-latestVersion", MusicUtil.getVersion()); + String appName = jsonObj.getAppname(); + PreparedQueryObject pQuery = new PreparedQueryObject(); + long count = 0; + if (appName == null && aid == null) { + resultMap.put("Exception", "Please make sure either appName(ns) or Aid is present"); + return resultMap; + } + if (aid != null) { + pQuery.appendQueryString( + "select count(*) as count from admin.keyspace_master where uuid = ?"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), + UUID.fromString(aid))); + Row row = MusicCore.get(pQuery).one(); + if (row != null) { + count = row.getLong(0); + } + + if (count == 0) { + resultMap.put("Failure", "Please verify your AID."); + return resultMap; + } else { + pQuery = new PreparedQueryObject(); + pQuery.appendQueryString("delete from admin.keyspace_master where uuid = ?"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), + UUID.fromString(aid))); + String result = MusicCore.eventualPut(pQuery).toString(); + if (result.toLowerCase().contains("success")) { + resultMap.put("Success", "Your application has been deleted."); + return resultMap; + } else { + resultMap.put("Failure", "Please verify your AID."); + return resultMap; + } + } + + } + pQuery.appendQueryString( + "select uuid from admin.keyspace_master where application_name = ? allow filtering"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); + ResultSet rs = MusicCore.get(pQuery); + List<Row> rows = rs.all(); + String uuid = null; + if (rows.size() == 0) { + resultMap.put("Exception", + "Application not found. Please make sure Application exists."); + return resultMap; + } else if (rows.size() == 1) { + uuid = rows.get(0).getUUID("uuid").toString(); + pQuery = new PreparedQueryObject(); + pQuery.appendQueryString("delete from admin.keyspace_master where uuid = ?"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), + UUID.fromString(uuid))); + MusicCore.eventualPut(pQuery); + resultMap.put("Success", "Your application " + appName + " has been deleted."); + return resultMap; + } else { + resultMap.put("Failure", "Please provide UUID for the application."); + } + + return resultMap; + } + + + @PUT + @Path("/onboardAppWithMusic") + @ApiOperation(value = "Update Onboard application", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Map<String, Object> updateOnboardApp(JsonOnboard jsonObj, + @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @Context HttpServletResponse response) throws Exception { + Map<String, Object> resultMap = new HashMap<>(); + response.addHeader("X-latestVersion", MusicUtil.getVersion()); + String appName = jsonObj.getAppname(); + String userId = jsonObj.getUserId(); + String isAAF = jsonObj.getIsAAF(); + String password = jsonObj.getPassword(); + String consistency = "eventual"; + PreparedQueryObject pQuery = new PreparedQueryObject(); + + if (aid == null) { + resultMap.put("Exception", "Please make sure Aid is present"); + return resultMap; + } + + if (appName == null && userId == null && password == null && isAAF == null) { + resultMap.put("Exception", + "No parameters found to update. Please update atleast one parameter."); + return resultMap; + } + + StringBuilder preCql = new StringBuilder("UPDATE admin.keyspace_master SET "); + if (appName != null) + preCql.append(" application_name = ?,"); + if (userId != null) + preCql.append(" username = ?,"); + if (password != null) + preCql.append(" password = ?,"); + if (isAAF != null) + preCql.append(" is_aaf = ?,"); + preCql.deleteCharAt(preCql.length() - 1); + preCql.append(" WHERE uuid = ?"); + pQuery.appendQueryString(preCql.toString()); + if (appName != null) + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); + if (userId != null) + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); + if (password != null) + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), password)); + if (isAAF != null) + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF)); + + + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), UUID.fromString(aid))); + Boolean result = MusicCore.nonKeyRelatedPut(pQuery, consistency); + + if (result) { + resultMap.put("Success", "Your application has been updated successfully"); + } else { + resultMap.put("Exception", + "Oops. Spomething went wrong. Please make sure Aid is correct and application is onboarded"); + } + + return resultMap; + } +} diff --git a/src/main/java/org/onap/music/rest/RestMusicBmAPI.java b/src/main/java/org/onap/music/rest/RestMusicBmAPI.java new file mode 100644 index 00000000..90b82229 --- /dev/null +++ b/src/main/java/org/onap/music/rest/RestMusicBmAPI.java @@ -0,0 +1,313 @@ +/* + * ============LICENSE_START========================================== org.onap.music + * =================================================================== Copyright (c) 2017 AT&T + * Intellectual Property =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.rest; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.UriInfo; +import org.apache.log4j.Logger; +import org.onap.music.datastore.jsonobjects.JsonInsert; +import org.onap.music.datastore.jsonobjects.JsonOnboard; +import org.onap.music.datastore.jsonobjects.JsonUpdate; +import org.onap.music.main.CachingUtil; +import org.onap.music.main.MusicCore; +import org.onap.music.main.MusicUtil; +import org.onap.music.main.ResultType; +import org.onap.music.main.ReturnType; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import org.onap.music.datastore.PreparedQueryObject; +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.TableMetadata; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; + +/* + * These are functions created purely for benchmarking purposes. Commented out Swagger - This should + * be undocumented API + * + */ +@Path("/v{version: [0-9]+}/benchmarks/") +@Api(value = "Benchmark API", hidden = true) +public class RestMusicBmAPI { + private static EELFLogger logger = EELFManager.getInstance().getLogger(RestMusicBmAPI.class); + + // pure zk calls... + + /** + * + * @param nodeName + * @throws Exception + */ + @POST + @Path("/purezk/{name}") + @Consumes(MediaType.APPLICATION_JSON) + public void pureZkCreate(@PathParam("name") String nodeName) throws Exception { + MusicCore.pureZkCreate("/" + nodeName); + } + + + /** + * + * @param insObj + * @param nodeName + * @throws Exception + */ + @PUT + @Path("/purezk/{name}") + @Consumes(MediaType.APPLICATION_JSON) + public void pureZkUpdate(JsonInsert insObj, @PathParam("name") String nodeName) + throws Exception { + logger.info("--------------Zk normal update-------------------------"); + long start = System.currentTimeMillis(); + MusicCore.pureZkWrite(nodeName, insObj.serialize()); + long end = System.currentTimeMillis(); + logger.info("Total time taken for Zk normal update:" + (end - start) + " ms"); + } + + /** + * + * @param nodeName + * @return + * @throws Exception + */ + @GET + @Path("/purezk/{name}") + @Consumes(MediaType.TEXT_PLAIN) + public byte[] pureZkGet(@PathParam("name") String nodeName) throws Exception { + return MusicCore.pureZkRead(nodeName); + } + + /** + * + * @param insObj + * @param lockName + * @param nodeName + * @throws Exception + */ + @PUT + @Path("/purezk/atomic/{lockname}/{name}") + @Consumes(MediaType.APPLICATION_JSON) + public void pureZkAtomicPut(JsonInsert updateObj, @PathParam("lockname") String lockname, + @PathParam("name") String nodeName) throws Exception { + long startTime = System.currentTimeMillis(); + String operationId = UUID.randomUUID().toString();// just for debugging purposes. + String consistency = updateObj.getConsistencyInfo().get("type"); + + logger.info("--------------Zookeeper " + consistency + " update-" + operationId + + "-------------------------"); + + byte[] data = updateObj.serialize(); + long jsonParseCompletionTime = System.currentTimeMillis(); + + String lockId = MusicCore.createLockReference(lockname); + + long lockCreationTime = System.currentTimeMillis(); + + long leasePeriod = MusicUtil.getDefaultLockLeasePeriod(); + ReturnType lockAcqResult = MusicCore.acquireLockWithLease(lockname, lockId, leasePeriod); + long lockAcqTime = System.currentTimeMillis(); + long zkPutTime = 0, lockReleaseTime = 0; + + if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) { + logger.info("acquired lock with id " + lockId); + MusicCore.pureZkWrite(lockname, data); + zkPutTime = System.currentTimeMillis(); + boolean voluntaryRelease = true; + if (consistency.equals("atomic")) + MusicCore.releaseLock(lockId, voluntaryRelease); + else if (consistency.equals("atomic_delete_lock")) + MusicCore.deleteLock(lockname); + lockReleaseTime = System.currentTimeMillis(); + } else { + MusicCore.destroyLockRef(lockId); + } + + long actualUpdateCompletionTime = System.currentTimeMillis(); + + + long endTime = System.currentTimeMillis(); + + String lockingInfo = "|lock creation time:" + (lockCreationTime - jsonParseCompletionTime) + + "|lock accquire time:" + (lockAcqTime - lockCreationTime) + + "|zk put time:" + (zkPutTime - lockAcqTime); + + if (consistency.equals("atomic")) + lockingInfo = lockingInfo + "|lock release time:" + (lockReleaseTime - zkPutTime) + "|"; + else if (consistency.equals("atomic_delete_lock")) + lockingInfo = lockingInfo + "|lock delete time:" + (lockReleaseTime - zkPutTime) + "|"; + + String timingString = "Time taken in ms for Zookeeper " + consistency + " update-" + + operationId + ":" + "|total operation time:" + (endTime - startTime) + + "|json parsing time:" + (jsonParseCompletionTime - startTime) + + "|update time:" + (actualUpdateCompletionTime - jsonParseCompletionTime) + + lockingInfo; + + logger.info(timingString); + } + + /** + * + * @param insObj + * @param lockName + * @param nodeName + * @throws Exception + */ + @GET + @Path("/purezk/atomic/{lockname}/{name}") + @Consumes(MediaType.APPLICATION_JSON) + public void pureZkAtomicGet(JsonInsert insObj, @PathParam("lockname") String lockName, + @PathParam("name") String nodeName) throws Exception { + logger.info("--------------Zk atomic read-------------------------"); + long start = System.currentTimeMillis(); + String lockId = MusicCore.createLockReference(lockName); + long leasePeriod = MusicUtil.getDefaultLockLeasePeriod(); + ReturnType lockAcqResult = MusicCore.acquireLockWithLease(lockName, lockId, leasePeriod); + if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) { + logger.info("acquired lock with id " + lockId); + MusicCore.pureZkRead(nodeName); + boolean voluntaryRelease = true; + MusicCore.releaseLock(lockId, voluntaryRelease); + } else { + MusicCore.destroyLockRef(lockId); + } + + long end = System.currentTimeMillis(); + logger.info("Total time taken for Zk atomic read:" + (end - start) + " ms"); + } + + /** + * + * doing an update directly to cassa but through the rest api + * + * @param insObj + * @param keyspace + * @param tablename + * @param info + * @return + * @throws Exception + */ + @PUT + @Path("/cassa/keyspaces/{keyspace}/tables/{tablename}/rows") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public boolean updateTableCassa(JsonInsert insObj, @PathParam("keyspace") String keyspace, + @PathParam("tablename") String tablename, @Context UriInfo info) + throws Exception { + long startTime = System.currentTimeMillis(); + String operationId = UUID.randomUUID().toString();// just for debugging purposes. + String consistency = insObj.getConsistencyInfo().get("type"); + logger.info("--------------Cassandra " + consistency + " update-" + operationId + + "-------------------------"); + PreparedQueryObject queryObject = new PreparedQueryObject(); + Map<String, Object> valuesMap = insObj.getValues(); + TableMetadata tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename); + String vectorTs = "'" + Thread.currentThread().getId() + System.currentTimeMillis() + "'"; + String fieldValueString = "vector_ts= ? ,"; + queryObject.addValue(vectorTs); + + int counter = 0; + for (Map.Entry<String, Object> entry : valuesMap.entrySet()) { + Object valueObj = entry.getValue(); + DataType colType = tableInfo.getColumn(entry.getKey()).getType(); + Object valueString = MusicUtil.convertToActualDataType(colType, valueObj); + fieldValueString = fieldValueString + entry.getKey() + "= ?"; + queryObject.addValue(valueString); + if (counter != valuesMap.size() - 1) + fieldValueString = fieldValueString + ","; + counter = counter + 1; + } + + // get the row specifier + String rowSpec = ""; + counter = 0; + queryObject.appendQueryString("UPDATE " + keyspace + "." + tablename + " "); + MultivaluedMap<String, String> rowParams = info.getQueryParameters(); + String primaryKey = ""; + for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) { + String keyName = entry.getKey(); + List<String> valueList = entry.getValue(); + String indValue = valueList.get(0); + DataType colType = tableInfo.getColumn(entry.getKey()).getType(); + Object formattedValue = MusicUtil.convertToActualDataType(colType, indValue); + primaryKey = primaryKey + indValue; + rowSpec = rowSpec + keyName + "= ? "; + queryObject.addValue(formattedValue); + if (counter != rowParams.size() - 1) + rowSpec = rowSpec + " AND "; + counter = counter + 1; + } + + + String ttl = insObj.getTtl(); + String timestamp = insObj.getTimestamp(); + + if ((ttl != null) && (timestamp != null)) { + + logger.info("both there"); + queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?"); + queryObject.addValue(Integer.parseInt(ttl)); + queryObject.addValue(Long.parseLong(timestamp)); + } + + if ((ttl != null) && (timestamp == null)) { + logger.info("ONLY TTL there"); + queryObject.appendQueryString(" USING TTL ?"); + queryObject.addValue(Integer.parseInt(ttl)); + } + + if ((ttl == null) && (timestamp != null)) { + logger.info("ONLY timestamp there"); + queryObject.appendQueryString(" USING TIMESTAMP ?"); + queryObject.addValue(Long.parseLong(timestamp)); + } + queryObject.appendQueryString(" SET " + fieldValueString + " WHERE " + rowSpec + ";"); + + long jsonParseCompletionTime = System.currentTimeMillis(); + + boolean operationResult = true; + MusicCore.getDSHandle().executePut(queryObject, insObj.getConsistencyInfo().get("type")); + + long actualUpdateCompletionTime = System.currentTimeMillis(); + + long endTime = System.currentTimeMillis(); + + String timingString = "Time taken in ms for Cassandra " + consistency + " update-" + + operationId + ":" + "|total operation time:" + (endTime - startTime) + + "|json parsing time:" + (jsonParseCompletionTime - startTime) + + "|update time:" + (actualUpdateCompletionTime - jsonParseCompletionTime) + + "|"; + logger.info(timingString); + + return operationResult; + } + +} diff --git a/src/main/java/org/onap/music/rest/RestMusicDataAPI.java b/src/main/java/org/onap/music/rest/RestMusicDataAPI.java new file mode 100755 index 00000000..ba0f1a3b --- /dev/null +++ b/src/main/java/org/onap/music/rest/RestMusicDataAPI.java @@ -0,0 +1,1088 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.rest; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +// import java.util.logging.Level; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.UriInfo; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.datastore.jsonobjects.JsonDelete; +import org.onap.music.datastore.jsonobjects.JsonInsert; +import org.onap.music.datastore.jsonobjects.JsonKeySpace; +import org.onap.music.response.jsonobjects.JsonResponse; +import org.onap.music.datastore.jsonobjects.JsonTable; +import org.onap.music.datastore.jsonobjects.JsonUpdate; +import org.onap.music.main.CachingUtil; +import org.onap.music.main.MusicCore; +import org.onap.music.main.MusicUtil; +import org.onap.music.main.ResultType; +import org.onap.music.main.ReturnType; +import org.onap.music.main.MusicCore.Condition; +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.TableMetadata; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; + +@Path("/v{version: [0-9]+}/keyspaces") +@Api(value = "Data Api") +public class RestMusicDataAPI { + /* + * Header values for Versioning X-minorVersion *** - Used to request or communicate a MINOR + * version back from the client to the server, and from the server back to the client - This + * will be the MINOR version requested by the client, or the MINOR version of the last MAJOR + * version (if not specified by the client on the request) - Contains a single position value + * (e.g. if the full version is 1.24.5, X-minorVersion = "24") - Is optional for the client on + * request; however, this header should be provided if the client needs to take advantage of + * MINOR incremented version functionality - Is mandatory for the server on response + * + *** X-patchVersion *** - Used only to communicate a PATCH version in a response for + * troubleshooting purposes only, and will not be provided by the client on request - This will + * be the latest PATCH version of the MINOR requested by the client, or the latest PATCH version + * of the MAJOR (if not specified by the client on the request) - Contains a single position + * value (e.g. if the full version is 1.24.5, X-patchVersion = "5") - Is mandatory for the + * server on response + * + *** X-latestVersion *** - Used only to communicate an API's latest version - Is mandatory for the + * server on response, and shall include the entire version of the API (e.g. if the full version + * is 1.24.5, X-latestVersion = "1.24.5") - Used in the response to inform clients that they are + * not using the latest version of the API + * + */ + + + private static EELFLogger logger = EELFManager.getInstance().getLogger(RestMusicDataAPI.class); + private static String xLatestVersion = "X-latestVersion"; + + private class RowIdentifier { + public String primarKeyValue; + public StringBuilder rowIdString; + public PreparedQueryObject queryObject;// the string with all the row + // identifiers separated by AND + + public RowIdentifier(String primaryKeyValue, StringBuilder rowIdString, + PreparedQueryObject queryObject) { + this.primarKeyValue = primaryKeyValue; + this.rowIdString = rowIdString; + this.queryObject = queryObject; + } + } + + private String buildVersion(String major, String minor, String patch) { + if (minor != null) { + major += "." + minor; + if (patch != null) { + major += "." + patch; + } + } + return major; + } + + /** + * Create Keyspace REST + * + * @param kspObject + * @param keyspaceName + * @return + * @throws Exception + */ + @POST + @Path("/{name}") + @ApiOperation(value = "Create Keyspace", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Map<String, Object> createKeySpace( + @ApiParam(value = "Major Version", + required = true) @PathParam("version") String version, + @ApiParam(value = "Minor Version", + required = false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value = "Patch Version", + required = false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam("ns") String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam("userId") String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam("password") String password, + JsonKeySpace kspObject, + @ApiParam(value = "Keyspace Name", + required = true) @PathParam("name") String keyspaceName, + @Context HttpServletResponse response) throws Exception { + Map<String, Object> resultMap = CachingUtil.verifyOnboarding(ns, userId, password); + response.addHeader(xLatestVersion, MusicUtil.getVersion()); + if (!resultMap.isEmpty()) { + return resultMap; + } + + resultMap = MusicCore.autheticateUser(ns, userId, password, keyspaceName, aid, + "createKeySpace"); + String newAid = null; + if (!resultMap.isEmpty()) { + if (resultMap.containsKey("aid")) { + newAid = (String) resultMap.get("aid"); + } else + return resultMap; + } + + String consistency = MusicUtil.EVENTUAL;// for now this needs only eventual + // consistency + + PreparedQueryObject queryObject = new PreparedQueryObject(); + boolean result = false; + long start = System.currentTimeMillis(); + Map<String, Object> replicationInfo = kspObject.getReplicationInfo(); + String repString = "{" + MusicUtil.jsonMaptoSqlString(replicationInfo, ",") + "}"; + queryObject.appendQueryString( + "CREATE KEYSPACE " + keyspaceName + " WITH replication = " + repString); + if (kspObject.getDurabilityOfWrites() != null) { + queryObject.appendQueryString( + " AND durable_writes = " + kspObject.getDurabilityOfWrites()); + } + + queryObject.appendQueryString(";"); + long end = System.currentTimeMillis(); + logger.info("Time taken for setting up query in create keyspace:" + (end - start)); + + try { + result = MusicCore.nonKeyRelatedPut(queryObject, consistency); + logger.debug("resulta = " + result); + } catch (Exception e) { + logger.error(e.getMessage()); + + } + logger.debug("result = " + result); + if (!result) { + resultMap.put("Status", String.valueOf(result)); + resultMap.put("Exception", "Keyspace already exists. Please contact admin."); + if (resultMap.get("uuid").equals("new")) { + queryObject = new PreparedQueryObject(); + queryObject.appendQueryString( + "DELETE FROM admin.keyspace_master where uuid = " + newAid); + queryObject.appendQueryString(";"); + result = MusicCore.nonKeyRelatedPut(queryObject, consistency); + resultMap.remove("aid"); + resultMap.remove("uuid"); + return resultMap; + + } else { + queryObject = new PreparedQueryObject(); + queryObject.appendQueryString( + "UPDATE admin.keyspace_master SET keyspace_name=?,password=?,is_api=null where uuid = ?;"); + queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), + MusicUtil.DEFAULTKEYSPACENAME)); + queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), null)); + queryObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), newAid)); + result = MusicCore.nonKeyRelatedPut(queryObject, consistency); + resultMap.remove("aid"); + resultMap.remove("uuid"); + return resultMap; + } + + } + try { + queryObject = new PreparedQueryObject(); + queryObject.appendQueryString("CREATE ROLE IF NOT EXISTS '" + userId + + "' WITH PASSWORD = '" + password + "' AND LOGIN = true;"); + result = MusicCore.nonKeyRelatedPut(queryObject, consistency); + if (result) { + queryObject = new PreparedQueryObject(); + queryObject.appendQueryString("GRANT ALL PERMISSIONS on KEYSPACE " + keyspaceName + + " to " + userId); + queryObject.appendQueryString(";"); + result = MusicCore.nonKeyRelatedPut(queryObject, consistency); + } else { + resultMap.remove("uuid"); + resultMap.put("Exception", "Exception while creating user."); + return resultMap; + } + } catch (Exception e) { + logger.error(e.getMessage()); + } + resultMap.remove("uuid"); + if (CachingUtil.isAAFApplication(ns)) + resultMap.remove("aid"); + resultMap.put("Status", String.valueOf(result)); + return resultMap; + + } + + /** + * + * @param kspObject + * @param keyspaceName + * @return + * @throws Exception + */ + @DELETE + @Path("/{name}") + @ApiOperation(value = "Delete Keyspace", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Map<String, Object> dropKeySpace( + @ApiParam(value = "Major Version", + required = true) @PathParam("version") String version, + @ApiParam(value = "Minor Version", + required = false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value = "Patch Version", + required = false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam("ns") String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam("userId") String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam("password") String password, + JsonKeySpace kspObject, + @ApiParam(value = "Keyspace Name", + required = true) @PathParam("name") String keyspaceName, + @Context HttpServletResponse response) throws Exception { + Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, + keyspaceName, aid, "dropKeySpace"); + response.addHeader(xLatestVersion, MusicUtil.getVersion()); + if (resultMap.containsKey("aid")) + resultMap.remove("aid"); + if (!resultMap.isEmpty()) { + return resultMap; + } + + String consistency = MusicUtil.EVENTUAL;// for now this needs only eventual + // consistency + String appName = CachingUtil.getAppName(keyspaceName); + String uuid = CachingUtil.getUuidFromMusicCache(keyspaceName); + PreparedQueryObject pQuery = new PreparedQueryObject(); + pQuery.appendQueryString( + "select count(*) as count from admin.keyspace_master where application_name=? allow filtering;"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); + Row row = MusicCore.get(pQuery).one(); + long count = row.getLong(0); + + if (count == 0) { + resultMap.put("Exception", "Keyspace not found. Please make sure keyspace exists."); + return resultMap; + } else if (count == 1) { + pQuery = new PreparedQueryObject(); + pQuery.appendQueryString( + "UPDATE admin.keyspace_master SET keyspace_name=?,password=?,is_api=null where uuid = ?;"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), + MusicUtil.DEFAULTKEYSPACENAME)); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), null)); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); + MusicCore.nonKeyRelatedPut(pQuery, consistency); + } else { + pQuery = new PreparedQueryObject(); + pQuery.appendQueryString("delete from admin.keyspace_master where uuid = ?"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); + MusicCore.nonKeyRelatedPut(pQuery, consistency); + } + + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString("DROP KEYSPACE " + keyspaceName + ";"); + return new JsonResponse(MusicCore.nonKeyRelatedPut(queryObject, consistency), "", "") + .toMap(); + } + + /** + * + * @param tableObj + * @param keyspace + * @param tablename + * @return + * @throws Exception + */ + @POST + @Path("/{keyspace}/tables/{tablename}") + @ApiOperation(value = "Create Table", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Map<String, Object> createTable( + @ApiParam(value = "Major Version", + required = true) @PathParam("version") String version, + @ApiParam(value = "Minor Version", + required = false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value = "Patch Version", + required = false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam("ns") String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam("userId") String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam("password") String password, + JsonTable tableObj, + @ApiParam(value = "Keyspace Name", + required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Table Name", + required = true) @PathParam("tablename") String tablename, + @Context HttpServletResponse response) throws Exception { + Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace, + aid, "createTable"); + response.addHeader(xLatestVersion, MusicUtil.getVersion()); + if (resultMap.containsKey("aid")) + resultMap.remove("aid"); + if (!resultMap.isEmpty()) { + return resultMap; + } + String consistency = MusicUtil.EVENTUAL; + // for now this needs only eventual consistency + PreparedQueryObject queryObject = new PreparedQueryObject(); + boolean result = false; + // first read the information about the table fields + Map<String, String> fields = tableObj.getFields(); + StringBuilder fieldsString = new StringBuilder("(vector_ts text,"); + int counter = 0; + String primaryKey; + for (Map.Entry<String, String> entry : fields.entrySet()) { + fieldsString.append("" + entry.getKey() + " " + entry.getValue() + ""); + if (entry.getKey().equals("PRIMARY KEY")) { + primaryKey = entry.getValue().substring(entry.getValue().indexOf('(') + 1); + primaryKey = primaryKey.substring(0, primaryKey.indexOf(')')); + } + if (counter == fields.size() - 1) + fieldsString.append(")"); + else + fieldsString.append(","); + counter = counter + 1; + } + // information about the name-value style properties + Map<String, Object> propertiesMap = tableObj.getProperties(); + StringBuilder propertiesString = new StringBuilder(); + if (propertiesMap != null) { + counter = 0; + for (Map.Entry<String, Object> entry : propertiesMap.entrySet()) { + Object ot = entry.getValue(); + String value = ot + ""; + if (ot instanceof String) { + value = "'" + value + "'"; + } else if (ot instanceof Map) { + Map<String, Object> otMap = (Map<String, Object>) ot; + value = "{" + MusicUtil.jsonMaptoSqlString(otMap, ",") + "}"; + } + + propertiesString.append(entry.getKey() + "=" + value + ""); + if (counter != propertiesMap.size() - 1) + propertiesString.append(" AND "); + + counter = counter + 1; + } + } + + queryObject.appendQueryString("CREATE TABLE IF NOT EXISTS " + keyspace + "." + tablename + + " " + fieldsString); + + if (propertiesMap != null) + queryObject.appendQueryString(" WITH " + propertiesString); + + queryObject.appendQueryString(";"); + result = MusicCore.nonKeyRelatedPut(queryObject, consistency); + + return new JsonResponse(result, "", "").toMap(); + } + + /** + * + * @param keyspace + * @param tablename + * @param fieldName + * @param info + * @throws Exception + */ + @POST + @Path("/{keyspace}/tables/{tablename}/index/{field}") + @ApiOperation(value = "Create Index", response = String.class) + @Produces(MediaType.APPLICATION_JSON) + public Map<String, Object> createIndex( + @ApiParam(value = "Major Version", + required = true) @PathParam("version") String version, + @ApiParam(value = "Minor Version", + required = false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value = "Patch Version", + required = false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam("ns") String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam("userId") String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam("password") String password, + @ApiParam(value = "Keyspace Name", + required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Table Name", + required = true) @PathParam("tablename") String tablename, + @ApiParam(value = "Field Name", + required = true) @PathParam("field") String fieldName, + @Context UriInfo info, @Context HttpServletResponse response) throws Exception { + Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace, + aid, "createIndex"); + response.addHeader(xLatestVersion, MusicUtil.getVersion()); + if (resultMap.containsKey("aid")) + resultMap.remove("aid"); + if (!resultMap.isEmpty()) + return resultMap; + MultivaluedMap<String, String> rowParams = info.getQueryParameters(); + String indexName = ""; + if (rowParams.getFirst("index_name") != null) + indexName = rowParams.getFirst("index_name"); + PreparedQueryObject query = new PreparedQueryObject(); + query.appendQueryString("Create index " + indexName + " if not exists on " + keyspace + "." + + tablename + " (" + fieldName + ");"); + return new JsonResponse(MusicCore.nonKeyRelatedPut(query, "eventual"), "", "").toMap(); + + } + + /** + * + * @param insObj + * @param keyspace + * @param tablename + * @return + * @throws Exception + */ + @POST + @Path("/{keyspace}/tables/{tablename}/rows") + @ApiOperation(value = "Insert Into Table", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Map<String, Object> insertIntoTable( + @ApiParam(value = "Major Version", + required = true) @PathParam("version") String version, + @ApiParam(value = "Minor Version", + required = false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value = "Patch Version", + required = false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam("ns") String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam("userId") String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam("password") String password, + JsonInsert insObj, + @ApiParam(value = "Keyspace Name", + required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Table Name", + required = true) @PathParam("tablename") String tablename, + @Context HttpServletResponse response) throws Exception { + Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace, + aid, "insertIntoTable"); + response.addHeader(xLatestVersion, MusicUtil.getVersion()); + if (resultMap.containsKey("aid")) + resultMap.remove("aid"); + if (!resultMap.isEmpty()) { + return resultMap; + } + ReturnType result = null; + Map<String, Object> valuesMap = insObj.getValues(); + PreparedQueryObject queryObject = new PreparedQueryObject(); + TableMetadata tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename); + String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName(); + StringBuilder fieldsString = new StringBuilder("(vector_ts,"); + String vectorTs = + String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis()); + StringBuilder valueString = new StringBuilder("(" + "?" + ","); + queryObject.addValue(vectorTs); + int counter = 0; + String primaryKey = ""; + + for (Map.Entry<String, Object> entry : valuesMap.entrySet()) { + fieldsString.append("" + entry.getKey()); + Object valueObj = entry.getValue(); + if (primaryKeyName.equals(entry.getKey())) { + primaryKey = entry.getValue() + ""; + primaryKey = primaryKey.replace("'", "''"); + } + + DataType colType = tableInfo.getColumn(entry.getKey()).getType(); + + Object formattedValue = MusicUtil.convertToActualDataType(colType, valueObj); + valueString.append("?"); + queryObject.addValue(formattedValue); + + if (counter == valuesMap.size() - 1) { + fieldsString.append(")"); + valueString.append(")"); + } else { + fieldsString.append(","); + valueString.append(","); + } + counter = counter + 1; + } + + queryObject.appendQueryString("INSERT INTO " + keyspace + "." + tablename + " " + + fieldsString + " VALUES " + valueString); + + String ttl = insObj.getTtl(); + String timestamp = insObj.getTimestamp(); + + if ((ttl != null) && (timestamp != null)) { + logger.info("both there"); + queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?"); + queryObject.addValue(Integer.parseInt(ttl)); + queryObject.addValue(Long.parseLong(timestamp)); + } + + if ((ttl != null) && (timestamp == null)) { + logger.info("ONLY TTL there"); + queryObject.appendQueryString(" USING TTL ?"); + queryObject.addValue(Integer.parseInt(ttl)); + } + + if ((ttl == null) && (timestamp != null)) { + logger.info("ONLY timestamp there"); + queryObject.appendQueryString(" USING TIMESTAMP ?"); + queryObject.addValue(Long.parseLong(timestamp)); + } + + queryObject.appendQueryString(";"); + + String consistency = insObj.getConsistencyInfo().get("type"); + try { + if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) { + result = MusicCore.eventualPut(queryObject); + } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + String lockId = insObj.getConsistencyInfo().get("lockId"); + result = MusicCore.criticalPut(keyspace, tablename, primaryKey, queryObject, lockId, + null); + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + result = MusicCore.atomicPut(keyspace, tablename, primaryKey, queryObject, null); + + } + return (result != null) ? result.toMap() + : new ReturnType(ResultType.FAILURE, + "Null result - Please Contact admin").toMap(); + } catch (Exception ex) { + logger.error(ex.getMessage()); + return new ReturnType(ResultType.FAILURE, ex.getMessage()).toMap(); + } + } + + /** + * + * @param insObj + * @param keyspace + * @param tablename + * @param info + * @return + * @throws Exception + */ + @PUT + @Path("/{keyspace}/tables/{tablename}/rows") + @ApiOperation(value = "Update Table", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Map<String, Object> updateTable( + @ApiParam(value = "Major Version", + required = true) @PathParam("version") String version, + @ApiParam(value = "Minor Version", + required = false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value = "Patch Version", + required = false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam("ns") String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam("userId") String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam("password") String password, + JsonUpdate updateObj, + @ApiParam(value = "Keyspace Name", + required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Table Name", + required = true) @PathParam("tablename") String tablename, + @Context UriInfo info, @Context HttpServletResponse response) throws Exception { + Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace, + aid, "updateTable"); + response.addHeader(xLatestVersion, MusicUtil.getVersion()); + if (resultMap.containsKey("aid")) + resultMap.remove("aid"); + if (!resultMap.isEmpty()) { + return resultMap; + } + long startTime = System.currentTimeMillis(); + String operationId = UUID.randomUUID().toString();// just for infoging + // purposes. + String consistency = updateObj.getConsistencyInfo().get("type"); + logger.info("--------------Music " + consistency + " update-" + operationId + + "-------------------------"); + // obtain the field value pairs of the update + + PreparedQueryObject queryObject = new PreparedQueryObject(); + Map<String, Object> valuesMap = updateObj.getValues(); + + TableMetadata tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename); + String vectorTs = + String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis()); + StringBuilder fieldValueString = new StringBuilder("vector_ts=?,"); + queryObject.addValue(vectorTs); + int counter = 0; + for (Map.Entry<String, Object> entry : valuesMap.entrySet()) { + Object valueObj = entry.getValue(); + DataType colType = tableInfo.getColumn(entry.getKey()).getType(); + Object valueString = MusicUtil.convertToActualDataType(colType, valueObj); + fieldValueString.append(entry.getKey() + "= ?"); + queryObject.addValue(valueString); + if (counter != valuesMap.size() - 1) + fieldValueString.append(","); + counter = counter + 1; + } + String ttl = updateObj.getTtl(); + String timestamp = updateObj.getTimestamp(); + + queryObject.appendQueryString("UPDATE " + keyspace + "." + tablename + " "); + if ((ttl != null) && (timestamp != null)) { + + logger.info("both there"); + queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?"); + queryObject.addValue(Integer.parseInt(ttl)); + queryObject.addValue(Long.parseLong(timestamp)); + } + + if ((ttl != null) && (timestamp == null)) { + logger.info("ONLY TTL there"); + queryObject.appendQueryString(" USING TTL ?"); + queryObject.addValue(Integer.parseInt(ttl)); + } + + if ((ttl == null) && (timestamp != null)) { + logger.info("ONLY timestamp there"); + queryObject.appendQueryString(" USING TIMESTAMP ?"); + queryObject.addValue(Long.parseLong(timestamp)); + } + // get the row specifier + RowIdentifier rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), + queryObject); + + queryObject.appendQueryString( + " SET " + fieldValueString + " WHERE " + rowId.rowIdString + ";"); + + // get the conditional, if any + Condition conditionInfo; + if (updateObj.getConditions() == null) + conditionInfo = null; + else {// to avoid parsing repeatedly, just send the select query to + // obtain row + String selectQuery = "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + + rowId.rowIdString + ";"; + conditionInfo = new MusicCore.Condition(updateObj.getConditions(), selectQuery); + } + + ReturnType operationResult = null; + long jsonParseCompletionTime = System.currentTimeMillis(); + + if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) + operationResult = MusicCore.eventualPut(queryObject); + else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + String lockId = updateObj.getConsistencyInfo().get("lockId"); + operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue, + queryObject, lockId, conditionInfo); + } + else if (consistency.equalsIgnoreCase("atomic_delete_lock")) { + // this function is mainly for the benchmarks + operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, + rowId.primarKeyValue, queryObject, conditionInfo); + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue, + queryObject, conditionInfo); + } + long actualUpdateCompletionTime = System.currentTimeMillis(); + + long endTime = System.currentTimeMillis(); + String timingString = "Time taken in ms for Music " + consistency + " update-" + operationId + + ":" + "|total operation time:" + (endTime - startTime) + + "|json parsing time:" + (jsonParseCompletionTime - startTime) + + "|update time:" + (actualUpdateCompletionTime - jsonParseCompletionTime) + + "|"; + + if (operationResult != null && operationResult.getTimingInfo() != null) { + String lockManagementTime = operationResult.getTimingInfo(); + timingString = timingString + lockManagementTime; + } + logger.info(timingString); + return (operationResult != null) ? operationResult.toMap() + : new ReturnType(ResultType.FAILURE, "Null result - Please Contact admin") + .toMap(); + } + + /** + * + * @param delObj + * @param keyspace + * @param tablename + * @param info + * @return + * @throws Exception + */ + @DELETE + @Path("/{keyspace}/tables/{tablename}/rows") + @ApiOperation(value = "Delete From table", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Map<String, Object> deleteFromTable( + @ApiParam(value = "Major Version", + required = true) @PathParam("version") String version, + @ApiParam(value = "Minor Version", + required = false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value = "Patch Version", + required = false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam("ns") String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam("userId") String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam("password") String password, + JsonDelete delObj, + @ApiParam(value = "Keyspace Name", + required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Table Name", + required = true) @PathParam("tablename") String tablename, + @Context UriInfo info, @Context HttpServletResponse response) throws Exception { + Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace, + aid, "deleteFromTable"); + response.addHeader(xLatestVersion, MusicUtil.getVersion()); + if (resultMap.containsKey("aid")) + resultMap.remove("aid"); + if (!resultMap.isEmpty()) { + return resultMap; + } + PreparedQueryObject queryObject = new PreparedQueryObject(); + StringBuilder columnString = new StringBuilder(); + + int counter = 0; + ArrayList<String> columnList = delObj.getColumns(); + if (columnList != null) { + for (String column : columnList) { + columnString.append(column); + if (counter != columnList.size() - 1) + columnString.append(","); + counter = counter + 1; + } + } + + // get the row specifier + RowIdentifier rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), + queryObject); + String rowSpec = rowId.rowIdString.toString(); + + if ((columnList != null) && (!rowSpec.isEmpty())) { + queryObject.appendQueryString("DELETE " + columnString + " FROM " + keyspace + "." + + tablename + " WHERE " + rowSpec + ";"); + } + + if ((columnList == null) && (!rowSpec.isEmpty())) { + queryObject.appendQueryString("DELETE FROM " + keyspace + "." + tablename + " WHERE " + + rowSpec + ";"); + } + + if ((columnList != null) && (rowSpec.isEmpty())) { + queryObject.appendQueryString( + "DELETE " + columnString + " FROM " + keyspace + "." + rowSpec + ";"); + } + + // get the conditional, if any + Condition conditionInfo; + if (delObj.getConditions() == null) + conditionInfo = null; + else {// to avoid parsing repeatedly, just send the select query to + // obtain row + String selectQuery = "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + + rowId.rowIdString + ";"; + conditionInfo = new MusicCore.Condition(delObj.getConditions(), selectQuery); + } + + String consistency = delObj.getConsistencyInfo().get("type"); + + ReturnType operationResult = null; + + if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) + operationResult = MusicCore.eventualPut(queryObject); + else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + String lockId = delObj.getConsistencyInfo().get("lockId"); + operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue, + queryObject, lockId, conditionInfo); + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue, + queryObject, conditionInfo); + } + try { + return operationResult.toMap(); + } catch (NullPointerException e) { + return new ReturnType(ResultType.FAILURE, e.getMessage()).toMap(); + } + } + + /** + * + * @param tabObj + * @param keyspace + * @param tablename + * @throws Exception + */ + @DELETE + @Path("/{keyspace}/tables/{tablename}") + @ApiOperation(value = "Drop Table", response = String.class) + + public Map<String, Object> dropTable( + @ApiParam(value = "Major Version", + required = true) @PathParam("version") String version, + @ApiParam(value = "Minor Version", + required = false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value = "Patch Version", + required = false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam("ns") String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam("userId") String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam("password") String password, + JsonTable tabObj, + @ApiParam(value = "Keyspace Name", + required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Table Name", + required = true) @PathParam("tablename") String tablename, + @Context HttpServletResponse response) throws Exception { + Map<String, Object> resultMap = + MusicCore.autheticateUser(ns, userId, password, keyspace, aid, "dropTable"); + response.addHeader(xLatestVersion, MusicUtil.getVersion()); + if (resultMap.containsKey("aid")) + resultMap.remove("aid"); + if (!resultMap.isEmpty()) { + return resultMap; + } + String consistency = "eventual";// for now this needs only eventual + // consistency + PreparedQueryObject query = new PreparedQueryObject(); + query.appendQueryString("DROP TABLE IF EXISTS " + keyspace + "." + tablename + ";"); + return new JsonResponse(MusicCore.nonKeyRelatedPut(query, consistency), "", "").toMap(); + } + + /** + * + * @param selObj + * @param keyspace + * @param tablename + * @param info + * @return + */ + @PUT + @Path("/{keyspace}/tables/{tablename}/rows/criticalget") + @ApiOperation(value = "Select Critical", response = Map.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Map<String, HashMap<String, Object>> selectCritical( + @ApiParam(value = "Major Version", + required = true) @PathParam("version") String version, + @ApiParam(value = "Minor Version", + required = false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value = "Patch Version", + required = false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam("ns") String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam("userId") String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam("password") String password, + JsonInsert selObj, + @ApiParam(value = "Keyspace Name", + required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Table Name", + required = true) @PathParam("tablename") String tablename, + @Context UriInfo info, @Context HttpServletResponse response) throws Exception { + Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace, + aid, "selectCritical"); + response.addHeader(xLatestVersion, MusicUtil.getVersion()); + if (resultMap.containsKey("aid")) + resultMap.remove("aid"); + if (!resultMap.isEmpty()) { + logger.error("Error while authentication... "); + HashMap<String, Object> tempMap = new HashMap<>(); + tempMap.putAll(resultMap); + Map<String, HashMap<String, Object>> results = new HashMap<>(); + results.put("Result", tempMap); + return results; + } + String lockId = selObj.getConsistencyInfo().get("lockId"); + + PreparedQueryObject queryObject = new PreparedQueryObject(); + StringBuilder rowSpec = new StringBuilder(); + + RowIdentifier rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), + queryObject); + + queryObject.appendQueryString( + "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowSpec + ";"); + + ResultSet results = null; + + String consistency = selObj.getConsistencyInfo().get("type"); + + if (consistency.equalsIgnoreCase("critical")) { + results = MusicCore.criticalGet(keyspace, tablename, rowId.primarKeyValue, queryObject, + lockId); + } else if (consistency.equalsIgnoreCase("atomic")) { + results = MusicCore.atomicGet(keyspace, tablename, rowId.primarKeyValue, queryObject); + } + + return MusicCore.marshallResults(results); + } + + /** + * + * @param keyspace + * @param tablename + * @param info + * @return + * @throws Exception + */ + @GET + @Path("/{keyspace}/tables/{tablename}/rows") + @ApiOperation(value = "Select All or Select Specivic", response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + public Map<String, HashMap<String, Object>> select( + @ApiParam(value = "Major Version", + required = true) @PathParam("version") String version, + @ApiParam(value = "Minor Version", + required = false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value = "Patch Version", + required = false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid, + @ApiParam(value = "Application namespace", + required = true) @HeaderParam("ns") String ns, + @ApiParam(value = "userId", + required = true) @HeaderParam("userId") String userId, + @ApiParam(value = "Password", + required = true) @HeaderParam("password") String password, + @ApiParam(value = "Keyspace Name", + required = true) @PathParam("keyspace") String keyspace, + @ApiParam(value = "Table Name", + required = true) @PathParam("tablename") String tablename, + @Context UriInfo info, @Context HttpServletResponse response) throws Exception { + Map<String, Object> resultMap = + MusicCore.autheticateUser(ns, userId, password, keyspace, aid, "select"); + response.addHeader(xLatestVersion, MusicUtil.getVersion()); + if (resultMap.containsKey("aid")) + resultMap.remove("aid"); + if (!resultMap.isEmpty()) { + logger.error("Error while authentication... "); + HashMap<String, Object> tempMap = new HashMap<>(); + tempMap.putAll(resultMap); + Map<String, HashMap<String, Object>> results = new HashMap<>(); + results.put("Result", tempMap); + return results; + } + PreparedQueryObject queryObject = new PreparedQueryObject(); + + if (info.getQueryParameters().isEmpty())// select all + queryObject.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + ";"); + else { + int limit = -1; // do not limit the number of results + queryObject = selectSpecificQuery(version, minorVersion, patchVersion, aid, ns, userId, + password, keyspace, tablename, info, limit); + } + ResultSet results = MusicCore.get(queryObject); + return MusicCore.marshallResults(results); + } + + /** + * + * @param keyspace + * @param tablename + * @param info + * @param limit + * @return + * @throws Exception + */ + public PreparedQueryObject selectSpecificQuery(String version, String minorVersion, + String patchVersion, String aid, String ns, String userId, String password, + String keyspace, String tablename, UriInfo info, int limit) { + + PreparedQueryObject queryObject = new PreparedQueryObject(); + StringBuilder rowIdString = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), + queryObject).rowIdString; + + queryObject.appendQueryString( + "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowIdString); + + if (limit != -1) { + queryObject.appendQueryString(" LIMIT " + limit); + } + + queryObject.appendQueryString(";"); + return queryObject; + + } + + /** + * + * @param keyspace + * @param tablename + * @param rowParams + * @param queryObject + * @return + * @throws Exception + */ + private RowIdentifier getRowIdentifier(String keyspace, String tablename, + MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject) { + StringBuilder rowSpec = new StringBuilder(); + int counter = 0; + TableMetadata tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename); + StringBuilder primaryKey = new StringBuilder(); + for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) { + String keyName = entry.getKey(); + List<String> valueList = entry.getValue(); + String indValue = valueList.get(0); + DataType colType = tableInfo.getColumn(entry.getKey()).getType(); + Object formattedValue = MusicUtil.convertToActualDataType(colType, indValue); + primaryKey.append(indValue); + rowSpec.append(keyName + "= ?"); + queryObject.addValue(formattedValue); + if (counter != rowParams.size() - 1) + rowSpec.append(" AND "); + counter = counter + 1; + } + return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject); + } + +} diff --git a/src/main/java/org/onap/music/rest/RestMusicLocksAPI.java b/src/main/java/org/onap/music/rest/RestMusicLocksAPI.java new file mode 100644 index 00000000..8612b1fa --- /dev/null +++ b/src/main/java/org/onap/music/rest/RestMusicLocksAPI.java @@ -0,0 +1,209 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.rest; + +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; + +import org.onap.music.datastore.jsonobjects.JsonLeasedLock; +import org.onap.music.lockingservice.MusicLockState; +import org.onap.music.main.MusicCore; +import org.onap.music.main.MusicUtil; +import org.onap.music.response.jsonobjects.JsonLockResponse; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; + + +@Path("/v{version: [0-9]+}/locks/") +@Api(value="Lock Api") +public class RestMusicLocksAPI { + + private static EELFLogger logger = EELFManager.getInstance().getLogger(RestMusicLocksAPI.class); + private static String xLatestVersion = "X-latestVersion"; + /** + * Puts the requesting process in the q for this lock. The corresponding + * node will be created in zookeeper if it did not already exist + * + * @param lockName + * @return + */ + + @POST + @Path("/create/{lockname}") + @ApiOperation(value = "Create Lock", + notes = "Puts the requesting process in the q for this lock." + + " The corresponding node will be created in zookeeper if it did not already exist." + + " Lock Name is the \"key\" of the form keyspaceName.tableName.rowId", + response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + public Map<String,Object> createLockReference( + @ApiParam(value="Lock Name",required=true) @PathParam("lockname") String lockName, + @Context HttpServletResponse response){ + response.addHeader(xLatestVersion,MusicUtil.getVersion()); + Boolean status = true; + String lockId = MusicCore.createLockReference(lockName); + if ( lockId == null ) { status = false; } + return new JsonLockResponse(status.toString(),"",lockId).toMap(); + } + + /** + * + * Checks if the node is in the top of the queue and hence acquires the lock + * + * @param lockId + * @return + */ + @GET + @Path("/acquire/{lockreference}") + @ApiOperation(value = "Aquire Lock", + notes = "Checks if the node is in the top of the queue and hence acquires the lock", + response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + public Map<String,Object> accquireLock( + @ApiParam(value="Lock Reference",required=true) @PathParam("lockreference") String lockId, + @Context HttpServletResponse response){ + response.addHeader(xLatestVersion,MusicUtil.getVersion()); + String lockName = lockId.substring(lockId.indexOf('$')+1, lockId.lastIndexOf('$')); + Boolean lockStatus = MusicCore.acquireLock(lockName,lockId); + return new JsonLockResponse(lockStatus.toString(),"",lockId,lockStatus.toString(),"").toMap(); + } + + + + + @POST + @Path("/acquire-with-lease/{lockreference}") + @ApiOperation(value = "Aquire Lock with Lease", response = Map.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Map<String,Object> accquireLockWithLease(JsonLeasedLock lockObj, + @ApiParam(value="Lock Reference",required=true) @PathParam("lockreference") String lockId, + @Context HttpServletResponse response){ + response.addHeader(xLatestVersion,MusicUtil.getVersion()); + String lockName = lockId.substring(lockId.indexOf('$')+1, lockId.lastIndexOf('$')); + String lockLeaseStatus = MusicCore.acquireLockWithLease(lockName, lockId, lockObj.getLeasePeriod()).toString(); + return new JsonLockResponse(lockLeaseStatus,"",lockName,lockLeaseStatus,"",String.valueOf(lockObj.getLeasePeriod())).toMap(); + } + + + @GET + @Path("/enquire/{lockname}") + @ApiOperation(value = "Get Lock Holder", + notes = "Gets the current Lock Holder", + response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + public Map<String,Object> currentLockHolder( + @ApiParam(value="Lock Name",required=true) @PathParam("lockname") String lockName, + @Context HttpServletResponse response){ + response.addHeader(xLatestVersion,MusicUtil.getVersion()); + String who = MusicCore.whoseTurnIsIt(lockName); + String status = "true"; + String error = ""; + if ( who == null ) { + status = "false"; + error = "There was a problem getting the lock holder"; + } + return new JsonLockResponse(status,error,lockName,"",who).toMap(); + } + + @GET + @Path("/{lockname}") + @ApiOperation(value = "Lock State", + notes = "Returns current Lock State and Holder.", + response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + public Map<String,Object> currentLockState( + @ApiParam(value="Lock Name",required=true) @PathParam("lockname") String lockName, + @Context HttpServletResponse response){ + response.addHeader(xLatestVersion,MusicUtil.getVersion()); + MusicLockState mls = MusicCore.getMusicLockState(lockName); + Map<String,Object> returnMap = null; + JsonLockResponse jsonResponse = new JsonLockResponse("false","",lockName); + if(mls == null) { + jsonResponse.setError(""); + jsonResponse.setMessage("No lock object created yet.."); + } else { + jsonResponse.setStatus("true"); + jsonResponse.setLockStatus(mls.getLockStatus().toString()); + jsonResponse.setLockHolder(mls.getLockHolder()); + } + return returnMap; + } + + /** + * + * deletes the process from the zk queue + * + * @param lockId + */ + @DELETE + @Path("/release/{lockreference}") + @ApiOperation(value = "Release Lock", + notes = "deletes the process from the zk queue", + response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + public Map<String,Object> unLock(@PathParam("lockreference") String lockId, + @Context HttpServletResponse response){ + response.addHeader(xLatestVersion,MusicUtil.getVersion()); + boolean voluntaryRelease = true; + MusicLockState mls = MusicCore.releaseLock(lockId,voluntaryRelease); + Map<String,Object> returnMap = null; + if ( mls.getLockStatus() == MusicLockState.LockStatus.UNLOCKED ) { + returnMap = new JsonLockResponse("Unlocked","","").toMap(); + } + if ( mls.getLockStatus() == MusicLockState.LockStatus.LOCKED) { + returnMap = new JsonLockResponse("Locked","","").toMap(); + } + return returnMap; + } + + /** + * + * @param lockName + */ + @DELETE + @Path("/delete/{lockname}") + @ApiOperation(value = "Delete Lock", response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + public Map<String,Object> deleteLock(@PathParam("lockname") String lockName, + @Context HttpServletResponse response){ + response.addHeader(xLatestVersion,MusicUtil.getVersion()); + MusicCore.deleteLock(lockName); + return new JsonLockResponse("true","","").toMap(); + } + +} diff --git a/src/main/java/org/onap/music/rest/RestMusicQAPI.java b/src/main/java/org/onap/music/rest/RestMusicQAPI.java new file mode 100755 index 00000000..3e92461c --- /dev/null +++ b/src/main/java/org/onap/music/rest/RestMusicQAPI.java @@ -0,0 +1,257 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.rest; + + + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriInfo; + +import org.onap.music.datastore.jsonobjects.JsonDelete; +import org.onap.music.datastore.jsonobjects.JsonInsert; +import org.onap.music.datastore.jsonobjects.JsonTable; +import org.onap.music.datastore.jsonobjects.JsonUpdate; +import org.onap.music.main.MusicCore; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import org.onap.music.datastore.PreparedQueryObject; +import com.datastax.driver.core.ResultSet; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; + +//@Path("/v{version: [0-9]+}/priorityq/") +@Path("/priorityq/") +@Api(value="Q Api") +public class RestMusicQAPI { + + private static EELFLogger logger = EELFManager.getInstance().getLogger(RestMusicQAPI.class); + + + /** + * + * @param tableObj + * @param keyspace + * @param tablename + * @throws Exception + */ + + @POST + @Path("/keyspaces/{keyspace}/{qname}") + @ApiOperation(value = "", response = Void.class) + @Consumes(MediaType.APPLICATION_JSON) + public Map<String,Object> createQ( + @ApiParam(value="Major Version",required=true) @PathParam("version") String version, + @ApiParam(value="Minor Version",required=false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value="Patch Version",required=false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value="AID",required=true) @HeaderParam("aid") String aid, + @ApiParam(value="Application namespace",required=true) @HeaderParam("ns") String ns, + @ApiParam(value="userId",required=true) @HeaderParam("userId") String userId, + @ApiParam(value="Password",required=true) @HeaderParam("password") String password, JsonTable tableObj, + @ApiParam(value="Key Space",required=true) @PathParam("keyspace") String keyspace, + @ApiParam(value="Table Name",required=true) @PathParam("tablename") String tablename, + @Context HttpServletResponse response) throws Exception{ + return new RestMusicDataAPI().createTable(version,minorVersion,patchVersion,aid, ns, userId, password, tableObj, keyspace, tablename,response); + } + + /** + * + * @param insObj + * @param keyspace + * @param tablename + * @throws Exception + */ + @POST + @Path("/keyspaces/{keyspace}/{qname}/rows") + @ApiOperation(value = "", response = Void.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Map<String,Object> insertIntoQ( + @ApiParam(value="Major Version",required=true) @PathParam("version") String version, + @ApiParam(value="Minor Version",required=false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value="Patch Version",required=false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value="AID",required=true) @HeaderParam("aid") String aid, + @ApiParam(value="Application namespace",required=true) @HeaderParam("ns") String ns, @ApiParam(value="userId",required=true) @HeaderParam("userId") String userId, + @ApiParam(value="Password",required=true) @HeaderParam("password") String password, JsonInsert insObj, + @ApiParam(value="Key Space",required=true) @PathParam("keyspace") String keyspace, + @ApiParam(value="Table Name",required=true) @PathParam("tablename") String tablename, + @Context HttpServletResponse response) throws Exception{ + return new RestMusicDataAPI().insertIntoTable(version,minorVersion,patchVersion,aid, ns, userId, password, insObj, keyspace, tablename,response); + } + + /** + * + * @param updateObj + * @param keyspace + * @param tablename + * @param info + * @return + * @throws Exception + */ + @PUT + @Path("/keyspaces/{keyspace}/{qname}/rows") + @ApiOperation(value = "", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Map<String,Object> updateQ( + @ApiParam(value="Major Version",required=true) @PathParam("version") String version, + @ApiParam(value="Minor Version",required=false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value="Patch Version",required=false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value="AID",required=true) @HeaderParam("aid") String aid, + @ApiParam(value="Application namespace",required=true) @HeaderParam("ns") String ns, @ApiParam(value="userId",required=true) @HeaderParam("userId") String userId, + @ApiParam(value="Password",required=true) @HeaderParam("password") String password, JsonUpdate updateObj, + @ApiParam(value="Key Space",required=true) @PathParam("keyspace") String keyspace, + @ApiParam(value="Table Name",required=true) @PathParam("tablename") String tablename, + @Context UriInfo info, + @Context HttpServletResponse response) throws Exception{ + return new RestMusicDataAPI().updateTable(version,minorVersion,patchVersion,aid, ns, userId, password, updateObj, keyspace, tablename, info,response); + } + + /** + * + * @param delObj + * @param keyspace + * @param tablename + * @param info + * @return + * @throws Exception + */ + @DELETE + @Path("/keyspaces/{keyspace}/{qname}/rows") + @ApiOperation(value = "", response = String.class) + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Map<String,Object> deleteFromQ( + @ApiParam(value="Major Version",required=true) @PathParam("version") String version, + @ApiParam(value="Minor Version",required=false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value="Patch Version",required=false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value="AID",required=true) @HeaderParam("aid") String aid, + @ApiParam(value="Application namespace",required=true) @HeaderParam("ns") String ns, + @ApiParam(value="userId",required=true) @HeaderParam("userId") String userId, + @ApiParam(value="Password",required=true) @HeaderParam("password") String password, JsonDelete delObj, + @ApiParam(value="Key Space",required=true) @PathParam("keyspace") String keyspace, + @ApiParam(value="Table Name",required=true) @PathParam("tablename") String tablename, + @Context UriInfo info, + @Context HttpServletResponse response) throws Exception{ + return new RestMusicDataAPI().deleteFromTable(version,minorVersion,patchVersion,aid, ns, userId, password, delObj, keyspace, tablename, info,response); + } + + /** + * + * @param keyspace + * @param tablename + * @param info + * @return + * @throws Exception + */ + @GET + @Path("/keyspaces/{keyspace}/{qname}/peek") + @ApiOperation(value = "", response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + public Map<String, HashMap<String, Object>> peek( + @ApiParam(value="Major Version",required=true) @PathParam("version") String version, + @ApiParam(value="Minor Version",required=false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value="Patch Version",required=false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value="AID",required=true) @HeaderParam("aid") String aid, + @ApiParam(value="Application namespace",required=true) @HeaderParam("ns") String ns, + @ApiParam(value="userId",required=true) @HeaderParam("userId") String userId, + @ApiParam(value="Password",required=true) @HeaderParam("password") String password, + @ApiParam(value="Key Space",required=true) @PathParam("keyspace") String keyspace, + @ApiParam(value="Table Name",required=true) @PathParam("tablename") String tablename, + @Context UriInfo info) throws Exception{ + int limit =1; //peek must return just the top row + PreparedQueryObject query = new RestMusicDataAPI().selectSpecificQuery(version,minorVersion,patchVersion,aid, ns, userId, password,keyspace,tablename,info,limit); + ResultSet results = MusicCore.get(query); + return MusicCore.marshallResults(results); + + } + + /** + * + * + * @param keyspace + * @param tablename + * @param info + * @return + * @throws Exception + */ + @GET + @Path("/keyspaces/{keyspace}/{qname}/filter") + @ApiOperation(value = "", response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + public Map<String, HashMap<String, Object>> filter( + @ApiParam(value="Major Version",required=true) @PathParam("version") String version, + @ApiParam(value="Minor Version",required=false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value="Patch Version",required=false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value="AID",required=true) @HeaderParam("aid") String aid, + @ApiParam(value="Application namespace",required=true) @HeaderParam("ns") String ns, + @ApiParam(value="userId",required=true) @HeaderParam("userId") String userId, + @ApiParam(value="Password",required=true) @HeaderParam("password") String password, + @ApiParam(value="Key Space",required=true) @PathParam("keyspace") String keyspace, + @ApiParam(value="Table Name",required=true) @PathParam("tablename") String tablename, + @Context UriInfo info) throws Exception{ + int limit =-1; + PreparedQueryObject query = new RestMusicDataAPI().selectSpecificQuery(version,minorVersion,patchVersion,aid, ns, userId, password,keyspace,tablename,info,limit); + ResultSet results = MusicCore.get(query); + return MusicCore.marshallResults(results); + } + + /** + * + * @param tabObj + * @param keyspace + * @param tablename + * @throws Exception + */ + @DELETE + @ApiOperation(value = "", response = Void.class) + @Path("/keyspaces/{keyspace}/{qname}") + public Map<String,Object> dropQ( + @ApiParam(value="Major Version",required=true) @PathParam("version") String version, + @ApiParam(value="Minor Version",required=false) @HeaderParam("X-minorVersion") String minorVersion, + @ApiParam(value="Patch Version",required=false) @HeaderParam("X-patchVersion") String patchVersion, + @ApiParam(value="AID",required=true) @HeaderParam("aid") String aid, + @ApiParam(value="Application namespace",required=true) @HeaderParam("ns") String ns, + @ApiParam(value="userId",required=true) @HeaderParam("userId") String userId, + @ApiParam(value="Password",required=true) @HeaderParam("password") String password, JsonTable tabObj, + @ApiParam(value="Key Space",required=true) @PathParam("keyspace") String keyspace, + @ApiParam(value="Table Name",required=true) @PathParam("tablename") String tablename, + @Context HttpServletResponse response) throws Exception{ + return new RestMusicDataAPI().dropTable(version,minorVersion,patchVersion,aid, ns, userId, password, tabObj, keyspace, tablename,response); + } +} diff --git a/src/main/java/org/onap/music/rest/RestMusicTestAPI.java b/src/main/java/org/onap/music/rest/RestMusicTestAPI.java new file mode 100644 index 00000000..6b6bc101 --- /dev/null +++ b/src/main/java/org/onap/music/rest/RestMusicTestAPI.java @@ -0,0 +1,67 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.rest; + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; + +import org.onap.music.main.MusicUtil; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + + +@Path("/v{version: [0-9]+}/test") +@Api(value="Test Api") +public class RestMusicTestAPI { + private static EELFLogger logger = EELFManager.getInstance().getLogger(RestMusicTestAPI.class); + + /** + * Returns a test JSON. This will confirm that REST is working. + * @return + */ + @GET + @ApiOperation(value = "Get Test", response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + public Map<String, HashMap<String, String>> simpleTests( + @Context HttpServletResponse response) { + response.addHeader("X-latestVersion",MusicUtil.getVersion()); + Map<String, HashMap<String, String>> testMap = new HashMap<>(); + for(int i=0; i < 3; i++){ + HashMap<String, String> innerMap = new HashMap<>(); + innerMap.put(i+"", i+1+""); + innerMap.put(i+1+"", i+2+""); + testMap.put(i+"", innerMap); + } + return testMap; + } +} diff --git a/src/main/java/org/onap/music/rest/RestMusicVersionAPI.java b/src/main/java/org/onap/music/rest/RestMusicVersionAPI.java new file mode 100644 index 00000000..924b0289 --- /dev/null +++ b/src/main/java/org/onap/music/rest/RestMusicVersionAPI.java @@ -0,0 +1,61 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.rest; + +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; + +import org.onap.music.response.jsonobjects.JsonResponse; +import org.onap.music.main.MusicUtil; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + + +@Path("/v{version: [0-9]+}/version") +@Api(value="Version Api") +public class RestMusicVersionAPI { + + private static EELFLogger logger = EELFManager.getInstance().getLogger(RestMusicVersionAPI.class); + /** + * Get the version of MUSIC + * @return + */ + @GET + @ApiOperation(value = "Get Version", response = Map.class) + @Produces(MediaType.APPLICATION_JSON) + public Map<String,Object> version(@Context HttpServletResponse response) { + logger.info("Replying to request for MUSIC version with MUSIC:" + MusicUtil.getVersion()); + JsonResponse jResponse = new JsonResponse(true,"","MUSIC:" + MusicUtil.getVersion()); + response.addHeader("X-latestVersion",MusicUtil.getVersion()); + return jResponse.toMap(); + } +}
\ No newline at end of file |