2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright (c) 2017 AT&T Intellectual Property
6 * ===================================================================
7 * Modifications Copyright (c) 2018 IBM.
8 * ===================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
21 * ============LICENSE_END=============================================
22 * ====================================================================
25 package org.onap.music.main;
28 import java.io.FileNotFoundException;
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.math.BigInteger;
32 import java.nio.ByteBuffer;
33 import java.util.ArrayList;
34 import java.util.HashMap;
35 import java.util.List;
37 import java.util.Properties;
38 import java.util.Scanner;
39 import java.util.StringTokenizer;
40 import java.util.UUID;
41 import java.util.concurrent.ConcurrentHashMap;
42 import java.util.concurrent.ConcurrentMap;
44 import javax.ws.rs.core.Response;
45 import javax.ws.rs.core.Response.ResponseBuilder;
47 import org.onap.music.datastore.PreparedQueryObject;
48 import org.onap.music.eelf.logging.EELFLoggerDelegate;
49 import org.onap.music.exceptions.MusicQueryException;
50 import org.onap.music.exceptions.MusicServiceException;
51 import org.onap.music.service.MusicCoreService;
52 import org.onap.music.service.impl.MusicCassaCore;
53 import org.onap.music.service.impl.MusicZKCore;
55 import com.datastax.driver.core.ConsistencyLevel;
56 import com.datastax.driver.core.DataType;
57 import com.sun.jersey.core.util.Base64;
62 * Properties This will take Properties and load them into MusicUtil.
63 * This is a hack for now. Eventually it would bebest to do this in
67 public class MusicUtil {
68 private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicUtil.class);
70 public static final String ATOMIC = "atomic";
71 public static final String EVENTUAL = "eventual";
72 public static final String CRITICAL = "critical";
73 public static final String EVENTUAL_NB = "eventual_nb";
74 public static final String ALL = "all";
75 public static final String QUORUM = "quorum";
76 public static final String ONE = "one";
77 public static final String ATOMICDELETELOCK = "atomic_delete_lock";
78 public static final String DEFAULTKEYSPACENAME = "TBD";
79 private static final String XLATESTVERSION = "X-latestVersion";
80 private static final String XMINORVERSION = "X-minorVersion";
81 private static final String XPATCHVERSION = "X-patchVersion";
82 public static final String SELECT = "select";
83 public static final String INSERT = "insert";
84 public static final String UPDATE = "update";
85 public static final String UPSERT = "upsert";
86 public static final String USERID = "userId";
87 public static final String PASSWORD = "password";
88 public static final String CASSANDRA = "cassandra";
89 public static final String ZOOKEEPER = "zookeeper";
91 public static final String AUTHORIZATION = "Authorization";
93 private static final String LOCALHOST = "localhost";
94 private static final String PROPERTIES_FILE = "/opt/app/music/etc/music.properties";
96 private static int myId = 0;
97 private static ArrayList<String> allIds = new ArrayList<>();
98 private static String publicIp = "";
99 private static ArrayList<String> allPublicIps = new ArrayList<>();
100 private static String myZkHost = LOCALHOST;
101 private static String myCassaHost = LOCALHOST;
102 private static String defaultMusicIp = LOCALHOST;
103 private static int cassandraPort = 9042;
104 private static int notifytimeout = 30000;
105 private static int notifyinterval = 5000;
106 private static int cacheObjectMaxLife = -1;
107 private static String lockUsing = MusicUtil.CASSANDRA;
108 private static boolean isCadi = false;
110 private static boolean debug = true;
111 private static String version = "2.3.0";
112 private static String musicRestIp = LOCALHOST;
113 private static String musicPropertiesFilePath = PROPERTIES_FILE;
114 private static long defaultLockLeasePeriod = 6000;
115 private static final String[] propKeys = new String[] { "zookeeper.host", "cassandra.host", "music.ip", "debug",
116 "version", "music.rest.ip", "music.properties", "lock.lease.period", "id", "all.ids", "public.ip",
117 "all.pubic.ips", "cassandra.user", "cassandra.password", "aaf.endpoint.url","admin.username","admin.password","aaf.admin.url",
118 "music.namespace","admin.aaf.role","cassandra.port","lock.using"};
119 private static final String[] cosistencyLevel = new String[] {
120 "ALL","EACH_QUORUM","QUORUM","LOCAL_QUORUM","ONE","TWO","THREE","LOCAL_ONE","ANY","SERIAL","LOCAL_SERIAL"};
121 private static final Map<String,ConsistencyLevel> consistencyName = new HashMap<>();
123 consistencyName.put("ONE",ConsistencyLevel.ONE);
124 consistencyName.put("TWO",ConsistencyLevel.TWO);
125 consistencyName.put("THREE",ConsistencyLevel.THREE);
126 consistencyName.put("SERIAL",ConsistencyLevel.SERIAL);
127 consistencyName.put("ALL",ConsistencyLevel.ALL);
128 consistencyName.put("EACH_QUORUM",ConsistencyLevel.EACH_QUORUM);
129 consistencyName.put("QUORUM",ConsistencyLevel.QUORUM);
130 consistencyName.put("LOCAL_QUORUM",ConsistencyLevel.LOCAL_QUORUM);
131 consistencyName.put("LOCAL_ONE",ConsistencyLevel.LOCAL_ONE);
132 consistencyName.put("LOCAL_SERIAL",ConsistencyLevel.LOCAL_SERIAL);
135 private static String cassName = "cassandra";
136 private static String cassPwd;
137 private static String aafEndpointUrl = null;
138 public static ConcurrentMap<String, Long> zkNodeMap = new ConcurrentHashMap<>();
139 private static String adminId = "username";
140 private static String adminPass= "password";
141 private static String aafAdminUrl= null;
142 private static String musicNamespace= "com.att.music.api";
143 private static String adminAafRole= "com.att.music.api.admin_api";
145 public static final long MusicEternityEpochMillis = 1533081600000L; // Wednesday, August 1, 2018 12:00:00 AM
147 public static final long MaxLockReferenceTimePart = 1000000000000L; // millis after eternity (eq sometime in 2050)
149 public static final long MaxCriticalSectionDurationMillis = 1L * 24 * 60 * 60 * 1000; // 1 day
152 public static String getLockUsing() {
157 public static void setLockUsing(String lockUsing) {
158 MusicUtil.lockUsing = lockUsing;
161 public static String getAafAdminUrl() {
166 public static void setAafAdminUrl(String aafAdminUrl) {
167 MusicUtil.aafAdminUrl = aafAdminUrl;
171 public static String getMusicNamespace() {
172 return musicNamespace;
176 public static void setMusicNamespace(String musicNamespace) {
177 MusicUtil.musicNamespace = musicNamespace;
181 public static String getAdminAafRole() {
186 public static void setAdminAafRole(String adminAafRole) {
187 MusicUtil.adminAafRole = adminAafRole;
192 public static String getAdminId() {
197 public static void setAdminId(String adminId) {
198 MusicUtil.adminId = adminId;
202 public static String getAdminPass() {
206 public static void setAdminPass(String adminPass) {
207 MusicUtil.adminPass = adminPass;
211 private MusicUtil() {
212 throw new IllegalStateException("Utility Class");
216 * @return cassandra port
218 public static int getCassandraPort() {
219 return cassandraPort;
224 * @param cassandraPort
226 public static void setCassandraPort(int cassandraPort) {
227 MusicUtil.cassandraPort = cassandraPort;
230 * @return the cassName
232 public static String getCassName() {
237 * @return the cassPwd
239 public static String getCassPwd() {
244 * @return the aafEndpointUrl
246 public static String getAafEndpointUrl() {
247 return aafEndpointUrl;
252 * @param aafEndpointUrl
254 public static void setAafEndpointUrl(String aafEndpointUrl) {
255 MusicUtil.aafEndpointUrl = aafEndpointUrl;
262 public static int getMyId() {
270 public static void setMyId(int myId) {
271 MusicUtil.myId = myId;
278 public static List<String> getAllIds() {
286 public static void setAllIds(List<String> allIds) {
287 MusicUtil.allIds = (ArrayList<String>) allIds;
294 public static String getPublicIp() {
302 public static void setPublicIp(String publicIp) {
303 MusicUtil.publicIp = publicIp;
310 public static List<String> getAllPublicIps() {
316 * @param allPublicIps
318 public static void setAllPublicIps(List<String> allPublicIps) {
319 MusicUtil.allPublicIps = (ArrayList<String>) allPublicIps;
323 * Returns An array of property names that should be in the Properties
328 public static String[] getPropkeys() {
333 * Get MusicRestIp - default = localhost property file value - music.rest.ip
337 public static String getMusicRestIp() {
346 public static void setMusicRestIp(String musicRestIp) {
347 MusicUtil.musicRestIp = musicRestIp;
351 * Get MusicPropertiesFilePath - Default = /opt/music/music.properties
352 * property file value - music.properties
356 public static String getMusicPropertiesFilePath() {
357 return musicPropertiesFilePath;
361 * Set MusicPropertiesFilePath
363 * @param musicPropertiesFilePath
365 public static void setMusicPropertiesFilePath(String musicPropertiesFilePath) {
366 MusicUtil.musicPropertiesFilePath = musicPropertiesFilePath;
370 * Get DefaultLockLeasePeriod - Default = 6000 property file value -
375 public static long getDefaultLockLeasePeriod() {
376 return defaultLockLeasePeriod;
380 * Set DefaultLockLeasePeriod
382 * @param defaultLockLeasePeriod
384 public static void setDefaultLockLeasePeriod(long defaultLockLeasePeriod) {
385 MusicUtil.defaultLockLeasePeriod = defaultLockLeasePeriod;
393 public static void setDebug(boolean debug) {
394 MusicUtil.debug = debug;
398 * Is Debug - Default = true property file value - debug
402 public static boolean isDebug() {
411 public static void setVersion(String version) {
412 MusicUtil.version = version;
416 * Return the version property file value - version
420 public static String getVersion() {
425 * Get MyZkHost - Zookeeper Hostname - Default = localhost property file
426 * value - zookeeper.host
430 public static String getMyZkHost() {
435 * Set MyZkHost - Zookeeper Hostname
439 public static void setMyZkHost(String myZkHost) {
440 MusicUtil.myZkHost = myZkHost;
444 * Get MyCassHost - Cassandra Hostname - Default = localhost property file
445 * value - cassandra.host
449 public static String getMyCassaHost() {
454 * Set MyCassHost - Cassandra Hostname
458 public static void setMyCassaHost(String myCassaHost) {
459 MusicUtil.myCassaHost = myCassaHost;
463 * Get DefaultMusicIp - Default = localhost property file value - music.ip
467 public static String getDefaultMusicIp() {
468 return defaultMusicIp;
474 * @param defaultMusicIp
476 public static void setDefaultMusicIp(String defaultMusicIp) {
477 MusicUtil.defaultMusicIp = defaultMusicIp;
484 public static String getTestType() {
485 String testType = "";
487 Scanner fileScanner = new Scanner(new File(""));
488 testType = fileScanner.next();// ignore the my id line
489 @SuppressWarnings("unused")
490 String batchSize = fileScanner.next();// ignore the my public ip
493 } catch (FileNotFoundException e) {
494 logger.error(EELFLoggerDelegate.errorLogger, e.getMessage());
504 public static void sleep(long time) {
507 } catch (InterruptedException e) {
508 logger.error(EELFLoggerDelegate.errorLogger, e.getMessage());
509 Thread.currentThread().interrupt();
514 * Utility function to check if the query object is valid.
520 public static boolean isValidQueryObject(boolean withparams, PreparedQueryObject queryObject) {
522 int noOfValues = queryObject.getValues().size();
524 char[] temp = queryObject.getQuery().toCharArray();
525 for (int i = 0; i < temp.length; i++) {
529 return (noOfValues == noOfParams);
531 return !queryObject.getQuery().isEmpty();
536 public static void setCassName(String cassName) {
537 MusicUtil.cassName = cassName;
540 public static void setCassPwd(String cassPwd) {
541 MusicUtil.cassPwd = cassPwd;
544 @SuppressWarnings("unchecked")
545 public static String convertToCQLDataType(DataType type, Object valueObj) throws Exception {
548 switch (type.getName()) {
550 value = valueObj + "";
554 String valueString = valueObj + "";
555 valueString = valueString.replace("'", "''");
556 value = "'" + valueString + "'";
559 Map<String, Object> otMap = (Map<String, Object>) valueObj;
560 value = "{" + jsonMaptoSqlString(otMap, ",") + "}";
564 value = valueObj + "";
575 * @throws MusicTypeConversionException
578 @SuppressWarnings("unchecked")
579 public static Object convertToActualDataType(DataType colType, Object valueObj) throws Exception {
580 String valueObjString = valueObj + "";
581 switch (colType.getName()) {
583 return UUID.fromString(valueObjString);
585 return BigInteger.valueOf(Long.parseLong(valueObjString));
587 return Long.parseLong(valueObjString);
589 return Integer.parseInt(valueObjString);
591 return Float.parseFloat(valueObjString);
593 return Double.parseDouble(valueObjString);
595 return Boolean.parseBoolean(valueObjString);
597 return (Map<String, Object>) valueObj;
599 return (List<Object>)valueObj;
603 return valueObjString;
607 public static ByteBuffer convertToActualDataType(DataType colType, byte[] valueObj) {
608 ByteBuffer buffer = ByteBuffer.wrap(valueObj);
614 * Utility function to parse json map into sql like string
617 * @param lineDelimiter
621 public static String jsonMaptoSqlString(Map<String, Object> jMap, String lineDelimiter) throws Exception{
622 StringBuilder sqlString = new StringBuilder();
624 for (Map.Entry<String, Object> entry : jMap.entrySet()) {
625 Object ot = entry.getValue();
626 String value = ot + "";
627 if (ot instanceof String) {
628 value = "'" + value.replace("'", "''") + "'";
630 sqlString.append("'" + entry.getKey() + "':" + value);
631 if (counter != jMap.size() - 1)
632 sqlString.append(lineDelimiter);
633 counter = counter + 1;
635 return sqlString.toString();
638 @SuppressWarnings("unused")
639 public static String buildVersion(String major, String minor, String patch) {
641 major += "." + minor;
643 major += "." + patch;
650 * Currently this will build a header with X-latestVersion, X-minorVersion and X-pathcVersion
651 * X-latestVerstion will be equal to the latest full version.
652 * X-minorVersion - will be equal to the latest minor version.
653 * X-pathVersion - will be equal to the latest patch version.
654 * Future plans will change this.
661 public static ResponseBuilder buildVersionResponse(String major, String minor, String patch) {
662 ResponseBuilder response = Response.noContent();
663 String versionIn = buildVersion(major,minor,patch);
664 String version = MusicUtil.getVersion();
665 String[] verArray = version.split("\\.",3);
666 if ( minor != null ) {
667 response.header(XMINORVERSION,minor);
669 response.header(XMINORVERSION,verArray[1]);
671 if ( patch != null ) {
672 response.header(XPATCHVERSION,patch);
674 response.header(XPATCHVERSION,verArray[2]);
676 response.header(XLATESTVERSION,version);
677 logger.info(EELFLoggerDelegate.applicationLogger,"Version In:" + versionIn);
682 public static Map<String,String> extractBasicAuthentication(String authorization){
683 Map<String,String> authValues = new HashMap<>();
684 if(authorization == null) {
685 authValues.put("ERROR", "Authorization cannot be null");
688 authorization = authorization.replaceFirst("Basic", "");
689 String decoded = Base64.base64Decode(authorization);
690 StringTokenizer token = new StringTokenizer(decoded, ":");
691 authValues.put(MusicUtil.USERID, token.nextToken());
692 authValues.put(MusicUtil.PASSWORD,token.nextToken());
697 public static boolean isValidConsistency(String consistency) {
698 for (String string : cosistencyLevel) {
699 if (string.equalsIgnoreCase(consistency))
706 public static ConsistencyLevel getConsistencyLevel(String consistency) {
707 return consistencyName.get(consistency.toUpperCase());
710 public static void loadProperties() throws Exception {
711 Properties prop = new Properties();
712 InputStream input = null;
714 // load the properties file
715 input = MusicUtil.class.getClassLoader().getResourceAsStream("music.properties");
717 } catch (Exception ex) {
718 logger.error(EELFLoggerDelegate.errorLogger, "Unable to find properties file.");
719 throw new Exception();
724 } catch (IOException e) {
729 // get the property value and return it
730 MusicUtil.setMyCassaHost(prop.getProperty("cassandra.host"));
731 String zkHosts = prop.getProperty("zookeeper.host");
732 MusicUtil.setMyZkHost(zkHosts);
733 MusicUtil.setCassName(prop.getProperty("cassandra.user"));
734 MusicUtil.setCassPwd(prop.getProperty("cassandra.password"));
735 MusicUtil.setCassandraPort(Integer.parseInt(prop.getProperty("cassandra.port")));
736 MusicUtil.setNotifyTimeOut(Integer.parseInt(prop.getProperty("notify.timeout")));
737 MusicUtil.setNotifyInterval(Integer.parseInt(prop.getProperty("notify.interval")));
738 MusicUtil.setCacheObjectMaxLife(Integer.parseInt(prop.getProperty("cacheobject.maxlife")));
741 public static void setNotifyInterval(int notifyinterval) {
742 MusicUtil.notifyinterval = notifyinterval;
744 public static void setNotifyTimeOut(int notifytimeout) {
745 MusicUtil.notifytimeout = notifytimeout;
748 public static int getNotifyInterval() {
749 return MusicUtil.notifyinterval;
752 public static int getNotifyTimeout() {
753 return MusicUtil.notifytimeout;
756 public static int getCacheObjectMaxLife() {
757 return MusicUtil.cacheObjectMaxLife;
760 public static void setCacheObjectMaxLife(int cacheObjectMaxLife) {
761 MusicUtil.cacheObjectMaxLife = cacheObjectMaxLife;
765 * Given the time of write for an update in a critical section, this method provides a transformed timestamp
766 * that ensures that a previous lock holder who is still alive can never corrupt a later critical section.
767 * The main idea is to us the lock reference to clearly demarcate the timestamps across critical sections.
768 * @param the UUID lock reference associated with the write.
769 * @param the long timeOfWrite which is the actual time at which the write took place
770 * @throws MusicServiceException
771 * @throws MusicQueryException
773 public static long v2sTimeStampInMicroseconds(long ordinal, long timeOfWrite) throws MusicServiceException, MusicQueryException {
774 // TODO: use acquire time instead of music eternity epoch
775 long ts = ordinal * MaxLockReferenceTimePart + (timeOfWrite - MusicEternityEpochMillis);
780 public static MusicCoreService getMusicCoreService() {
781 if(getLockUsing().equals(MusicUtil.CASSANDRA))
782 return MusicCassaCore.getInstance();
783 else if (getLockUsing().equals(MusicUtil.ZOOKEEPER))
784 return MusicZKCore.getInstance();
786 return MusicCassaCore.getInstance();
793 public static Map<String, Object> validateLock(String lockName) {
794 Map<String, Object> resultMap = new HashMap<>();
795 String[] locks = lockName.split("\\.");
796 if(locks.length < 3) {
797 resultMap.put("Error", "Invalid lock. Please make sure lock is of the type keyspaceName.tableName.primaryKey");
800 String keyspace= locks[0];
801 if(keyspace.startsWith("$"))
802 keyspace = keyspace.substring(1);
803 resultMap.put("keyspace",keyspace);
808 public static void setIsCadi(boolean isCadi) {
809 // TODO Auto-generated method stub
810 MusicUtil.isCadi = isCadi;
813 public static boolean getIsCadi() {
814 return MusicUtil.isCadi;