aboutsummaryrefslogtreecommitdiffstats
path: root/jar/src/main/java/org/onap/music/main
diff options
context:
space:
mode:
Diffstat (limited to 'jar/src/main/java/org/onap/music/main')
-rwxr-xr-xjar/src/main/java/org/onap/music/main/CachingUtil.java420
-rw-r--r--jar/src/main/java/org/onap/music/main/CronJobManager.java47
-rw-r--r--jar/src/main/java/org/onap/music/main/MusicCore.java992
-rw-r--r--jar/src/main/java/org/onap/music/main/MusicDigest.java78
-rwxr-xr-xjar/src/main/java/org/onap/music/main/MusicUtil.java560
-rwxr-xr-xjar/src/main/java/org/onap/music/main/PropertiesListener.java151
-rw-r--r--jar/src/main/java/org/onap/music/main/ResultType.java41
-rw-r--r--jar/src/main/java/org/onap/music/main/ReturnType.java74
8 files changed, 2363 insertions, 0 deletions
diff --git a/jar/src/main/java/org/onap/music/main/CachingUtil.java b/jar/src/main/java/org/onap/music/main/CachingUtil.java
new file mode 100755
index 00000000..aa06aae2
--- /dev/null
+++ b/jar/src/main/java/org/onap/music/main/CachingUtil.java
@@ -0,0 +1,420 @@
+/*
+ * ============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.codehaus.jackson.map.ObjectMapper;
+import org.mindrot.jbcrypt.BCrypt;
+import org.onap.music.datastore.PreparedQueryObject;
+import org.onap.music.datastore.jsonobjects.AAFResponse;
+import org.onap.music.eelf.logging.EELFLoggerDelegate;
+import org.onap.music.eelf.logging.format.AppMessages;
+import org.onap.music.eelf.logging.format.ErrorSeverity;
+import org.onap.music.eelf.logging.format.ErrorTypes;
+import org.onap.music.exceptions.MusicServiceException;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.datastax.driver.core.DataType;
+import com.datastax.driver.core.ResultSet;
+import com.datastax.driver.core.Row;
+import com.datastax.driver.core.exceptions.InvalidQueryException;
+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 EELFLoggerDelegate logger = EELFLoggerDelegate.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 CacheAccess<String, Map<String, String>> musicValidateCache = JCS.getInstance("musicValidateCache");
+ 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(EELFLoggerDelegate.applicationLogger,"Initializing Music Cache...");
+ musicCache.put("isInitialized", "true");
+ }
+
+ public void initializeAafCache() throws MusicServiceException {
+ logger.info(EELFLoggerDelegate.applicationLogger,"Resetting and initializing AAF Cache...");
+
+ String query = "SELECT uuid, 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) {
+ logger.error(EELFLoggerDelegate.errorLogger, e1.getMessage(),AppMessages.CACHEERROR, ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
+ e1.printStackTrace();
+ }
+ 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(keySpace, nameSpace);
+ logger.debug("Cronjob: Cache Updated with AAF response for namespace "
+ + nameSpace);
+ }
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.UNKNOWNERROR, ErrorSeverity.INFO, ErrorTypes.GENERALSERVICEERROR);
+ logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),"Something at AAF was changed for ns: " + nameSpace+" So not updating Cache for the namespace. ");
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+ @Override
+ public void run() {
+ logger.info(EELFLoggerDelegate.applicationLogger,"Scheduled task invoked. Refreshing Cache...");
+ try {
+ initializeAafCache();
+ } catch (MusicServiceException e) {
+ logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.UNKNOWNERROR, ErrorSeverity.INFO, ErrorTypes.GENERALSERVICEERROR);
+ }
+ }
+
+ public static boolean authenticateAAFUser(String nameSpace, String userId, String password,
+ String keySpace) throws Exception {
+
+ if (aafCache.get(nameSpace) != null) {
+ if (keySpace != null && !musicCache.get(keySpace).equals(nameSpace)) {
+ logger.info(EELFLoggerDelegate.applicationLogger,"Create new application for the same namespace.");
+ } else if (aafCache.get(nameSpace).get(userId).equals(password)) {
+ logger.info(EELFLoggerDelegate.applicationLogger,"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(EELFLoggerDelegate.applicationLogger,"Reached max attempts. Checking if time out..");
+ logger.info(EELFLoggerDelegate.applicationLogger,"Failed time: "+lastFailedTime.get(nameSpace).getTime());
+ Calendar calendar = Calendar.getInstance();
+ long delayTime = (calendar.getTimeInMillis()-lastFailedTime.get(nameSpace).getTimeInMillis());
+ logger.info(EELFLoggerDelegate.applicationLogger,"Delayed time: "+delayTime);
+ if( delayTime > 120000) {
+ logger.info(EELFLoggerDelegate.applicationLogger,"Resetting failed attempt.");
+ userAttempts.put(nameSpace, 0);
+ } else {
+ logger.info(EELFLoggerDelegate.applicationLogger,"No more attempts allowed. Please wait for atleast 2 min.");
+ throw new Exception("No more attempts allowed. Please wait for atleast 2 min.");
+ }
+ }
+ logger.error(EELFLoggerDelegate.errorLogger,"",AppMessages.CACHEAUTHENTICATION,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
+ logger.info(EELFLoggerDelegate.applicationLogger,"Check AAF again...");
+ }
+ }
+
+ AAFResponse responseObj = triggerAAF(nameSpace, userId, password);
+ if (responseObj.getNs().size() > 0) {
+ if (responseObj.getNs().get(0).getAdmin().contains(userId)) {
+ //Map<String, String> map = new HashMap<>();
+ //map.put(userId, password);
+ //aafCache.put(nameSpace, map);
+ return true;
+ }
+ }
+ logger.info(EELFLoggerDelegate.applicationLogger,"Invalid user. Cache not updated");
+ return false;
+ }
+
+ private static AAFResponse triggerAAF(String nameSpace, String userId, String password)
+ throws Exception {
+ if (MusicUtil.getAafEndpointUrl() == null) {
+ logger.error(EELFLoggerDelegate.errorLogger,"",AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
+ 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 void updateMusicCache(String keyspace, String nameSpace) {
+ logger.info(EELFLoggerDelegate.applicationLogger,"Updating musicCache for keyspace " + keyspace + " with nameSpace " + nameSpace);
+ musicCache.put(keyspace, nameSpace);
+ }
+
+ public static void updateMusicValidateCache(String nameSpace, String userId, String password) {
+ logger.info(EELFLoggerDelegate.applicationLogger,"Updating musicCache for nameSpacce " + nameSpace + " with userId " + userId);
+ Map<String, String> map = new HashMap<>();
+ map.put(userId, password);
+ musicValidateCache.put(nameSpace, map);
+ }
+
+ public static void updateisAAFCache(String namespace, String isAAF) {
+ appNameCache.put(namespace, isAAF);
+ }
+
+ public static String isAAFApplication(String namespace) throws MusicServiceException {
+ 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 = null;
+ try {
+ rs = MusicCore.get(pQuery).one();
+ } catch(InvalidQueryException e) {
+ logger.error(EELFLoggerDelegate.errorLogger,"Exception admin keyspace not configured."+e.getMessage());
+ throw new MusicServiceException("Please make sure admin.keyspace_master table is configured.");
+ }
+ try {
+ isAAF = String.valueOf(rs.getBool("is_aaf"));
+ if(isAAF != null)
+ appNameCache.put(namespace, isAAF);
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), AppMessages.QUERYERROR,ErrorSeverity.ERROR, ErrorTypes.QUERYERROR);
+ e.printStackTrace();
+ }
+ }
+ return isAAF;
+ }
+
+ public static String getUuidFromMusicCache(String keyspace) throws MusicServiceException {
+ String uuid = null;
+ 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();
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger,"Exception occured during uuid retrieval from DB."+e.getMessage());
+ e.printStackTrace();
+ }
+ }
+ return uuid;
+ }
+
+ public static String getAppName(String keyspace) throws MusicServiceException {
+ 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(EELFLoggerDelegate.errorLogger, e.getMessage(), AppMessages.QUERYERROR, ErrorSeverity.ERROR, ErrorTypes.QUERYERROR);
+ e.printStackTrace();
+ }
+ return appName;
+ }
+
+ public static String generateUUID() {
+ String uuid = UUID.randomUUID().toString();
+ logger.info(EELFLoggerDelegate.applicationLogger,"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) {
+ Map<String, Object> resultMap = new HashMap<>();
+ if (ns == null || userId == null || password == null) {
+ logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
+ logger.error(EELFLoggerDelegate.errorLogger,"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 = ? allow filtering");
+ try {
+ queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), ns));
+ } catch(Exception e) {
+ resultMap.put("Exception",
+ "Unable to process input data. Invalid input data type. Please check ns, userId and password values. "+e.getMessage());
+ return resultMap;
+ }
+ Row rs = null;
+ try {
+ rs = MusicCore.get(queryObject).one();
+ } catch (MusicServiceException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ resultMap.put("Exception", "Unable to process operation. Error is "+e.getMessage());
+ return resultMap;
+ } catch (InvalidQueryException e) {
+ logger.error(EELFLoggerDelegate.errorLogger,"Exception admin keyspace not configured."+e.getMessage());
+ resultMap.put("Exception", "Please make sure admin.keyspace_master table is configured.");
+ return resultMap;
+ }
+ if (rs == null) {
+ logger.error(EELFLoggerDelegate.errorLogger,"Application is not onboarded. Please contact admin.");
+ resultMap.put("Exception", "Application is not onboarded. Please contact admin.");
+ } else {
+ if(!(rs.getString("username").equals(userId)) || !(BCrypt.checkpw(password, rs.getString("password")))) {
+ logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.AUTHENTICATIONERROR, ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
+ logger.error(EELFLoggerDelegate.errorLogger,"Namespace, UserId and password doesn't match. namespace: "+ns+" and userId: "+userId);
+ resultMap.put("Exception", "Namespace, UserId and password doesn't match. namespace: "+ns+" and userId: "+userId);
+ return resultMap;
+ }
+ }
+ return resultMap;
+ }
+
+ public static Map<String, Object> authenticateAIDUser(String nameSpace, String userId, String password,
+ String keyspace) {
+ Map<String, Object> resultMap = new HashMap<>();
+ String pwd = null;
+ if((musicCache.get(keyspace) != null) && (musicValidateCache.get(nameSpace) != null)
+ && (musicValidateCache.get(nameSpace).containsKey(userId))) {
+ if(!musicCache.get(keyspace).equals(nameSpace)) {
+ resultMap.put("Exception", "Namespace and keyspace doesn't match");
+ return resultMap;
+ }
+ if(!BCrypt.checkpw(password,musicValidateCache.get(nameSpace).get(userId))) {
+ resultMap.put("Exception", "Namespace, userId and password doesn't match");
+ return resultMap;
+ }
+ return resultMap;
+ }
+ PreparedQueryObject queryObject = new PreparedQueryObject();
+ queryObject.appendQueryString(
+ "select * from admin.keyspace_master where keyspace_name = ? allow filtering");
+ try {
+ queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), keyspace));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ Row rs = null;
+ try {
+ rs = MusicCore.get(queryObject).one();
+ } catch (MusicServiceException e) {
+ e.printStackTrace();
+ resultMap.put("Exception", "Unable to process operation. Error is "+e.getMessage());
+ return resultMap;
+ }
+ if(rs == null) {
+ resultMap.put("Exception", "Please make sure keyspace:"+keyspace+" exists.");
+ return resultMap;
+ }
+ else {
+ String user = rs.getString("username");
+ pwd = rs.getString("password");
+ String ns = rs.getString("application_name");
+ if(!ns.equals(nameSpace)) {
+ resultMap.put("Exception", "Namespace and keyspace doesn't match");
+ return resultMap;
+ }
+ if(!user.equals(userId)) {
+ resultMap.put("Exception", "Invalid userId :"+userId);
+ return resultMap;
+ }
+ if(!BCrypt.checkpw(password, pwd)) {
+ resultMap.put("Exception", "Invalid password");
+ return resultMap;
+ }
+ }
+ CachingUtil.updateMusicCache(keyspace, nameSpace);
+ CachingUtil.updateMusicValidateCache(nameSpace, userId, pwd);
+ return resultMap;
+ }
+}
diff --git a/jar/src/main/java/org/onap/music/main/CronJobManager.java b/jar/src/main/java/org/onap/music/main/CronJobManager.java
new file mode 100644
index 00000000..fb4a2ac3
--- /dev/null
+++ b/jar/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/jar/src/main/java/org/onap/music/main/MusicCore.java b/jar/src/main/java/org/onap/music/main/MusicCore.java
new file mode 100644
index 00000000..cad384a3
--- /dev/null
+++ b/jar/src/main/java/org/onap/music/main/MusicCore.java
@@ -0,0 +1,992 @@
+/*
+ * ============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.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.KeeperException.NoNodeException;
+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.eelf.logging.format.AppMessages;
+import org.onap.music.eelf.logging.format.ErrorSeverity;
+import org.onap.music.eelf.logging.format.ErrorTypes;
+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.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 EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicCore.class);
+
+ public static class Condition {
+ Map<String, Object> conditions;
+ PreparedQueryObject selectQueryForTheRow;
+
+ public Condition(Map<String, Object> conditions, PreparedQueryObject selectQueryForTheRow) {
+ this.conditions = conditions;
+ this.selectQueryForTheRow = selectQueryForTheRow;
+ }
+
+ public boolean testCondition() throws Exception {
+ // first generate the row
+ ResultSet results = quorumGet(selectQueryForTheRow);
+ Row row = results.one();
+ return getDSHandle().doesRowSatisfyCondition(row, conditions);
+ }
+ }
+
+
+ public static MusicLockingService getLockingServiceHandle() throws MusicLockingException {
+ logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring lock store handle");
+ long start = System.currentTimeMillis();
+
+ if (mLockHandle == null) {
+ try {
+ mLockHandle = new MusicLockingService();
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKHANDLE,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
+ throw new MusicLockingException("Failed to aquire Locl store handle " + e);
+ }
+ }
+ long end = System.currentTimeMillis();
+ logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire lock store handle:" + (end - start) + " ms");
+ return mLockHandle;
+ }
+
+ /**
+ *
+ * @param remoteIp
+ * @return
+ */
+ public static MusicDataStore getDSHandle(String remoteIp) {
+ logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring data store handle");
+ long start = System.currentTimeMillis();
+ if (mDstoreHandle == null) {
+ try {
+ MusicUtil.loadProperties();
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "No properties file defined. Falling back to default.");
+ }
+ mDstoreHandle = new MusicDataStore(remoteIp);
+ }
+ long end = System.currentTimeMillis();
+ logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire data store handle:" + (end - start) + " ms");
+ return mDstoreHandle;
+ }
+
+ /**
+ *
+ * @return
+ * @throws MusicServiceException
+ */
+ public static MusicDataStore getDSHandle() throws MusicServiceException {
+ logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring data store handle");
+ long start = System.currentTimeMillis();
+ if (mDstoreHandle == null) {
+ try {
+ MusicUtil.loadProperties();
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "No properties file defined. Falling back to default.");
+ }
+ // Quick Fix - Best to put this into every call to getDSHandle?
+ if (! MusicUtil.getMyCassaHost().equals("localhost") ) {
+ mDstoreHandle = new MusicDataStore(MusicUtil.getMyCassaHost());
+ } else {
+ mDstoreHandle = new MusicDataStore();
+ }
+ }
+ if(mDstoreHandle.getSession() == null) {
+ String message = "Connection to Cassandra has not been enstablished."
+ + " Please check connection properites and reboot.";
+ logger.info(EELFLoggerDelegate.applicationLogger, message);
+ throw new MusicServiceException(message);
+ }
+ long end = System.currentTimeMillis();
+ logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire data store handle:" + (end - start) + " ms");
+ return mDstoreHandle;
+ }
+
+ public static String createLockReference(String lockName) {
+ logger.info(EELFLoggerDelegate.applicationLogger,"Creating lock reference for lock name:" + lockName);
+ long start = System.currentTimeMillis();
+ String lockId = null;
+ try {
+ lockId = getLockingServiceHandle().createLockId("/" + lockName);
+ } catch (MusicLockingException e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.CREATELOCK+lockName,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
+
+ }
+ long end = System.currentTimeMillis();
+ logger.info(EELFLoggerDelegate.applicationLogger,"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(EELFLoggerDelegate.applicationLogger,"Time taken to get lock state:" + (end - start) + " ms");
+ return mls;
+ } catch (NullPointerException | MusicLockingException e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
+ }
+ 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(EELFLoggerDelegate.applicationLogger,"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(EELFLoggerDelegate.applicationLogger,"Lock period " + currentLockPeriod
+ + " has exceeded lease period " + currentLeasePeriod);
+ boolean voluntaryRelease = false;
+ String currentLockHolder = mls.getLockHolder();
+ mls = releaseLock(currentLockHolder, voluntaryRelease);
+ }
+ }
+ } else
+ logger.error(EELFLoggerDelegate.errorLogger,key, AppMessages.INVALIDLOCK,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
+
+ /*
+ * 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).getResult() == ResultType.SUCCESS) {
+ mls = getMusicLockState(key);// get latest state
+ if ( mls == null ) {
+ logger.info(EELFLoggerDelegate.applicationLogger,"Music Lock State is null");
+ return new ReturnType(ResultType.FAILURE, "Could not acquire lock, Lock State is null");
+ }
+ 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(EELFLoggerDelegate.applicationLogger,"Time taken to acquire leased lock:" + (end - start) + " ms");
+ return new ReturnType(ResultType.SUCCESS, "Accquired lock");
+ } else {
+ long end = System.currentTimeMillis();
+ logger.info(EELFLoggerDelegate.applicationLogger,"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(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR506E] Failed to aquire lock ",ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
+
+ String exceptionAsString = sw.toString();
+ return new ReturnType(ResultType.FAILURE,
+ "Exception thrown in acquireLockWithLease:\n" + exceptionAsString);
+ }
+ }
+
+ public static ReturnType acquireLock(String key, String lockId) throws MusicLockingException {
+ /*
+ * 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(EELFLoggerDelegate.errorLogger,AppMessages.INVALIDLOCK + lockId + " " + e2);
+ throw new MusicLockingException();
+ }
+ if (!result) {
+ logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Not your turn, someone else has the lock");
+ try {
+ if (!getLockingServiceHandle().lockIdExists(lockId)) {
+ logger.info(EELFLoggerDelegate.applicationLogger, "In acquire lock: this lockId doesn't exist");
+ return new ReturnType(ResultType.FAILURE, "Lockid doesn't exist");
+ }
+ } catch (MusicLockingException e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK+lockId,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
+ throw new MusicLockingException();
+ }
+ logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: returning failure");
+ return new ReturnType(ResultType.FAILURE, "Not your turn, someone else has the lock");
+ }
+
+
+ // this is for backward compatibility where locks could also be acquired on just
+ // keyspaces or tables.
+ if (isTableOrKeySpaceLock(key)) {
+ logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: A table or keyspace lock so no need to perform sync...so returning true");
+ return new ReturnType(ResultType.SUCCESS, "A table or keyspace lock so no need to perform sync...so returning 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(EELFLoggerDelegate.applicationLogger,"In acquire lock: You already have the lock!");
+ return new ReturnType(ResultType.SUCCESS, "You already have the lock!");
+ }
+ } catch (NullPointerException e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK+lockId,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
+ }
+
+ // 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(EELFLoggerDelegate.errorLogger,e1.getMessage(), AppMessages.LOCKSTATE+key,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
+ }
+ logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Set lock state to being_locked");
+
+ // do syncing if this was a forced lock release
+ if (needToSyncQuorum) {
+ logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Since there was a forcible release, need to sync quorum!");
+ try {
+ syncQuorum(key);
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger,"Failed to set Lock state " + e);
+ }
+ }
+
+ // 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(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKSTATE+key,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
+ }
+ logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Set lock state to locked and assigned current lock ref "
+ + lockId + " as holder");
+
+ return new ReturnType(result?ResultType.SUCCESS:ResultType.FAILURE, "Set lock state to locked and assigned a lock holder");
+ }
+
+
+
+ /**
+ *
+ * @param keyspaceName
+ * @param kspObject
+ * @return
+ * @throws Exception
+ */
+ public boolean createKeyspace(String keyspaceName, JsonKeySpace kspObject) throws Exception {
+ return true;
+ }
+
+
+ private static void syncQuorum(String key) throws Exception {
+ logger.info(EELFLoggerDelegate.applicationLogger,"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();
+ Object cqlFormattedPrimaryKeyValue =
+ MusicUtil.convertToActualDataType(primaryKeyType, primaryKeyValue);
+
+ // get the row of data from a quorum
+ selectQuery.appendQueryString("SELECT * FROM " + keyspaceName + "." + tableName + " WHERE "
+ + primaryKeyName + "= ?" + ";");
+ selectQuery.addValue(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;
+ 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);
+ Object valueString = MusicUtil.convertToActualDataType(colType, valueObj);
+ 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);
+
+ getDSHandle().executePut(updateQuery, "critical");
+ } catch (MusicServiceException | MusicQueryException e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.QUERYERROR +""+updateQuery ,ErrorSeverity.MAJOR, ErrorTypes.QUERYERROR);
+ }
+ }
+
+
+
+
+ /**
+ *
+ * @param query
+ * @return ResultSet
+ */
+ public static ResultSet quorumGet(PreparedQueryObject query) {
+ ResultSet results = null;
+ try {
+ results = getDSHandle().executeCriticalGet(query);
+ } catch (MusicServiceException | MusicQueryException e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.MAJOR, ErrorTypes.GENERALSERVICEERROR);
+
+ }
+ return results;
+
+ }
+
+ /**
+ *
+ * @param results
+ * @return
+ * @throws MusicServiceException
+ */
+ public static Map<String, HashMap<String, Object>> marshallResults(ResultSet results) throws MusicServiceException {
+ return getDSHandle().marshalData(results);
+ }
+
+ /**
+ *
+ * @param lockName
+ * @return
+ */
+ public static String whoseTurnIsIt(String lockName) {
+
+ try {
+ return getLockingServiceHandle().whoseTurnIsIt("/" + lockName) + "";
+ } catch (MusicLockingException e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKINGERROR+lockName ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
+ }
+ 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 | NoNodeException e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.DESTROYLOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
+ }
+ long end = System.currentTimeMillis();
+ logger.info(EELFLoggerDelegate.applicationLogger,"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(EELFLoggerDelegate.errorLogger,e1.getMessage(), AppMessages.RELEASELOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
+ } catch (KeeperException.NoNodeException nne) {
+ logger.error(EELFLoggerDelegate.errorLogger,"Failed to release Lock " + lockId + " " + nne);
+ MusicLockState mls = new MusicLockState("Lock doesn't exists. Release lock operation failed.");
+ return mls;
+ }
+ String lockName = getLockNameFromId(lockId);
+ MusicLockState mls;
+ String lockHolder = null;
+ if (voluntaryRelease) {
+ mls = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder);
+ logger.info(EELFLoggerDelegate.applicationLogger,"In unlock: lock voluntarily released for " + lockId);
+ } else {
+ boolean needToSyncQuorum = true;
+ mls = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder,
+ needToSyncQuorum);
+ logger.info(EELFLoggerDelegate.applicationLogger,"In unlock: lock forcibly released for " + lockId);
+ }
+ try {
+ getLockingServiceHandle().setLockState(lockName, mls);
+ } catch (MusicLockingException e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.RELEASELOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
+ }
+ long end = System.currentTimeMillis();
+ logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to release lock:" + (end - start) + " ms");
+ return mls;
+ }
+
+ public static void voluntaryReleaseLock(String lockId) throws MusicLockingException{
+ try {
+ getLockingServiceHandle().unlockAndDeleteId(lockId);
+ } catch (KeeperException.NoNodeException e) {
+ // ??? No way
+ }
+ }
+
+ /**
+ *
+ * @param lockName
+ * @throws MusicLockingException
+ */
+ public static void deleteLock(String lockName) throws MusicLockingException {
+ long start = System.currentTimeMillis();
+ logger.info(EELFLoggerDelegate.applicationLogger,"Deleting lock for " + lockName);
+ try {
+ getLockingServiceHandle().deleteLock("/" + lockName);
+ } catch (MusicLockingException e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.DELTELOCK+lockName ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
+ throw new MusicLockingException(e.getMessage());
+ }
+ long end = System.currentTimeMillis();
+ logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to delete lock:" + (end - start) + " ms");
+ }
+
+
+
+ /**
+ *
+ * @param keyspace
+ * @param tablename
+ * @return
+ * @throws MusicServiceException
+ */
+ public static TableMetadata returnColumnMetadata(String keyspace, String tablename) throws MusicServiceException {
+ return getDSHandle().returnColumnMetadata(keyspace, tablename);
+ }
+
+
+ /**
+ *
+ * @param nodeName
+ */
+ public static void pureZkCreate(String nodeName) {
+ try {
+ getLockingServiceHandle().getzkLockHandle().createNode(nodeName);
+ } catch (MusicLockingException e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
+ }
+ }
+
+ /**
+ *
+ * @param nodeName
+ * @param data
+ */
+ public static void pureZkWrite(String nodeName, byte[] data) {
+ long start = System.currentTimeMillis();
+ logger.info(EELFLoggerDelegate.applicationLogger,"Performing zookeeper write to " + nodeName);
+ try {
+ getLockingServiceHandle().getzkLockHandle().setNodeData(nodeName, data);
+ } catch (MusicLockingException e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
+ }
+ logger.info(EELFLoggerDelegate.applicationLogger,"Performed zookeeper write to " + nodeName);
+ long end = System.currentTimeMillis();
+ logger.info(EELFLoggerDelegate.applicationLogger,"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(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
+ }
+ long end = System.currentTimeMillis();
+ logger.info(EELFLoggerDelegate.applicationLogger,"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(EELFLoggerDelegate.errorLogger,ex.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
+ logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() + " " + ex.getCause() + " " + ex);
+ return new ReturnType(ResultType.FAILURE, ex.getMessage());
+ }
+ 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)
+ try {
+ if (conditionInfo.testCondition() == false)
+ return new ReturnType(ResultType.FAILURE,
+ "Lock acquired but the condition is not true");
+ } catch (Exception e) {
+ return new ReturnType(ResultType.FAILURE,
+ "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n"
+ + e.getMessage());
+ }
+ getDSHandle().executePut(queryObject, MusicUtil.CRITICAL);
+ long end = System.currentTimeMillis();
+ logger.info(EELFLoggerDelegate.applicationLogger,"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 e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
+ return new ReturnType(ResultType.FAILURE,
+ "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n"
+ + e.getMessage());
+ }catch(MusicLockingException ex){
+ return new ReturnType(ResultType.FAILURE,ex.getMessage());
+ }
+
+ }
+
+ /**
+ *
+ * @param queryObject
+ * @param consistency
+ * @return Boolean Indicates success or failure
+ * @throws MusicServiceException
+ *
+ *
+ */
+ public static ResultType nonKeyRelatedPut(PreparedQueryObject queryObject, String consistency) throws MusicServiceException {
+ // 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(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
+ throw new MusicServiceException(ex.getMessage());
+ }
+ return result?ResultType.SUCCESS:ResultType.FAILURE;
+ }
+
+ /**
+ * This method performs DDL operation on cassandra.
+ *
+ * @param queryObject query object containing prepared query and values
+ * @return ResultSet
+ * @throws MusicServiceException
+ */
+ public static ResultSet get(PreparedQueryObject queryObject) throws MusicServiceException {
+ ResultSet results = null;
+ try {
+ results = getDSHandle().executeEventualGet(queryObject);
+ } catch (MusicQueryException | MusicServiceException e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e.getMessage());
+ throw new MusicServiceException(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(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
+ }
+ 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
+ * @throws MusicLockingException
+ */
+ public static ReturnType atomicPut(String keyspaceName, String tableName, String primaryKey,
+ PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException {
+
+ long start = System.currentTimeMillis();
+ String key = keyspaceName + "." + tableName + "." + primaryKey;
+ String lockId = createLockReference(key);
+ long lockCreationTime = System.currentTimeMillis();
+ ReturnType lockAcqResult = acquireLock(key, lockId);
+ long lockAcqTime = System.currentTimeMillis();
+ if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
+ logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
+ ReturnType criticalPutResult = criticalPut(keyspaceName, tableName, primaryKey,
+ queryObject, lockId, conditionInfo);
+ long criticalPutTime = System.currentTimeMillis();
+ voluntaryReleaseLock(lockId);
+ 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(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
+ destroyLockRef(lockId);
+ return lockAcqResult;
+ }
+ }
+
+ /**
+ * 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
+ * @throws MusicLockingException
+ */
+ public static ReturnType atomicPutWithDeleteLock(String keyspaceName, String tableName,
+ String primaryKey, PreparedQueryObject queryObject, Condition conditionInfo) throws MusicLockingException {
+
+ long start = System.currentTimeMillis();
+ String key = keyspaceName + "." + tableName + "." + primaryKey;
+ String lockId = createLockReference(key);
+ long lockCreationTime = System.currentTimeMillis();
+ long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
+ ReturnType lockAcqResult = acquireLock(key, lockId);
+ long lockAcqTime = System.currentTimeMillis();
+ if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
+ logger.info(EELFLoggerDelegate.applicationLogger,"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(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
+ deleteLock(key);
+ 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
+ * @throws MusicLockingException
+ */
+ public static ResultSet atomicGet(String keyspaceName, String tableName, String primaryKey,
+ PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException {
+ String key = keyspaceName + "." + tableName + "." + primaryKey;
+ String lockId = createLockReference(key);
+ long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
+ ReturnType lockAcqResult = acquireLock(key, lockId);
+ if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
+ logger.info(EELFLoggerDelegate.applicationLogger,"acquired lock with id " + lockId);
+ ResultSet result =
+ criticalGet(keyspaceName, tableName, primaryKey, queryObject, lockId);
+ voluntaryReleaseLock(lockId);
+ return result;
+ } else {
+ destroyLockRef(lockId);
+ logger.info(EELFLoggerDelegate.applicationLogger,"unable to acquire lock, id " + lockId);
+ return null;
+ }
+ }
+
+ public static ResultSet atomicGetWithDeleteLock(String keyspaceName, String tableName, String primaryKey,
+ PreparedQueryObject queryObject) throws MusicServiceException, MusicLockingException {
+ String key = keyspaceName + "." + tableName + "." + primaryKey;
+ String lockId = createLockReference(key);
+ long leasePeriod = MusicUtil.getDefaultLockLeasePeriod();
+
+ ReturnType lockAcqResult = acquireLock(key, lockId);
+
+ if (lockAcqResult.getResult().equals(ResultType.SUCCESS)) {
+ logger.info(EELFLoggerDelegate.applicationLogger, "acquired lock with id " + lockId);
+ ResultSet result = criticalGet(keyspaceName, tableName, primaryKey, queryObject, lockId);
+ deleteLock(key);
+ return result;
+ } else {
+ deleteLock(key);
+ logger.info(EELFLoggerDelegate.applicationLogger, "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;
+ String isAAFApp = null;
+ try {
+ isAAFApp= CachingUtil.isAAFApplication(nameSpace);
+ } catch(MusicServiceException e) {
+ resultMap.put("Exception", e.getMessage());
+ return resultMap;
+ }
+ if(isAAFApp == null) {
+ resultMap.put("Exception", "Namespace: "+nameSpace+" doesn't exist. Please make sure ns(appName)"
+ + " is correct and Application is onboarded.");
+ return resultMap;
+ }
+ boolean isAAF = Boolean.valueOf(isAAFApp);
+ if (userId == null || password == null) {
+ logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
+ logger.error(EELFLoggerDelegate.errorLogger,"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;
+ }
+ if(!isAAF && !(operation.equals("createKeySpace"))) {
+ resultMap = CachingUtil.authenticateAIDUser(nameSpace, userId, password, 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(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
+ logger.error(EELFLoggerDelegate.errorLogger,"Got exception while AAF authentication for namespace " + nameSpace);
+ resultMap.put("Exception", e.getMessage());
+ }
+ if (!isValid) {
+ logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
+ resultMap.put("Exception", "User not authenticated...");
+ }
+ if (!resultMap.isEmpty())
+ return resultMap;
+
+ }
+
+ if (operation.equals("createKeySpace")) {
+ logger.info(EELFLoggerDelegate.applicationLogger,"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(EELFLoggerDelegate.applicationLogger,"No UUID found in DB. So creating new UUID.");
+ uuid = CachingUtil.generateUUID();
+ resultMap.put("uuid", "new");
+ }
+ resultMap.put("aid", uuid);
+ }
+
+ return resultMap;
+ }
+
+ /**
+ * @param lockName
+ * @return
+ */
+ public static Map<String, Object> validateLock(String lockName) {
+ Map<String, Object> resultMap = new HashMap<>();
+ String[] locks = lockName.split("\\.");
+ if(locks.length < 3) {
+ resultMap.put("Exception", "Invalid lock. Please make sure lock is of the type keyspaceName.tableName.primaryKey");
+ return resultMap;
+ }
+ String keyspace= locks[0];
+ if(keyspace.startsWith("$"))
+ keyspace = keyspace.substring(1);
+ resultMap.put("keyspace",keyspace);
+ return resultMap;
+ }
+}
diff --git a/jar/src/main/java/org/onap/music/main/MusicDigest.java b/jar/src/main/java/org/onap/music/main/MusicDigest.java
new file mode 100644
index 00000000..893cb51f
--- /dev/null
+++ b/jar/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/jar/src/main/java/org/onap/music/main/MusicUtil.java b/jar/src/main/java/org/onap/music/main/MusicUtil.java
new file mode 100755
index 00000000..fe799c4b
--- /dev/null
+++ b/jar/src/main/java/org/onap/music/main/MusicUtil.java
@@ -0,0 +1,560 @@
+/*
+ * ============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 javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+import org.onap.music.datastore.PreparedQueryObject;
+import org.onap.music.eelf.logging.EELFLoggerDelegate;
+import com.datastax.driver.core.DataType;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+
+/**
+ * @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);
+
+ public static final String ATOMIC = "atomic";
+ public static final String EVENTUAL = "eventual";
+ public static final String CRITICAL = "critical";
+ public static final String ATOMICDELETELOCK = "atomic_delete_lock";
+ public static final String DEFAULTKEYSPACENAME = "TBD";
+ private static final String XLATESTVERSION = "X-latestVersion";
+ private static final String XMINORVERSION = "X-minorVersion";
+ private static final String XPATCHVERSION = "X-patchVersion";
+
+ private static final String LOCALHOST = "localhost";
+ private static final String PROPERTIES_FILE = "/opt/app/music/etc/music.properties";
+
+ private static int myId = 0;
+ private static ArrayList<String> allIds = new ArrayList<>();
+ private static String publicIp = "";
+ private static ArrayList<String> allPublicIps = new ArrayList<>();
+ 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";
+ private static String musicRestIp = LOCALHOST;
+ private static String musicPropertiesFilePath = PROPERTIES_FILE;
+ 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" };
+
+ private static String cassName = "cassandra";
+ private static String cassPwd = "cassandra";
+ private static String aafEndpointUrl = null;
+
+ private MusicUtil() {
+ throw new IllegalStateException("Utility Class");
+ }
+
+
+ /**
+ * @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 List<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 List<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());
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ /**
+ * 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) throws Exception {
+
+ 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 MusicTypeConversionException
+ * @throws Exception
+ */
+ public static Object convertToActualDataType(DataType colType, Object valueObj) throws Exception {
+ 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) throws Exception{
+ 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();
+ }
+
+ @SuppressWarnings("unused")
+ public static String buildVersion(String major, String minor, String patch) {
+ if (minor != null) {
+ major += "." + minor;
+ if (patch != null) {
+ major += "." + patch;
+ }
+ }
+ return major;
+ }
+
+ /**
+ * Currently this will build a header with X-latestVersion, X-minorVersion and X-pathcVersion
+ * X-latestVerstion will be equal to the latest full version.
+ * X-minorVersion - will be equal to the latest minor version.
+ * X-pathVersion - will be equal to the latest patch version.
+ * Future plans will change this.
+ * @param response
+ * @param major
+ * @param minor
+ * @param patch
+ * @return
+ */
+ public static ResponseBuilder buildVersionResponse(String major, String minor, String patch) {
+ ResponseBuilder response = Response.noContent();
+ String versionIn = buildVersion(major,minor,patch);
+ String version = MusicUtil.getVersion();
+ String[] verArray = version.split("\\.",3);
+ if ( minor != null ) {
+ response.header(XMINORVERSION,minor);
+ } else {
+ response.header(XMINORVERSION,verArray[1]);
+ }
+ if ( patch != null ) {
+ response.header(XPATCHVERSION,patch);
+ } else {
+ response.header(XPATCHVERSION,verArray[2]);
+ }
+ response.header(XLATESTVERSION,version);
+ logger.info(EELFLoggerDelegate.applicationLogger,"Version In:" + versionIn);
+ return response;
+ }
+
+
+ public static void loadProperties() throws Exception {
+ Properties prop = new Properties();
+ InputStream input = null;
+ try {
+ // load the properties file
+ input = MusicUtil.class.getClassLoader().getResourceAsStream("music.properties");
+ prop.load(input);
+ } catch (Exception ex) {
+ logger.error(EELFLoggerDelegate.errorLogger, "Unable to find properties file.");
+ throw new Exception();
+ } finally {
+ if (input != null) {
+ try {
+ input.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ // get the property value and return it
+ MusicUtil.setMyCassaHost(prop.getProperty("cassandra.host"));
+ String[] zkHost = prop.getProperty("zookeeper.host").split(",");
+ MusicUtil.setMyZkHost(zkHost[0]);
+ MusicUtil.setCassName(prop.getProperty("cassandra.user"));
+ MusicUtil.setCassPwd(prop.getProperty("cassandra.password"));
+ }
+
+}
diff --git a/jar/src/main/java/org/onap/music/main/PropertiesListener.java b/jar/src/main/java/org/onap/music/main/PropertiesListener.java
new file mode 100755
index 00000000..afd35387
--- /dev/null
+++ b/jar/src/main/java/org/onap/music/main/PropertiesListener.java
@@ -0,0 +1,151 @@
+/*
+ * ============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;
+import org.onap.music.eelf.logging.format.AppMessages;
+import org.onap.music.eelf.logging.format.ErrorSeverity;
+import org.onap.music.eelf.logging.format.ErrorTypes;
+
+@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(), AppMessages.IOERROR ,ErrorSeverity.CRITICAL, ErrorTypes.CONNECTIONERROR);
+ 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/jar/src/main/java/org/onap/music/main/ResultType.java b/jar/src/main/java/org/onap/music/main/ResultType.java
new file mode 100644
index 00000000..61ba0295
--- /dev/null
+++ b/jar/src/main/java/org/onap/music/main/ResultType.java
@@ -0,0 +1,41 @@
+/*
+ * ============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"),
+ SYNTAXERROR("SyntaxError"), EXCEPTION("Exception"),
+ BODYMISSING("Incomplete Request body. Please correct your input request and retry.");
+
+ private String result;
+
+ ResultType(String result) {
+ this.result = result;
+ }
+
+ public String getResult() {
+ return result;
+ }
+
+}
+
+
diff --git a/jar/src/main/java/org/onap/music/main/ReturnType.java b/jar/src/main/java/org/onap/music/main/ReturnType.java
new file mode 100644
index 00000000..1453a1bf
--- /dev/null
+++ b/jar/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;
+ }
+
+}