aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/org/onap/music/main
diff options
context:
space:
mode:
authorarthurdent3 <tn1381@att.com>2018-02-02 21:19:53 -0500
committerarthurdent3 <tn1381@att.com>2018-02-05 10:20:49 -0500
commite99b7fa829bf957c2a46223a1a20a32aebeda91b (patch)
tree59ea8681b4165df7fb2482af3f6d411115e32f5a /src/main/java/org/onap/music/main
parentd221feba08b6ad24e7d232247306f7b67934941d (diff)
Initial code Import.
Issue-ID: MUSIC-21 Change-Id: I89ceab0891b4b7cb999dab532d6bae9092f027cc Signed-off-by: arthurdent3 <tn1381@att.com>
Diffstat (limited to 'src/main/java/org/onap/music/main')
-rwxr-xr-xsrc/main/java/org/onap/music/main/CachingUtil.java370
-rw-r--r--src/main/java/org/onap/music/main/CronJobManager.java47
-rw-r--r--src/main/java/org/onap/music/main/MusicCore.java874
-rw-r--r--src/main/java/org/onap/music/main/MusicDigest.java78
-rwxr-xr-xsrc/main/java/org/onap/music/main/MusicUtil.java465
-rwxr-xr-xsrc/main/java/org/onap/music/main/PropertiesListener.java147
-rw-r--r--src/main/java/org/onap/music/main/ResultType.java39
-rw-r--r--src/main/java/org/onap/music/main/ReturnType.java74
8 files changed, 2094 insertions, 0 deletions
diff --git a/src/main/java/org/onap/music/main/CachingUtil.java b/src/main/java/org/onap/music/main/CachingUtil.java
new file mode 100755
index 00000000..0ab055df
--- /dev/null
+++ b/src/main/java/org/onap/music/main/CachingUtil.java
@@ -0,0 +1,370 @@
+/*
+ * ============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.main;
+
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.UUID;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.jcs.JCS;
+import org.apache.commons.jcs.access.CacheAccess;
+import org.apache.log4j.Logger;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.onap.music.datastore.jsonobjects.AAFResponse;
+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.Row;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+
+/**
+ * All Caching related logic is handled by this class and a schedule cron runs to update cache.
+ *
+ * @author Vikram
+ *
+ */
+public class CachingUtil implements Runnable {
+
+ private static EELFLogger logger = EELFManager.getInstance().getLogger(CachingUtil.class);
+
+ private static CacheAccess<String, String> musicCache = JCS.getInstance("musicCache");
+ private static CacheAccess<String, Map<String, String>> aafCache = JCS.getInstance("aafCache");
+ private static CacheAccess<String, String> appNameCache = JCS.getInstance("appNameCache");
+ private static Map<String, Number> userAttempts = new HashMap<>();
+ private static Map<String, Calendar> lastFailedTime = new HashMap<>();
+
+ public boolean isCacheRefreshNeeded() {
+ if (aafCache.get("initBlankMap") == null)
+ return true;
+ return false;
+ }
+
+ public void initializeMusicCache() {
+ logger.info("Initializing Music Cache...");
+ musicCache.put("isInitialized", "true");
+ }
+
+ public void initializeAafCache() {
+ logger.info("Resetting and initializing AAF Cache...");
+
+ // aafCache.clear();
+ // loop through aafCache ns .. only the authenticated ns will be re cached. and non
+ // authenticated will wait for user to retry.
+ String query = "SELECT application_name, keyspace_name, username, password FROM admin.keyspace_master WHERE is_api = ? allow filtering";
+ PreparedQueryObject pQuery = new PreparedQueryObject();
+ pQuery.appendQueryString(query);
+ try {
+ pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), false));
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ logger.error("Exception is " + e1.getMessage() + "during initalizeAafCache");
+ }
+ ResultSet rs = MusicCore.get(pQuery);
+ Iterator<Row> it = rs.iterator();
+ Map<String, String> map = null;
+ while (it.hasNext()) {
+ Row row = it.next();
+ String nameSpace = row.getString("keyspace_name");
+ String userId = row.getString("username");
+ String password = row.getString("password");
+ String keySpace = row.getString("application_name");
+ try {
+ userAttempts.put(nameSpace, 0);
+ AAFResponse responseObj = triggerAAF(nameSpace, userId, password);
+ if (responseObj.getNs().size() > 0) {
+ map = new HashMap<>();
+ map.put(userId, password);
+ aafCache.put(nameSpace, map);
+ musicCache.put(nameSpace, keySpace);
+ logger.debug("Cronjob: Cache Updated with AAF response for namespace "
+ + nameSpace);
+ }
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ logger.error("Something at AAF was changed for ns: " + nameSpace
+ + ". So not updating Cache for the namespace. ");
+ logger.error("Exception is " + e.getMessage());
+ }
+ }
+
+ }
+
+ @Override
+ public void run() {
+ logger.debug("Scheduled task invoked. Refreshing Cache...");
+ initializeAafCache();
+ }
+
+ public static boolean authenticateAAFUser(String nameSpace, String userId, String password,
+ String keySpace) throws Exception {
+
+ if (aafCache.get(nameSpace) != null) {
+ if (!musicCache.get(nameSpace).equals(keySpace)) {
+ logger.debug("Create new application for the same namespace.");
+ } else if (aafCache.get(nameSpace).get(userId).equals(password)) {
+ logger.debug("Authenticated with cache value..");
+ // reset invalid attempts to 0
+ userAttempts.put(nameSpace, 0);
+ return true;
+ } else {
+ // call AAF update cache with new password
+ if (userAttempts.get(nameSpace) == null)
+ userAttempts.put(nameSpace, 0);
+ if ((Integer) userAttempts.get(nameSpace) >= 3) {
+ logger.info("Reached max attempts. Checking if time out..");
+ logger.info("Failed time: " + lastFailedTime.get(nameSpace).getTime());
+ Calendar calendar = Calendar.getInstance();
+ long delayTime = (calendar.getTimeInMillis()
+ - lastFailedTime.get(nameSpace).getTimeInMillis());
+ logger.info("Delayed time: " + delayTime);
+ if (delayTime > 120000) {
+ logger.info("Resetting failed attempt.");
+ userAttempts.put(nameSpace, 0);
+ } else {
+ throw new Exception(
+ "No more attempts allowed. Please wait for atleast 2 min.");
+ }
+ }
+ logger.error("Cache not authenticated..");
+ logger.info("Check AAF again...");
+ }
+ }
+
+ AAFResponse responseObj = triggerAAF(nameSpace, userId, password);
+ if (responseObj.getNs().size() > 0) {
+ if (responseObj.getNs().get(0).getAdmin().contains(userId))
+ return true;
+
+ }
+ logger.info("Invalid user. Cache not updated");
+ return false;
+ }
+
+ private static AAFResponse triggerAAF(String nameSpace, String userId, String password)
+ throws Exception {
+ if (MusicUtil.getAafEndpointUrl() == null) {
+ throw new Exception("AAF endpoint is not set. Please specify in the properties file.");
+ }
+ Client client = Client.create();
+ // WebResource webResource =
+ // client.resource("https://aaftest.test.att.com:8095/proxy/authz/nss/"+nameSpace);
+ WebResource webResource = client.resource(MusicUtil.getAafEndpointUrl().concat(nameSpace));
+ String plainCreds = userId + ":" + password;
+ byte[] plainCredsBytes = plainCreds.getBytes();
+ byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes);
+ String base64Creds = new String(base64CredsBytes);
+
+ ClientResponse response = webResource.accept(MediaType.APPLICATION_JSON)
+ .header("Authorization", "Basic " + base64Creds)
+ .header("content-type", "application/json").get(ClientResponse.class);
+ if (response.getStatus() != 200) {
+ if (userAttempts.get(nameSpace) == null)
+ userAttempts.put(nameSpace, 0);
+ if ((Integer) userAttempts.get(nameSpace) >= 2) {
+ lastFailedTime.put(nameSpace, Calendar.getInstance());
+ userAttempts.put(nameSpace, ((Integer) userAttempts.get(nameSpace) + 1));
+ throw new Exception(
+ "Reached max invalid attempts. Please contact admin and retry with valid credentials.");
+ }
+ userAttempts.put(nameSpace, ((Integer) userAttempts.get(nameSpace) + 1));
+ throw new Exception(
+ "Unable to authenticate. Please check the AAF credentials against namespace.");
+ // TODO Allow for 2-3 times and forbid any attempt to trigger AAF with invalid values
+ // for specific time.
+ }
+ response.getHeaders().put(HttpHeaders.CONTENT_TYPE,
+ Arrays.asList(MediaType.APPLICATION_JSON));
+ // AAFResponse output = response.getEntity(AAFResponse.class);
+ response.bufferEntity();
+ String x = response.getEntity(String.class);
+ AAFResponse responseObj = new ObjectMapper().readValue(x, AAFResponse.class);
+ return responseObj;
+ }
+
+ public static Map<String, Object> authenticateAIDUser(String aid, String keyspace)
+ throws Exception {
+ Map<String, Object> resultMap = new HashMap<>();
+ String uuid = null;
+ /*
+ * if(aid == null || aid.length() == 0) { resultMap.put("Exception Message",
+ * "AID is missing for the keyspace requested."); //create a new AID ?? } else
+ */
+ if (musicCache.get(keyspace) == null) {
+ PreparedQueryObject pQuery = new PreparedQueryObject();
+ pQuery.appendQueryString(
+ "SELECT uuid from admin.keyspace_master where keyspace_name = '"
+ + keyspace + "' allow filtering");
+ Row rs = MusicCore.get(pQuery).one();
+ try {
+ uuid = rs.getUUID("uuid").toString();
+ musicCache.put(keyspace, uuid);
+ } catch (Exception e) {
+ String msg = e.getMessage();
+ logger.error("Exception occured during uuid retrieval from DB." + e.getMessage());
+ resultMap.put("Exception", "Unauthorized operation. Check AID and Keyspace. "
+ + "Exception from MUSIC is: "
+ + (msg == null ? "Keyspace is new so no AID should be passed in Header."
+ : msg));
+ return resultMap;
+ }
+ if (!musicCache.get(keyspace).toString().equals(aid)) {
+ resultMap.put("Exception Message",
+ "Unauthorized operation. Invalid AID for the keyspace");
+ return resultMap;
+ }
+ } else if (musicCache.get(keyspace) != null
+ && !musicCache.get(keyspace).toString().equals(aid)) {
+ resultMap.put("Exception Message",
+ "Unauthorized operation. Invalid AID for the keyspace");
+ return resultMap;
+ }
+ resultMap.put("aid", uuid);
+ return resultMap;
+ }
+
+ public static void updateMusicCache(String aid, String keyspace) {
+ logger.info("Updating musicCache for keyspace " + keyspace + " with aid " + aid);
+ musicCache.put(keyspace, aid);
+ }
+
+ public static void updateisAAFCache(String namespace, String isAAF) {
+ appNameCache.put(namespace, isAAF);
+ }
+
+ public static Boolean isAAFApplication(String namespace) {
+
+ String isAAF = appNameCache.get(namespace);
+ if (isAAF == null) {
+ PreparedQueryObject pQuery = new PreparedQueryObject();
+ pQuery.appendQueryString(
+ "SELECT is_aaf from admin.keyspace_master where application_name = '"
+ + namespace + "' allow filtering");
+ Row rs = MusicCore.get(pQuery).one();
+ try {
+ isAAF = String.valueOf(rs.getBool("is_aaf"));
+ appNameCache.put(namespace, isAAF);
+ } catch (Exception e) {
+ logger.error("Exception occured during uuid retrieval from DB." + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+ return Boolean.valueOf(isAAF);
+ }
+
+ public static String getUuidFromMusicCache(String keyspace) {
+ String uuid = musicCache.get(keyspace);
+ if (uuid == null) {
+ PreparedQueryObject pQuery = new PreparedQueryObject();
+ pQuery.appendQueryString(
+ "SELECT uuid from admin.keyspace_master where keyspace_name = '"
+ + keyspace + "' allow filtering");
+ Row rs = MusicCore.get(pQuery).one();
+ try {
+ uuid = rs.getUUID("uuid").toString();
+ musicCache.put(keyspace, uuid);
+ } catch (Exception e) {
+ logger.error("Exception occured during uuid retrieval from DB." + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+ return uuid;
+ }
+
+ public static String getAppName(String keyspace) {
+ String appName = null;
+ PreparedQueryObject pQuery = new PreparedQueryObject();
+ pQuery.appendQueryString(
+ "SELECT application_name from admin.keyspace_master where keyspace_name = '"
+ + keyspace + "' allow filtering");
+ Row rs = MusicCore.get(pQuery).one();
+ try {
+ appName = rs.getString("application_name");
+ } catch (Exception e) {
+ logger.error("Exception occured during uuid retrieval from DB." + e.getMessage());
+ e.printStackTrace();
+ }
+ return appName;
+ }
+
+ public static String generateUUID() {
+ String uuid = UUID.randomUUID().toString();
+ logger.info("New AID generated: " + uuid);
+ return uuid;
+ }
+
+ public static Map<String, Object> validateRequest(String nameSpace, String userId,
+ String password, String keyspace, String aid, String operation) {
+ Map<String, Object> resultMap = new HashMap<>();
+ if (!"createKeySpace".equals(operation)) {
+ if (nameSpace == null) {
+ resultMap.put("Exception", "Application namespace is mandatory.");
+ }
+ }
+ return resultMap;
+
+ }
+
+ public static Map<String, Object> verifyOnboarding(String ns, String userId, String password)
+ throws Exception {
+ Map<String, Object> resultMap = new HashMap<>();
+ if (ns == null || userId == null || password == null) {
+ logger.error("One or more required headers is missing. userId: " + userId
+ + " :: password: " + password);
+ resultMap.put("Exception",
+ "One or more required headers appName(ns), userId, password is missing. Please check.");
+ return resultMap;
+ }
+ PreparedQueryObject queryObject = new PreparedQueryObject();
+ queryObject.appendQueryString(
+ "select * from admin.keyspace_master where application_name=? and username=? allow filtering");
+ queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), ns));
+ queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId));
+ Row rs = MusicCore.get(queryObject).one();
+ if (rs == null) {
+ logger.error("Namespace and UserId doesn't match. namespace: " + ns + " and userId: "
+ + userId);
+ resultMap.put("Exception", "Application " + ns
+ + " doesn't seem to be Onboarded. Please onboard your application with MUSIC. If already onboarded contact Admin");
+ } else {
+ boolean is_aaf = rs.getBool("is_aaf");
+ String keyspace = rs.getString("keyspace_name");
+ if (!is_aaf) {
+ if (!keyspace.equals(MusicUtil.DEFAULTKEYSPACENAME)) {
+ logger.error("Non AAF applications are allowed to have only one keyspace per application.");
+ resultMap.put("Exception",
+ "Non AAF applications are allowed to have only one keyspace per application.");
+ }
+ }
+ }
+ return resultMap;
+ }
+}
diff --git a/src/main/java/org/onap/music/main/CronJobManager.java b/src/main/java/org/onap/music/main/CronJobManager.java
new file mode 100644
index 00000000..fb4a2ac3
--- /dev/null
+++ b/src/main/java/org/onap/music/main/CronJobManager.java
@@ -0,0 +1,47 @@
+/*
+ * ============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.main;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.annotation.WebListener;
+
+@WebListener
+public class CronJobManager implements ServletContextListener {
+
+ private ScheduledExecutorService scheduler;
+
+ @Override
+ public void contextInitialized(ServletContextEvent event) {
+ scheduler = Executors.newSingleThreadScheduledExecutor();
+ scheduler.scheduleAtFixedRate(new CachingUtil(), 0, 24, TimeUnit.HOURS);
+ }
+
+ @Override
+ public void contextDestroyed(ServletContextEvent event) {
+ scheduler.shutdownNow();
+ }
+
+}
diff --git a/src/main/java/org/onap/music/main/MusicCore.java b/src/main/java/org/onap/music/main/MusicCore.java
new file mode 100644
index 00000000..592bae92
--- /dev/null
+++ b/src/main/java/org/onap/music/main/MusicCore.java
@@ -0,0 +1,874 @@
+/*
+ * ============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.main;
+
+
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+import org.onap.music.datastore.MusicDataStore;
+import org.onap.music.datastore.PreparedQueryObject;
+import org.onap.music.datastore.jsonobjects.JsonKeySpace;
+// import org.onap.music.eelf.logging.EELFLoggerDelegate;
+import org.onap.music.exceptions.MusicLockingException;
+import org.onap.music.exceptions.MusicQueryException;
+import org.onap.music.exceptions.MusicServiceException;
+import org.onap.music.lockingservice.MusicLockState;
+import org.onap.music.lockingservice.MusicLockState.LockStatus;
+import org.onap.music.lockingservice.MusicLockingService;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.datastax.driver.core.ColumnDefinitions;
+import com.datastax.driver.core.ColumnDefinitions.Definition;
+import com.datastax.driver.core.DataType;
+import com.datastax.driver.core.ResultSet;
+import com.datastax.driver.core.Row;
+import com.datastax.driver.core.TableMetadata;
+
+/**
+ * This class .....
+ *
+ *
+ */
+public class MusicCore {
+
+ public static MusicLockingService mLockHandle = null;
+ public static MusicDataStore mDstoreHandle = null;
+ private static EELFLogger logger = EELFManager.getInstance().getLogger(MusicCore.class);
+
+ public static class Condition {
+ Map<String, Object> conditions;
+ String selectQueryForTheRow;
+
+ public Condition(Map<String, Object> conditions, String selectQueryForTheRow) {
+ this.conditions = conditions;
+ this.selectQueryForTheRow = selectQueryForTheRow;
+ }
+
+ public boolean testCondition() {
+ // first generate the row
+ PreparedQueryObject query = new PreparedQueryObject();
+ query.appendQueryString(selectQueryForTheRow);
+ ResultSet results = quorumGet(query);
+ Row row = results.one();
+ return getDSHandle().doesRowSatisfyCondition(row, conditions);
+ }
+ }
+
+
+ public static MusicLockingService getLockingServiceHandle() throws MusicLockingException {
+ logger.info("Acquiring lock store handle");
+ long start = System.currentTimeMillis();
+
+ if (mLockHandle == null) {
+ try {
+ mLockHandle = new MusicLockingService();
+ } catch (Exception e) {
+ logger.error("Failed to aquire Locl store handle" + e.getMessage());
+ throw new MusicLockingException("Failed to aquire Locl store handle " + e);
+ }
+ }
+ long end = System.currentTimeMillis();
+ logger.info("Time taken to acquire lock store handle:" + (end - start) + " ms");
+ return mLockHandle;
+ }
+
+ /**
+ *
+ * @param remoteIp
+ * @return
+ */
+ public static MusicDataStore getDSHandle(String remoteIp) {
+ logger.info("Acquiring data store handle");
+ long start = System.currentTimeMillis();
+ if (mDstoreHandle == null) {
+ mDstoreHandle = new MusicDataStore(remoteIp);
+ }
+ long end = System.currentTimeMillis();
+ logger.info("Time taken to acquire data store handle:" + (end - start) + " ms");
+ return mDstoreHandle;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public static MusicDataStore getDSHandle() {
+ logger.info("Acquiring data store handle");
+ long start = System.currentTimeMillis();
+ if (mDstoreHandle == null) {
+ mDstoreHandle = new MusicDataStore();
+ }
+ long end = System.currentTimeMillis();
+ logger.info("Time taken to acquire data store handle:" + (end - start) + " ms");
+ return mDstoreHandle;
+ }
+
+ public static String createLockReference(String lockName) {
+ logger.info("Creating lock reference for lock name:" + lockName);
+ long start = System.currentTimeMillis();
+ String lockId = null;
+ try {
+ lockId = getLockingServiceHandle().createLockId("/" + lockName);
+ } catch (MusicLockingException e) {
+ logger.error("Failed to create Lock Reference " + lockName);
+ }
+ long end = System.currentTimeMillis();
+ logger.info("Time taken to create lock reference:" + (end - start) + " ms");
+ return lockId;
+ }
+
+ /**
+ *
+ * @param key
+ * @return
+ */
+ public static boolean isTableOrKeySpaceLock(String key) {
+ String[] splitString = key.split("\\.");
+ if (splitString.length > 2)
+ return false;
+ else
+ return true;
+ }
+
+ /**
+ *
+ * @param key
+ * @return
+ */
+ public static MusicLockState getMusicLockState(String key) {
+ long start = System.currentTimeMillis();
+ try {
+ String[] splitString = key.split("\\.");
+ String keyspaceName = splitString[0];
+ String tableName = splitString[1];
+ String primaryKey = splitString[2];
+ MusicLockState mls;
+ String lockName = keyspaceName + "." + tableName + "." + primaryKey;
+ mls = getLockingServiceHandle().getLockState(lockName);
+ long end = System.currentTimeMillis();
+ logger.info("Time taken to get lock state:" + (end - start) + " ms");
+ return mls;
+ } catch (NullPointerException | MusicLockingException e) {
+ logger.error("No lock object exists as of now.." + e);
+ }
+ return null;
+ }
+
+ public static ReturnType acquireLockWithLease(String key, String lockId, long leasePeriod) {
+ try {
+ long start = System.currentTimeMillis();
+ /* check if the current lock has exceeded its lease and if yes, release that lock */
+ MusicLockState mls = getMusicLockState(key);
+ if (mls != null) {
+ if (mls.getLockStatus().equals(LockStatus.LOCKED)) {
+ logger.info("The current lock holder for " + key + " is " + mls.getLockHolder()
+ + ". Checking if it has exceeded lease");
+ long currentLockPeriod = System.currentTimeMillis() - mls.getLeaseStartTime();
+ long currentLeasePeriod = mls.getLeasePeriod();
+ if (currentLockPeriod > currentLeasePeriod) {
+ logger.info("Lock period " + currentLockPeriod
+ + " has exceeded lease period " + currentLeasePeriod);
+ boolean voluntaryRelease = false;
+ String currentLockHolder = mls.getLockHolder();
+ mls = releaseLock(currentLockHolder, voluntaryRelease);
+ }
+ }
+ } else
+ logger.debug("There is no lock state object for " + key);
+
+ /*
+ * call the traditional acquire lock now and if the result returned is true, set the
+ * begin time-stamp and lease period
+ */
+ if (acquireLock(key, lockId) == true) {
+ mls = getMusicLockState(key);// get latest state
+ if (mls.getLeaseStartTime() == -1) {// set it again only if it is not set already
+ mls.setLeaseStartTime(System.currentTimeMillis());
+ mls.setLeasePeriod(leasePeriod);
+ getLockingServiceHandle().setLockState(key, mls);
+ }
+ long end = System.currentTimeMillis();
+ logger.info("Time taken to acquire leased lock:" + (end - start) + " ms");
+ return new ReturnType(ResultType.SUCCESS, "Accquired lock");
+ } else {
+ long end = System.currentTimeMillis();
+ logger.info("Time taken to fail to acquire leased lock:" + (end - start) + " ms");
+ return new ReturnType(ResultType.FAILURE, "Could not acquire lock");
+ }
+ } catch (Exception e) {
+ StringWriter sw = new StringWriter();
+ logger.error(e.getMessage());
+ String exceptionAsString = sw.toString();
+ return new ReturnType(ResultType.FAILURE,
+ "Exception thrown in acquireLockWithLease:\n" + exceptionAsString);
+ }
+ }
+
+ public static boolean acquireLock(String key, String lockId) {
+ /*
+ * first check if I am on top. Since ids are not reusable there is no need to check
+ * lockStatus If the status is unlocked, then the above call will automatically return
+ * false.
+ */
+ Boolean result = false;
+ try {
+ result = getLockingServiceHandle().isMyTurn(lockId);
+ } catch (MusicLockingException e2) {
+ logger.error("Failed to aquireLock lockId " + lockId + " " + e2);
+ }
+ if (result == false) {
+ logger.info("In acquire lock: Not your turn, someone else has the lock");
+ return false;
+ }
+
+
+ // this is for backward compatibility where locks could also be acquired on just
+ // keyspaces or tables.
+ if (isTableOrKeySpaceLock(key) == true) {
+ logger.info("In acquire lock: A table or keyspace lock so no need to perform sync...so returning true");
+ return true;
+ }
+
+ // read the lock name corresponding to the key and if the status is locked or being locked,
+ // then return false
+ MusicLockState currentMls = null;
+ MusicLockState newMls = null;
+ try {
+ currentMls = getMusicLockState(key);
+ String currentLockHolder = currentMls.getLockHolder();
+ if (lockId.equals(currentLockHolder)) {
+ logger.info("In acquire lock: You already have the lock!");
+ return true;
+ }
+ } catch (NullPointerException e) {
+ logger.error("In acquire lock:No one has tried to acquire the lock yet..");
+ }
+
+ // change status to "being locked". This state transition is necessary to ensure syncing
+ // before granting the lock
+ String lockHolder = null;
+ boolean needToSyncQuorum = false;
+ if (currentMls != null)
+ needToSyncQuorum = currentMls.isNeedToSyncQuorum();
+
+
+ newMls = new MusicLockState(MusicLockState.LockStatus.BEING_LOCKED, lockHolder,
+ needToSyncQuorum);
+ try {
+ getLockingServiceHandle().setLockState(key, newMls);
+ } catch (MusicLockingException e1) {
+ logger.error("Failed to set Lock state " + key + " " + e1);
+ }
+ logger.info("In acquire lock: Set lock state to being_locked");
+
+ // do syncing if this was a forced lock release
+ if (needToSyncQuorum) {
+ logger.info("In acquire lock: Since there was a forcible release, need to sync quorum!");
+ syncQuorum(key);
+ }
+
+ // change status to locked
+ lockHolder = lockId;
+ needToSyncQuorum = false;
+ newMls = new MusicLockState(MusicLockState.LockStatus.LOCKED, lockHolder, needToSyncQuorum);
+ try {
+ getLockingServiceHandle().setLockState(key, newMls);
+ } catch (MusicLockingException e) {
+ logger.error("Failed to set Lock state " + key + " " + e);
+ }
+ logger.info("In acquire lock: Set lock state to locked and assigned current lock ref "
+ + lockId + " as holder");
+ return result;
+ }
+
+
+
+ /**
+ *
+ * @param keyspaceName
+ * @param kspObject
+ * @return
+ * @throws Exception
+ */
+ public boolean createKeyspace(String keyspaceName, JsonKeySpace kspObject) throws Exception {
+ return true;
+ }
+
+
+ private static void syncQuorum(String key) {
+ logger.info("Performing sync operation---");
+ String[] splitString = key.split("\\.");
+ String keyspaceName = splitString[0];
+ String tableName = splitString[1];
+ String primaryKeyValue = splitString[2];
+ PreparedQueryObject selectQuery = new PreparedQueryObject();
+ PreparedQueryObject updateQuery = new PreparedQueryObject();
+
+ // get the primary key d
+ TableMetadata tableInfo = returnColumnMetadata(keyspaceName, tableName);
+ String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName();// we only support single
+ // primary key
+ DataType primaryKeyType = tableInfo.getPrimaryKey().get(0).getType();
+ String cqlFormattedPrimaryKeyValue =
+ MusicUtil.convertToCQLDataType(primaryKeyType, primaryKeyValue);
+
+ // get the row of data from a quorum
+ selectQuery.appendQueryString("SELECT * FROM " + keyspaceName + "." + tableName + " WHERE "
+ + primaryKeyName + "= ?" + ";");
+ selectQuery.addValue(cqlFormattedPrimaryKeyValue);
+ // String selectQuery = "SELECT * FROM "+keyspaceName+"."+tableName+ " WHERE
+ // "+primaryKeyName+"="+cqlFormattedPrimaryKeyValue+";";
+ ResultSet results = null;
+ try {
+ results = getDSHandle().executeCriticalGet(selectQuery);
+ // write it back to a quorum
+ Row row = results.one();
+ ColumnDefinitions colInfo = row.getColumnDefinitions();
+ int totalColumns = colInfo.size();
+ int counter = 1;
+ // String fieldValueString="";
+ StringBuilder fieldValueString = new StringBuilder("");
+ for (Definition definition : colInfo) {
+ String colName = definition.getName();
+ if (colName.equals(primaryKeyName))
+ continue;
+ DataType colType = definition.getType();
+ Object valueObj = getDSHandle().getColValue(row, colName, colType);
+ String valueString = MusicUtil.convertToCQLDataType(colType, valueObj);
+ // fieldValueString = fieldValueString+ colName+"="+valueString;
+ fieldValueString.append(colName + " = ?");
+ updateQuery.addValue(valueString);
+ if (counter != (totalColumns - 1))
+ fieldValueString.append(",");
+ counter = counter + 1;
+ }
+ updateQuery.appendQueryString("UPDATE " + keyspaceName + "." + tableName + " SET "
+ + fieldValueString + " WHERE " + primaryKeyName + "= ? " + ";");
+ updateQuery.addValue(cqlFormattedPrimaryKeyValue);
+ // String updateQuery = "UPDATE "+keyspaceName+"."+tableName+" SET "+fieldValueString+"
+ // WHERE "+primaryKeyName+"="+cqlFormattedPrimaryKeyValue+";";
+
+ getDSHandle().executePut(updateQuery, "critical");
+ } catch (MusicServiceException | MusicQueryException e) {
+ logger.error("Failed to execute update query " + updateQuery + " " + e);
+ }
+ }
+
+
+ /**
+ * this function is mainly for the benchmarks to see the effect of lock deletion.
+ *
+ * @param keyspaceName
+ * @param tableName
+ * @param primaryKey
+ * @param queryObject
+ * @param conditionInfo
+ * @return
+ */
+ public static ReturnType atomicPutWithDeleteLock(String keyspaceName, String tableName,
+ String primaryKey, PreparedQueryObject queryObject, Condition conditionInfo) {
+ long start = System.currentTimeMillis();
+ String key = keyspaceName + "." + tableName + "." + primaryKey;
+ String lockId = createLockReference(key);
+ long lockCreationTime = System.currentTimeMillis();
+ long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
+ ReturnType lockAcqResult = acquireLockWithLease(key, lockId, leasePeriod);
+ long lockAcqTime = System.currentTimeMillis();
+ if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
+ logger.info("acquired lock with id " + lockId);
+ ReturnType criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey,
+ queryObject, lockId, conditionInfo);
+ long criticalPutTime = System.currentTimeMillis();
+ deleteLock(key);
+ long lockDeleteTime = System.currentTimeMillis();
+ String timingInfo = "|lock creation time:" + (lockCreationTime - start)
+ + "|lock accquire time:" + (lockAcqTime - lockCreationTime)
+ + "|critical put time:" + (criticalPutTime - lockAcqTime)
+ + "|lock delete time:" + (lockDeleteTime - criticalPutTime) + "|";
+ criticalPutResult.setTimingInfo(timingInfo);
+ return criticalPutResult;
+ } else {
+ logger.info("unable to acquire lock, id " + lockId);
+ deleteLock(key);
+ return lockAcqResult;
+ }
+ }
+
+ /**
+ *
+ * @param query
+ * @return ResultSet
+ */
+ public static ResultSet quorumGet(PreparedQueryObject query) {
+ ResultSet results = null;
+ try {
+ results = getDSHandle().executeCriticalGet(query);
+ } catch (MusicServiceException | MusicQueryException e) {
+ logger.error(e.getMessage());
+ }
+ return results;
+
+ }
+
+ /**
+ *
+ * @param results
+ * @return
+ */
+ public static Map<String, HashMap<String, Object>> marshallResults(ResultSet results) {
+ return getDSHandle().marshalData(results);
+ }
+
+ /**
+ *
+ * @param lockName
+ * @return
+ */
+ public static String whoseTurnIsIt(String lockName) {
+
+ try {
+ return getLockingServiceHandle().whoseTurnIsIt("/" + lockName) + "";
+ } catch (MusicLockingException e) {
+ logger.error("Failed whoseTurnIsIt " + lockName + " " + e);
+ }
+ return null;
+
+
+ }
+
+ /**
+ *
+ * @param lockId
+ * @return
+ */
+ public static String getLockNameFromId(String lockId) {
+ StringTokenizer st = new StringTokenizer(lockId);
+ return st.nextToken("$");
+ }
+
+ public static void destroyLockRef(String lockId) {
+ long start = System.currentTimeMillis();
+ try {
+ getLockingServiceHandle().unlockAndDeleteId(lockId);
+ } catch (MusicLockingException e) {
+ logger.error("Failed to Destroy Lock Ref " + lockId + " " + e);
+ }
+ long end = System.currentTimeMillis();
+ logger.info("Time taken to destroy lock reference:" + (end - start) + " ms");
+ }
+
+ public static MusicLockState releaseLock(String lockId, boolean voluntaryRelease) {
+ long start = System.currentTimeMillis();
+ try {
+ getLockingServiceHandle().unlockAndDeleteId(lockId);
+ } catch (MusicLockingException e1) {
+ logger.error("Failed to release Lock " + lockId + " " + e1);
+ }
+ String lockName = getLockNameFromId(lockId);
+ MusicLockState mls;
+ String lockHolder = null;
+ if (voluntaryRelease) {
+ mls = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder);
+ logger.info("In unlock: lock voluntarily released for " + lockId);
+ } else {
+ boolean needToSyncQuorum = true;
+ mls = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder,
+ needToSyncQuorum);
+ logger.info("In unlock: lock forcibly released for " + lockId);
+ }
+ try {
+ getLockingServiceHandle().setLockState(lockName, mls);
+ } catch (MusicLockingException e) {
+ logger.error("Failed to release Lock " + lockName + " " + e);
+ }
+ long end = System.currentTimeMillis();
+ logger.info("Time taken to release lock:" + (end - start) + " ms");
+ return mls;
+ }
+
+ /**
+ *
+ * @param lockName
+ */
+ public static void deleteLock(String lockName) {
+ long start = System.currentTimeMillis();
+ logger.info("Deleting lock for " + lockName);
+ try {
+ getLockingServiceHandle().deleteLock("/" + lockName);
+ } catch (MusicLockingException e) {
+ logger.error("Failed to Delete Lock " + lockName + " " + e);
+ }
+ long end = System.currentTimeMillis();
+ logger.info("Time taken to delete lock:" + (end - start) + " ms");
+ }
+
+
+
+ /**
+ *
+ * @param keyspace
+ * @param tablename
+ * @return
+ */
+ public static TableMetadata returnColumnMetadata(String keyspace, String tablename) {
+ return getDSHandle().returnColumnMetadata(keyspace, tablename);
+ }
+
+
+ /**
+ *
+ * @param nodeName
+ */
+ public static void pureZkCreate(String nodeName) {
+ try {
+ getLockingServiceHandle().getzkLockHandle().createNode(nodeName);
+ } catch (MusicLockingException e) {
+ logger.error("Failed to get ZK Lock Handle " + e);
+ }
+ }
+
+ /**
+ *
+ * @param nodeName
+ * @param data
+ */
+ public static void pureZkWrite(String nodeName, byte[] data) {
+ long start = System.currentTimeMillis();
+ logger.info("Performing zookeeper write to " + nodeName);
+ try {
+ getLockingServiceHandle().getzkLockHandle().setNodeData(nodeName, data);
+ } catch (MusicLockingException e) {
+ logger.error("Failed to get ZK Lock Handle " + e);
+ }
+ logger.info("Performed zookeeper write to " + nodeName);
+ long end = System.currentTimeMillis();
+ logger.info("Time taken for the actual zk put:" + (end - start) + " ms");
+ }
+
+ /**
+ *
+ * @param nodeName
+ * @return
+ */
+ public static byte[] pureZkRead(String nodeName) {
+ long start = System.currentTimeMillis();
+ byte[] data = null;
+ try {
+ data = getLockingServiceHandle().getzkLockHandle().getNodeData(nodeName);
+ } catch (MusicLockingException e) {
+ logger.error("Failed to get ZK Lock Handle " + e);
+ }
+ long end = System.currentTimeMillis();
+ logger.info("Time taken for the actual zk put:" + (end - start) + " ms");
+ return data;
+ }
+
+
+
+ // Prepared Query Additions.
+
+ /**
+ *
+ * @param keyspaceName
+ * @param tableName
+ * @param primaryKey
+ * @param queryObject
+ * @return ReturnType
+ * @throws MusicServiceException
+ */
+ public static ReturnType eventualPut(PreparedQueryObject queryObject) {
+ boolean result = false;
+ try {
+ result = getDSHandle().executePut(queryObject, MusicUtil.EVENTUAL);
+ } catch (MusicServiceException | MusicQueryException ex) {
+ logger.error(ex.getMessage() + " " + ex.getCause() + " " + ex);
+ }
+ if (result) {
+ return new ReturnType(ResultType.SUCCESS, "Success");
+ } else {
+ return new ReturnType(ResultType.FAILURE, "Failure");
+ }
+ }
+
+ /**
+ *
+ * @param keyspaceName
+ * @param tableName
+ * @param primaryKey
+ * @param queryObject
+ * @param lockId
+ * @return
+ */
+ public static ReturnType criticalPut(String keyspaceName, String tableName, String primaryKey,
+ PreparedQueryObject queryObject, String lockId, Condition conditionInfo) {
+ long start = System.currentTimeMillis();
+
+ try {
+ MusicLockState mls = getLockingServiceHandle()
+ .getLockState(keyspaceName + "." + tableName + "." + primaryKey);
+ if (mls.getLockHolder().equals(lockId) == true) {
+ if (conditionInfo != null)// check if condition is true
+ if (conditionInfo.testCondition() == false)
+ return new ReturnType(ResultType.FAILURE,
+ "Lock acquired but the condition is not true");
+ getDSHandle().executePut(queryObject, MusicUtil.CRITICAL);
+ long end = System.currentTimeMillis();
+ logger.info("Time taken for the critical put:" + (end - start) + " ms");
+ return new ReturnType(ResultType.SUCCESS, "Update performed");
+ } else
+ return new ReturnType(ResultType.FAILURE,
+ "Cannot perform operation since you are the not the lock holder");
+ } catch (MusicQueryException | MusicServiceException | MusicLockingException e) {
+ logger.error(e.getMessage());
+ return new ReturnType(ResultType.FAILURE,
+ "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n"
+ + e.getMessage());
+ }
+
+ }
+
+ /**
+ *
+ * @param queryObject
+ * @param consistency
+ * @return Boolean Indicates success or failure
+ *
+ *
+ */
+ public static boolean nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) {
+ // this is mainly for some functions like keyspace creation etc which does not
+ // really need the bells and whistles of Music locking.
+ boolean result = false;
+ try {
+ result = getDSHandle().executePut(queryObject, consistency);
+ } catch (MusicQueryException | MusicServiceException ex) {
+ logger.error(ex.getMessage());
+ }
+ return result;
+ }
+
+ /**
+ * This method performs DDL operation on cassandra.
+ *
+ * @param queryObject query object containing prepared query and values
+ * @return ResultSet
+ */
+ public static ResultSet get(PreparedQueryObject queryObject) {
+ ResultSet results = null;
+ try {
+ results = getDSHandle().executeEventualGet(queryObject);
+ } catch (MusicQueryException | MusicServiceException e) {
+ logger.error(e.getMessage());
+ }
+ return results;
+ }
+
+ /**
+ * This method performs DDL operations on cassandra, if the the resource is available. Lock ID
+ * is used to check if the resource is free.
+ *
+ * @param keyspaceName name of the keyspace
+ * @param tableName name of the table
+ * @param primaryKey primary key value
+ * @param queryObject query object containing prepared query and values
+ * @param lockId lock ID to check if the resource is free to perform the operation.
+ * @return ResultSet
+ */
+ public static ResultSet criticalGet(String keyspaceName, String tableName, String primaryKey,
+ PreparedQueryObject queryObject, String lockId) throws MusicServiceException {
+ ResultSet results = null;
+ try {
+ MusicLockState mls = getLockingServiceHandle()
+ .getLockState(keyspaceName + "." + tableName + "." + primaryKey);
+ if (mls.getLockHolder().equals(lockId)) {
+ results = getDSHandle().executeCriticalGet(queryObject);
+ } else
+ throw new MusicServiceException("YOU DO NOT HAVE THE LOCK");
+ } catch (MusicQueryException | MusicServiceException | MusicLockingException e) {
+ logger.error(e.getMessage());
+ }
+ return results;
+ }
+
+ /**
+ * This method performs DML operation on cassandra, when the lock of the dd is acquired.
+ *
+ * @param keyspaceName name of the keyspace
+ * @param tableName name of the table
+ * @param primaryKey primary key value
+ * @param queryObject query object containing prepared query and values
+ * @return ReturnType
+ */
+ public static ReturnType atomicPut(String keyspaceName, String tableName, String primaryKey,
+ PreparedQueryObject queryObject, Condition conditionInfo) {
+ long start = System.currentTimeMillis();
+ String key = keyspaceName + "." + tableName + "." + primaryKey;
+ String lockId = createLockReference(key);
+ long lockCreationTime = System.currentTimeMillis();
+ long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
+ ReturnType lockAcqResult = acquireLockWithLease(key, lockId, leasePeriod);
+ long lockAcqTime = System.currentTimeMillis();
+ if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
+ logger.info("acquired lock with id " + lockId);
+ ReturnType criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey,
+ queryObject, lockId, conditionInfo);
+ long criticalPutTime = System.currentTimeMillis();
+ boolean voluntaryRelease = true;
+ deleteLock(key);
+ long lockDeleteTime = System.currentTimeMillis();
+ String timingInfo = "|lock creation time:" + (lockCreationTime - start)
+ + "|lock accquire time:" + (lockAcqTime - lockCreationTime)
+ + "|critical put time:" + (criticalPutTime - lockAcqTime)
+ + "|lock delete time:" + (lockDeleteTime - criticalPutTime) + "|";
+ criticalPutResult.setTimingInfo(timingInfo);
+ return criticalPutResult;
+ } else {
+ logger.info("unable to acquire lock, id " + lockId);
+ destroyLockRef(lockId);
+ return lockAcqResult;
+ }
+ }
+
+
+ /**
+ * This method performs DDL operation on cassasndra, when the lock for the resource is acquired.
+ *
+ * @param keyspaceName name of the keyspace
+ * @param tableName name of the table
+ * @param primaryKey primary key value
+ * @param queryObject query object containing prepared query and values
+ * @return ResultSet
+ * @throws MusicServiceException
+ */
+ public static ResultSet atomicGet(String keyspaceName, String tableName, String primaryKey,
+ PreparedQueryObject queryObject) throws MusicServiceException {
+ String key = keyspaceName + "." + tableName + "." + primaryKey;
+ String lockId = createLockReference(key);
+ long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
+ ReturnType lockAcqResult = acquireLockWithLease(key, lockId, leasePeriod);
+ if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
+ logger.info("acquired lock with id " + lockId);
+ ResultSet result =
+ criticalGet(keyspaceName, tableName, primaryKey, queryObject, lockId);
+ boolean voluntaryRelease = true;
+ releaseLock(lockId, voluntaryRelease);
+ return result;
+ } else {
+ logger.info("unable to acquire lock, id " + lockId);
+ return null;
+ }
+ }
+
+ /**
+ * authenticate user logic
+ *
+ * @param nameSpace
+ * @param userId
+ * @param password
+ * @param keyspace
+ * @param aid
+ * @param operation
+ * @return
+ * @throws Exception
+ */
+ public static Map<String, Object> autheticateUser(String nameSpace, String userId,
+ String password, String keyspace, String aid, String operation)
+ throws Exception {
+ Map<String, Object> resultMap = new HashMap<>();
+ String uuid = null;
+ resultMap = CachingUtil.validateRequest(nameSpace, userId, password, keyspace, aid,
+ operation);
+ if (!resultMap.isEmpty())
+ return resultMap;
+ if (aid == null && (userId == null || password == null)) {
+ logger.error("One or more required headers is missing. userId: " + userId
+ + " :: password: " + password);
+ resultMap.put("Exception",
+ "UserId and Password are mandatory for the operation " + operation);
+ return resultMap;
+ }
+ boolean isAAF = CachingUtil.isAAFApplication(nameSpace);
+ if (!isAAF && aid != null && aid.length() > 0) { // Non AAF app
+ resultMap = CachingUtil.authenticateAIDUser(aid, keyspace);
+ if (!resultMap.isEmpty())
+ return resultMap;
+ }
+ if (isAAF && nameSpace != null && userId != null && password != null) {
+ boolean isValid = true;
+ try {
+ isValid = CachingUtil.authenticateAAFUser(nameSpace, userId, password, keyspace);
+ } catch (Exception e) {
+ logger.error("Got exception while AAF authentication for namespace " + nameSpace);
+ resultMap.put("Exception", e.getMessage());
+ // return resultMap;
+ }
+ if (!isValid) {
+ logger.error("User not authenticated with AAF.");
+ resultMap.put("Exception", "User not authenticated...");
+ // return resultMap;
+ }
+ if (!resultMap.isEmpty())
+ return resultMap;
+
+ }
+
+ if (operation.equals("createKeySpace")) {
+ logger.info("AID is not provided. Creating new UUID for keyspace.");
+ PreparedQueryObject pQuery = new PreparedQueryObject();
+ pQuery.appendQueryString(
+ "select uuid from admin.keyspace_master where application_name=? and username=? and keyspace_name=? allow filtering");
+ pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), nameSpace));
+ pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId));
+ pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(),
+ MusicUtil.DEFAULTKEYSPACENAME));
+
+ try {
+ Row rs = MusicCore.get(pQuery).one();
+ uuid = rs.getUUID("uuid").toString();
+ resultMap.put("uuid", "existing");
+ } catch (Exception e) {
+ logger.info("No UUID found in DB. So creating new UUID.");
+ uuid = CachingUtil.generateUUID();
+ resultMap.put("uuid", "new");
+ }
+
+ pQuery = new PreparedQueryObject();
+ 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(), keyspace));
+ pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), nameSpace));
+ 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));
+ CachingUtil.updateMusicCache(uuid, keyspace);
+ MusicCore.eventualPut(pQuery);
+ resultMap.put("aid", uuid);
+ }
+
+ return resultMap;
+ }
+}
diff --git a/src/main/java/org/onap/music/main/MusicDigest.java b/src/main/java/org/onap/music/main/MusicDigest.java
new file mode 100644
index 00000000..893cb51f
--- /dev/null
+++ b/src/main/java/org/onap/music/main/MusicDigest.java
@@ -0,0 +1,78 @@
+/*
+ * ============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.main;
+
+/**
+ *
+ *
+ */
+public class MusicDigest {
+ private String evPutStatus;
+ private String vectorTs;
+
+ /**
+ * @param evPutStatus
+ * @param vectorTs
+ */
+ public MusicDigest(String evPutStatus, String vectorTs) {
+ this.evPutStatus = evPutStatus;
+ this.vectorTs = vectorTs;
+ }
+
+ /**
+ * @return
+ */
+ public String getEvPutStatus() {
+ return evPutStatus;
+ }
+
+ /**
+ * @param evPutStatus
+ */
+ public void setEvPutStatus(String evPutStatus) {
+ this.evPutStatus = evPutStatus;
+ }
+
+ /**
+ * @return
+ */
+ public String getVectorTs() {
+ return vectorTs;
+ }
+
+ /**
+ * @param vectorTs
+ */
+ public void setVectorTs(String vectorTs) {
+ this.vectorTs = vectorTs;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return vectorTs + "|" + evPutStatus;
+ }
+}
+
diff --git a/src/main/java/org/onap/music/main/MusicUtil.java b/src/main/java/org/onap/music/main/MusicUtil.java
new file mode 100755
index 00000000..61d428d1
--- /dev/null
+++ b/src/main/java/org/onap/music/main/MusicUtil.java
@@ -0,0 +1,465 @@
+/*
+ * ============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.main;
+
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.UUID;
+import org.onap.music.datastore.PreparedQueryObject;
+import org.onap.music.eelf.logging.EELFLoggerDelegate;
+import com.datastax.driver.core.DataType;
+
+/**
+ * @author nelson24
+ *
+ * Properties This will take Properties and load them into MusicUtil. This is a hack for
+ * now. Eventually it would bebest to do this in another way.
+ *
+ */
+public class MusicUtil {
+ private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicUtil.class);
+
+ private static int myId = 0;
+ private static ArrayList<String> allIds = new ArrayList<String>();
+ private static String publicIp = "";
+ private static ArrayList<String> allPublicIps = new ArrayList<String>();
+ private static String myZkHost = "localhost";
+ private static String myCassaHost = "localhost";
+ private static String defaultMusicIp = "localhost";
+ private static boolean debug = true;
+ private static String version = "2.3.0";
+ public static String musicRestIp = "localhost";
+ private static String musicPropertiesFilePath = "/opt/app/music/etc/music.properties";
+ private static long defaultLockLeasePeriod = 6000;
+ private static final String[] propKeys = new String[] {"zookeeper.host", "cassandra.host",
+ "music.ip", "debug", "version", "music.rest.ip", "music.properties",
+ "lock.lease.period", "id", "all.ids", "public.ip", "all.pubic.ips",
+ "cassandra.user", "cassandra.password", "aaf.endpoint.url"};
+
+ public static final String ATOMIC = "atomic";
+ public static final String EVENTUAL = "eventual";
+ public static final String CRITICAL = "critical";
+ public static final String DEFAULTKEYSPACENAME = "TBD";
+ private static String cassName = "cassandra";
+ private static String cassPwd = "cassandra";
+ private static String aafEndpointUrl = null;
+
+ /**
+ * @return the cassName
+ */
+ public static String getCassName() {
+ return cassName;
+ }
+
+ /**
+ * @return the cassPwd
+ */
+ public static String getCassPwd() {
+ return cassPwd;
+ }
+
+ /**
+ * @return the aafEndpointUrl
+ */
+ public static String getAafEndpointUrl() {
+ return aafEndpointUrl;
+ }
+
+ /**
+ *
+ * @param aafEndpointUrl
+ */
+ public static void setAafEndpointUrl(String aafEndpointUrl) {
+ MusicUtil.aafEndpointUrl = aafEndpointUrl;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public static int getMyId() {
+ return myId;
+ }
+
+ /**
+ *
+ * @param myId
+ */
+ public static void setMyId(int myId) {
+ MusicUtil.myId = myId;
+ }
+
+
+ /**
+ *
+ * @return
+ */
+ public static ArrayList<String> getAllIds() {
+ return allIds;
+ }
+
+ /**
+ *
+ * @param allIds
+ */
+ public static void setAllIds(List<String> allIds) {
+ MusicUtil.allIds = (ArrayList<String>) allIds;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public static String getPublicIp() {
+ return publicIp;
+ }
+
+ /**
+ *
+ * @param publicIp
+ */
+ public static void setPublicIp(String publicIp) {
+ MusicUtil.publicIp = publicIp;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public static ArrayList<String> getAllPublicIps() {
+ return allPublicIps;
+ }
+
+ /**
+ *
+ * @param allPublicIps
+ */
+ public static void setAllPublicIps(List<String> allPublicIps) {
+ MusicUtil.allPublicIps = (ArrayList<String>) allPublicIps;
+ }
+
+ /**
+ * Returns An array of property names that should be in the Properties files.
+ *
+ * @return
+ */
+ public static String[] getPropkeys() {
+ return propKeys;
+ }
+
+ /**
+ * Get MusicRestIp - default = localhost property file value - music.rest.ip
+ *
+ * @return
+ */
+ public static String getMusicRestIp() {
+ return musicRestIp;
+ }
+
+ /**
+ * Set MusicRestIp
+ *
+ * @param musicRestIp
+ */
+ public static void setMusicRestIp(String musicRestIp) {
+ MusicUtil.musicRestIp = musicRestIp;
+ }
+
+ /**
+ * Get MusicPropertiesFilePath - Default = /opt/music/music.properties property file value -
+ * music.properties
+ *
+ * @return
+ */
+ public static String getMusicPropertiesFilePath() {
+ return musicPropertiesFilePath;
+ }
+
+ /**
+ * Set MusicPropertiesFilePath
+ *
+ * @param musicPropertiesFilePath
+ */
+ public static void setMusicPropertiesFilePath(String musicPropertiesFilePath) {
+ MusicUtil.musicPropertiesFilePath = musicPropertiesFilePath;
+ }
+
+ /**
+ * Get DefaultLockLeasePeriod - Default = 6000 property file value - lock.lease.period
+ *
+ * @return
+ */
+ public static long getDefaultLockLeasePeriod() {
+ return defaultLockLeasePeriod;
+ }
+
+ /**
+ * Set DefaultLockLeasePeriod
+ *
+ * @param defaultLockLeasePeriod
+ */
+ public static void setDefaultLockLeasePeriod(long defaultLockLeasePeriod) {
+ MusicUtil.defaultLockLeasePeriod = defaultLockLeasePeriod;
+ }
+
+ /**
+ * Set Debug
+ *
+ * @param debug
+ */
+ public static void setDebug(boolean debug) {
+ MusicUtil.debug = debug;
+ }
+
+ /**
+ * Is Debug - Default = true property file value - debug
+ *
+ * @return
+ */
+ public static boolean isDebug() {
+ return debug;
+ }
+
+ /**
+ * Set Version
+ *
+ * @param version
+ */
+ public static void setVersion(String version) {
+ MusicUtil.version = version;
+ }
+
+ /**
+ * Return the version property file value - version
+ *
+ * @return
+ */
+ public static String getVersion() {
+ return version;
+ }
+
+ /**
+ * Get MyZkHost - Zookeeper Hostname - Default = localhost property file value - zookeeper.host
+ *
+ * @return
+ */
+ public static String getMyZkHost() {
+ return myZkHost;
+ }
+
+ /**
+ * Set MyZkHost - Zookeeper Hostname
+ *
+ * @param myZkHost
+ */
+ public static void setMyZkHost(String myZkHost) {
+ MusicUtil.myZkHost = myZkHost;
+ }
+
+ /**
+ * Get MyCassHost - Cassandra Hostname - Default = localhost property file value -
+ * cassandra.host
+ *
+ * @return
+ */
+ public static String getMyCassaHost() {
+ return myCassaHost;
+ }
+
+ /**
+ * Set MyCassHost - Cassandra Hostname
+ *
+ * @param myCassaHost
+ */
+ public static void setMyCassaHost(String myCassaHost) {
+ MusicUtil.myCassaHost = myCassaHost;
+ }
+
+ /**
+ * Get DefaultMusicIp - Default = localhost property file value - music.ip
+ *
+ * @return
+ */
+ public static String getDefaultMusicIp() {
+ return defaultMusicIp;
+ }
+
+ /**
+ * Set DefaultMusicIp
+ *
+ * @param defaultMusicIp
+ */
+ public static void setDefaultMusicIp(String defaultMusicIp) {
+ MusicUtil.defaultMusicIp = defaultMusicIp;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public static String getTestType() {
+ String testType = "";
+ try {
+ Scanner fileScanner = new Scanner(new File(""));
+ testType = fileScanner.next();// ignore the my id line
+ String batchSize = fileScanner.next();// ignore the my public ip line
+ fileScanner.close();
+ } catch (FileNotFoundException e) {
+ logger.error(EELFLoggerDelegate.errorLogger, e.getMessage());
+ }
+ return testType;
+
+ }
+
+ /**
+ *
+ * @param time
+ */
+ public static void sleep(long time) {
+ try {
+ Thread.sleep(time);
+ } catch (InterruptedException e) {
+ logger.error(EELFLoggerDelegate.errorLogger, e.getMessage());
+ }
+ }
+
+ /**
+ * Utility function to check if the query object is valid.
+ *
+ * @param withparams
+ * @param queryObject
+ * @return
+ */
+ public static boolean isValidQueryObject(boolean withparams, PreparedQueryObject queryObject) {
+ if (withparams) {
+ int noOfValues = queryObject.getValues().size();
+ int noOfParams = 0;
+ char[] temp = queryObject.getQuery().toCharArray();
+ for (int i = 0; i < temp.length; i++) {
+ if (temp[i] == '?')
+ noOfParams++;
+ }
+ return (noOfValues == noOfParams);
+ } else {
+ return !queryObject.getQuery().isEmpty();
+ }
+
+ }
+
+ public static void setCassName(String cassName) {
+ MusicUtil.cassName = cassName;
+ }
+
+ public static void setCassPwd(String cassPwd) {
+ MusicUtil.cassPwd = cassPwd;
+ }
+
+ public static String convertToCQLDataType(DataType type, Object valueObj) {
+
+ String value = "";
+ switch (type.getName()) {
+ case UUID:
+ value = valueObj + "";
+ break;
+ case TEXT:
+ case VARCHAR:
+ String valueString = valueObj + "";
+ valueString = valueString.replace("'", "''");
+ value = "'" + valueString + "'";
+ break;
+ case MAP: {
+ Map<String, Object> otMap = (Map<String, Object>) valueObj;
+ value = "{" + jsonMaptoSqlString(otMap, ",") + "}";
+ break;
+ }
+ default:
+ value = valueObj + "";
+ break;
+ }
+ return value;
+ }
+
+
+ /**
+ *
+ * @param colType
+ * @param valueObj
+ * @return
+ * @throws Exception
+ */
+ public static Object convertToActualDataType(DataType colType, Object valueObj) {
+ String valueObjString = valueObj + "";
+ switch (colType.getName()) {
+ case UUID:
+ return UUID.fromString(valueObjString);
+ case VARINT:
+ return BigInteger.valueOf(Long.parseLong(valueObjString));
+ case BIGINT:
+ return Long.parseLong(valueObjString);
+ case INT:
+ return Integer.parseInt(valueObjString);
+ case FLOAT:
+ return Float.parseFloat(valueObjString);
+ case DOUBLE:
+ return Double.parseDouble(valueObjString);
+ case BOOLEAN:
+ return Boolean.parseBoolean(valueObjString);
+ case MAP:
+ return (Map<String, Object>) valueObj;
+ default:
+ return valueObjString;
+ }
+ }
+
+
+ /**
+ *
+ * Utility function to parse json map into sql like string
+ *
+ * @param jMap
+ * @param lineDelimiter
+ * @return
+ */
+
+ public static String jsonMaptoSqlString(Map<String, Object> jMap, String lineDelimiter) {
+ StringBuilder sqlString = new StringBuilder();
+ int counter = 0;
+ for (Map.Entry<String, Object> entry : jMap.entrySet()) {
+ Object ot = entry.getValue();
+ String value = ot + "";
+ if (ot instanceof String) {
+ value = "'" + value.replace("'", "''") + "'";
+ }
+ sqlString.append("'" + entry.getKey() + "':" + value);
+ if (counter != jMap.size() - 1)
+ sqlString.append(lineDelimiter);
+ counter = counter + 1;
+ }
+ return sqlString.toString();
+ }
+}
diff --git a/src/main/java/org/onap/music/main/PropertiesListener.java b/src/main/java/org/onap/music/main/PropertiesListener.java
new file mode 100755
index 00000000..de231542
--- /dev/null
+++ b/src/main/java/org/onap/music/main/PropertiesListener.java
@@ -0,0 +1,147 @@
+/*
+ * ============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.main;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Properties;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.annotation.WebListener;
+import org.onap.music.eelf.logging.EELFLoggerDelegate;
+
+@WebListener
+public class PropertiesListener implements ServletContextListener {
+ private Properties prop;
+
+ private static EELFLoggerDelegate logger =
+ EELFLoggerDelegate.getLogger(PropertiesListener.class);
+
+ @Override
+ public void contextInitialized(ServletContextEvent servletContextEvent) {
+ prop = new Properties();
+ Properties projectProp = new Properties();
+ URL resource = getClass().getResource("/");
+ String musicPropertiesFilePath = resource.getPath().replace("WEB-INF/classes/",
+ "WEB-INF/classes/project.properties");
+
+ // Open the file
+ try {
+ InputStream musicProps = null;
+ projectProp.load(new FileInputStream(musicPropertiesFilePath));
+ if (projectProp.containsKey("music.properties")) {
+ musicProps = new FileInputStream(projectProp.getProperty("music.properties"));
+ } else {
+ musicProps = new FileInputStream(MusicUtil.getMusicPropertiesFilePath());
+ }
+ prop.load(musicProps);
+ musicProps.close();
+ prop.putAll(projectProp);
+ String[] propKeys = MusicUtil.getPropkeys();
+ for (int k = 0; k < propKeys.length; k++) {
+ String key = propKeys[k];
+ if (prop.containsKey(key) && prop.get(key) != null) {
+ logger.info(key + " : " + prop.getProperty(key));
+ switch (key) {
+ case "zookeeper.host":
+ MusicUtil.setMyZkHost(prop.getProperty(key));
+ break;
+ case "cassandra.host":
+ MusicUtil.setMyCassaHost(prop.getProperty(key));
+ break;
+ case "music.ip":
+ MusicUtil.setDefaultMusicIp(prop.getProperty(key));
+ break;
+ case "debug":
+ MusicUtil.setDebug(Boolean
+ .getBoolean(prop.getProperty(key).toLowerCase()));
+ break;
+ case "version":
+ MusicUtil.setVersion(prop.getProperty(key));
+ break;
+ case "music.rest.ip":
+ MusicUtil.setMusicRestIp(prop.getProperty(key));
+ break;
+ case "music.properties":
+ MusicUtil.setMusicPropertiesFilePath(prop.getProperty(key));
+ break;
+ case "lock.lease.period":
+ MusicUtil.setDefaultLockLeasePeriod(
+ Long.parseLong(prop.getProperty(key)));
+ break;
+ case "my.id":
+ MusicUtil.setMyId(Integer.parseInt(prop.getProperty(key)));
+ break;
+ case "all.ids":
+ String[] ids = prop.getProperty(key).split(":");
+ MusicUtil.setAllIds(new ArrayList<String>(Arrays.asList(ids)));
+ break;
+ case "public.ip":
+ MusicUtil.setPublicIp(prop.getProperty(key));
+ break;
+ case "all.public.ips":
+ String[] ips = prop.getProperty(key).split(":");
+ if (ips.length == 1) {
+ // Future use
+ } else if (ips.length > 1) {
+ MusicUtil.setAllPublicIps(
+ new ArrayList<String>(Arrays.asList(ips)));
+ }
+ break;
+ case "cassandra.user":
+ MusicUtil.setCassName(prop.getProperty(key));
+ break;
+ case "cassandra.password":
+ MusicUtil.setCassPwd(prop.getProperty(key));
+ break;
+ case "aaf.endpoint.url":
+ MusicUtil.setAafEndpointUrl(prop.getProperty(key));
+ break;
+ default:
+ logger.error(EELFLoggerDelegate.errorLogger,
+ "No case found for " + key);
+ }
+ }
+ }
+ } catch (IOException e) {
+ logger.error(EELFLoggerDelegate.errorLogger, e.getMessage());
+ }
+
+ logger.info(EELFLoggerDelegate.applicationLogger,
+ "Starting MUSIC " + MusicUtil.getVersion() + " on node with id "
+ + MusicUtil.getMyId() + " and public ip "
+ + MusicUtil.getPublicIp() + "...");
+ logger.info(EELFLoggerDelegate.applicationLogger,
+ "List of all MUSIC ids:" + MusicUtil.getAllIds().toString());
+ logger.info(EELFLoggerDelegate.applicationLogger,
+ "List of all MUSIC public ips:" + MusicUtil.getAllPublicIps().toString());
+ }
+
+ @Override
+ public void contextDestroyed(ServletContextEvent servletContextEvent) {
+ prop = null;
+ }
+}
diff --git a/src/main/java/org/onap/music/main/ResultType.java b/src/main/java/org/onap/music/main/ResultType.java
new file mode 100644
index 00000000..f19ada4a
--- /dev/null
+++ b/src/main/java/org/onap/music/main/ResultType.java
@@ -0,0 +1,39 @@
+/*
+ * ============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.main;
+
+public enum ResultType {
+ SUCCESS("Success"), FAILURE("Failure");
+
+ private String result;
+
+ ResultType(String result) {
+ this.result = result;
+ }
+
+ public String getResult() {
+ return result;
+ }
+
+}
+
+
diff --git a/src/main/java/org/onap/music/main/ReturnType.java b/src/main/java/org/onap/music/main/ReturnType.java
new file mode 100644
index 00000000..1453a1bf
--- /dev/null
+++ b/src/main/java/org/onap/music/main/ReturnType.java
@@ -0,0 +1,74 @@
+/*
+ * ============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.main;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ReturnType {
+ private ResultType result;
+ private String message;
+
+ public ReturnType(ResultType result, String message) {
+ super();
+ this.result = result;
+ this.message = message;
+ }
+
+ public String getTimingInfo() {
+ return timingInfo;
+ }
+
+ public void setTimingInfo(String timingInfo) {
+ this.timingInfo = timingInfo;
+ }
+
+ private String timingInfo;
+
+ public ResultType getResult() {
+ return result;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String toJson() {
+ return "{ \"result\":\"" + result.getResult() + "\", \"message\":\"" + message + "\"}";
+ }
+
+ public String toString() {
+ return result + " | " + message;
+ }
+
+ public Map<String, Object> toMap() {
+ Map<String, Object> newMap = new HashMap<>();
+ newMap.put("result", result.getResult());
+ newMap.put("message", message);
+ return newMap;
+ }
+
+}