aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/org/onap/music/main/MusicUtil.java
diff options
context:
space:
mode:
authorNelson,Thomas(tn1381)(arthurdent3) <tn1381@att.com>2019-01-29 15:55:37 -0500
committerNelson,Thomas(tn1381)(arthurdent3) <tn1381@att.com>2019-01-29 16:05:01 -0500
commita27be9fdbbf2d271c9c5780ba70fe15a24dbdb63 (patch)
tree1fa631eae149ed6be33b636e7eac03dadbef64c3 /src/main/java/org/onap/music/main/MusicUtil.java
parent95489883ce973e84267fcbcee685f1598d4bdd6e (diff)
Push variuos changes
- Spring Boot - Cadi - Cassandra Locking Change-Id: Ie9882f81f0ca141bdb7862cdabf978481fcd7c4a Issue-ID: MUSIC-296,MUSIC-272 Signed-off-by: Nelson,Thomas(tn1381)(arthurdent3) <tn1381@att.com>
Diffstat (limited to 'src/main/java/org/onap/music/main/MusicUtil.java')
-rwxr-xr-xsrc/main/java/org/onap/music/main/MusicUtil.java409
1 files changed, 296 insertions, 113 deletions
diff --git a/src/main/java/org/onap/music/main/MusicUtil.java b/src/main/java/org/onap/music/main/MusicUtil.java
index d2e8591c..805f459f 100755
--- a/src/main/java/org/onap/music/main/MusicUtil.java
+++ b/src/main/java/org/onap/music/main/MusicUtil.java
@@ -9,18 +9,19 @@
* 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;
@@ -45,24 +46,34 @@ import javax.ws.rs.core.Response.ResponseBuilder;
import org.onap.music.datastore.PreparedQueryObject;
import org.onap.music.eelf.logging.EELFLoggerDelegate;
+import org.onap.music.exceptions.MusicQueryException;
+import org.onap.music.exceptions.MusicServiceException;
+import org.onap.music.service.MusicCoreService;
+import org.onap.music.service.impl.MusicCassaCore;
+import org.onap.music.service.impl.MusicZKCore;
+import com.datastax.driver.core.ConsistencyLevel;
import com.datastax.driver.core.DataType;
import com.sun.jersey.core.util.Base64;
/**
* @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 EVENTUAL_NB = "eventual_nb";
+ public static final String ALL = "all";
+ public static final String QUORUM = "quorum";
+ public static final String ONE = "one";
public static final String ATOMICDELETELOCK = "atomic_delete_lock";
public static final String DEFAULTKEYSPACENAME = "TBD";
private static final String XLATESTVERSION = "X-latestVersion";
@@ -74,12 +85,14 @@ public class MusicUtil {
public static final String UPSERT = "upsert";
public static final String USERID = "userId";
public static final String PASSWORD = "password";
+ public static final String CASSANDRA = "cassandra";
+ public static final String ZOOKEEPER = "zookeeper";
- public static final String AUTHORIZATION = "Authorization";
+ public static final String AUTHORIZATION = "Authorization";
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 = "";
@@ -90,6 +103,9 @@ public class MusicUtil {
private static int cassandraPort = 9042;
private static int notifytimeout = 30000;
private static int notifyinterval = 5000;
+ private static int cacheObjectMaxLife = -1;
+ private static String lockUsing = MusicUtil.CASSANDRA;
+ private static boolean isCadi = false;
private static boolean debug = true;
private static String version = "2.3.0";
@@ -98,31 +114,118 @@ public class MusicUtil {
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","cassandra.port", "notify.timeout", "notify.interval" };
+ "all.pubic.ips", "cassandra.user", "cassandra.password", "aaf.endpoint.url","admin.username","admin.password","aaf.admin.url",
+ "music.namespace","admin.aaf.role","cassandra.port","lock.using"};
+ private static final String[] cosistencyLevel = new String[] {
+ "ALL","EACH_QUORUM","QUORUM","LOCAL_QUORUM","ONE","TWO","THREE","LOCAL_ONE","ANY","SERIAL","LOCAL_SERIAL"};
+ private static final Map<String,ConsistencyLevel> consistencyName = new HashMap<>();
+ static {
+ consistencyName.put("ONE",ConsistencyLevel.ONE);
+ consistencyName.put("TWO",ConsistencyLevel.TWO);
+ consistencyName.put("THREE",ConsistencyLevel.THREE);
+ consistencyName.put("SERIAL",ConsistencyLevel.SERIAL);
+ consistencyName.put("ALL",ConsistencyLevel.ALL);
+ consistencyName.put("EACH_QUORUM",ConsistencyLevel.EACH_QUORUM);
+ consistencyName.put("QUORUM",ConsistencyLevel.QUORUM);
+ consistencyName.put("LOCAL_QUORUM",ConsistencyLevel.LOCAL_QUORUM);
+ consistencyName.put("LOCAL_ONE",ConsistencyLevel.LOCAL_ONE);
+ consistencyName.put("LOCAL_SERIAL",ConsistencyLevel.LOCAL_SERIAL);
+ }
private static String cassName = "cassandra";
private static String cassPwd;
private static String aafEndpointUrl = null;
- public static final ConcurrentMap<String, Long> zkNodeMap = new ConcurrentHashMap<>();
+ public static ConcurrentMap<String, Long> zkNodeMap = new ConcurrentHashMap<>();
+ private static String adminId = "username";
+ private static String adminPass= "password";
+ private static String aafAdminUrl= null;
+ private static String musicNamespace= "com.att.music.api";
+ private static String adminAafRole= "com.att.music.api.admin_api";
+
+ public static final long MusicEternityEpochMillis = 1533081600000L; // Wednesday, August 1, 2018 12:00:00 AM
+
+ public static final long MaxLockReferenceTimePart = 1000000000000L; // millis after eternity (eq sometime in 2050)
+
+ public static final long MaxCriticalSectionDurationMillis = 1L * 24 * 60 * 60 * 1000; // 1 day
+
+
+ public static String getLockUsing() {
+ return lockUsing;
+ }
+
+
+ public static void setLockUsing(String lockUsing) {
+ MusicUtil.lockUsing = lockUsing;
+ }
+
+ public static String getAafAdminUrl() {
+ return aafAdminUrl;
+ }
+
+
+ public static void setAafAdminUrl(String aafAdminUrl) {
+ MusicUtil.aafAdminUrl = aafAdminUrl;
+ }
+
+
+ public static String getMusicNamespace() {
+ return musicNamespace;
+ }
+
+
+ public static void setMusicNamespace(String musicNamespace) {
+ MusicUtil.musicNamespace = musicNamespace;
+ }
+
+
+ public static String getAdminAafRole() {
+ return adminAafRole;
+ }
+
+
+ public static void setAdminAafRole(String adminAafRole) {
+ MusicUtil.adminAafRole = adminAafRole;
+ }
+
+
+
+ public static String getAdminId() {
+ return adminId;
+ }
+
+
+ public static void setAdminId(String adminId) {
+ MusicUtil.adminId = adminId;
+ }
+
+
+ public static String getAdminPass() {
+ return adminPass;
+ }
+
+ public static void setAdminPass(String adminPass) {
+ MusicUtil.adminPass = adminPass;
+ }
+
private MusicUtil() {
throw new IllegalStateException("Utility Class");
}
/**
- *
+ *
* @return cassandra port
*/
public static int getCassandraPort() {
- return cassandraPort;
- }
+ return cassandraPort;
+ }
/**
* set cassandra port
* @param cassandraPort
*/
- public static void setCassandraPort(int cassandraPort) {
- MusicUtil.cassandraPort = cassandraPort;
- }
+ public static void setCassandraPort(int cassandraPort) {
+ MusicUtil.cassandraPort = cassandraPort;
+ }
/**
* @return the cassName
*/
@@ -145,7 +248,7 @@ public class MusicUtil {
}
/**
- *
+ *
* @param aafEndpointUrl
*/
public static void setAafEndpointUrl(String aafEndpointUrl) {
@@ -153,7 +256,7 @@ public class MusicUtil {
}
/**
- *
+ *
* @return
*/
public static int getMyId() {
@@ -161,7 +264,7 @@ public class MusicUtil {
}
/**
- *
+ *
* @param myId
*/
public static void setMyId(int myId) {
@@ -169,7 +272,7 @@ public class MusicUtil {
}
/**
- *
+ *
* @return
*/
public static List<String> getAllIds() {
@@ -177,7 +280,7 @@ public class MusicUtil {
}
/**
- *
+ *
* @param allIds
*/
public static void setAllIds(List<String> allIds) {
@@ -185,7 +288,7 @@ public class MusicUtil {
}
/**
- *
+ *
* @return
*/
public static String getPublicIp() {
@@ -193,7 +296,7 @@ public class MusicUtil {
}
/**
- *
+ *
* @param publicIp
*/
public static void setPublicIp(String publicIp) {
@@ -201,7 +304,7 @@ public class MusicUtil {
}
/**
- *
+ *
* @return
*/
public static List<String> getAllPublicIps() {
@@ -209,7 +312,7 @@ public class MusicUtil {
}
/**
- *
+ *
* @param allPublicIps
*/
public static void setAllPublicIps(List<String> allPublicIps) {
@@ -219,7 +322,7 @@ public class MusicUtil {
/**
* Returns An array of property names that should be in the Properties
* files.
- *
+ *
* @return
*/
public static String[] getPropkeys() {
@@ -228,7 +331,7 @@ public class MusicUtil {
/**
* Get MusicRestIp - default = localhost property file value - music.rest.ip
- *
+ *
* @return
*/
public static String getMusicRestIp() {
@@ -237,7 +340,7 @@ public class MusicUtil {
/**
* Set MusicRestIp
- *
+ *
* @param musicRestIp
*/
public static void setMusicRestIp(String musicRestIp) {
@@ -247,7 +350,7 @@ public class MusicUtil {
/**
* Get MusicPropertiesFilePath - Default = /opt/music/music.properties
* property file value - music.properties
- *
+ *
* @return
*/
public static String getMusicPropertiesFilePath() {
@@ -256,7 +359,7 @@ public class MusicUtil {
/**
* Set MusicPropertiesFilePath
- *
+ *
* @param musicPropertiesFilePath
*/
public static void setMusicPropertiesFilePath(String musicPropertiesFilePath) {
@@ -266,7 +369,7 @@ public class MusicUtil {
/**
* Get DefaultLockLeasePeriod - Default = 6000 property file value -
* lock.lease.period
- *
+ *
* @return
*/
public static long getDefaultLockLeasePeriod() {
@@ -275,7 +378,7 @@ public class MusicUtil {
/**
* Set DefaultLockLeasePeriod
- *
+ *
* @param defaultLockLeasePeriod
*/
public static void setDefaultLockLeasePeriod(long defaultLockLeasePeriod) {
@@ -284,7 +387,7 @@ public class MusicUtil {
/**
* Set Debug
- *
+ *
* @param debug
*/
public static void setDebug(boolean debug) {
@@ -293,7 +396,7 @@ public class MusicUtil {
/**
* Is Debug - Default = true property file value - debug
- *
+ *
* @return
*/
public static boolean isDebug() {
@@ -302,7 +405,7 @@ public class MusicUtil {
/**
* Set Version
- *
+ *
* @param version
*/
public static void setVersion(String version) {
@@ -311,7 +414,7 @@ public class MusicUtil {
/**
* Return the version property file value - version
- *
+ *
* @return
*/
public static String getVersion() {
@@ -321,7 +424,7 @@ public class MusicUtil {
/**
* Get MyZkHost - Zookeeper Hostname - Default = localhost property file
* value - zookeeper.host
- *
+ *
* @return
*/
public static String getMyZkHost() {
@@ -330,7 +433,7 @@ public class MusicUtil {
/**
* Set MyZkHost - Zookeeper Hostname
- *
+ *
* @param myZkHost
*/
public static void setMyZkHost(String myZkHost) {
@@ -340,7 +443,7 @@ public class MusicUtil {
/**
* Get MyCassHost - Cassandra Hostname - Default = localhost property file
* value - cassandra.host
- *
+ *
* @return
*/
public static String getMyCassaHost() {
@@ -349,7 +452,7 @@ public class MusicUtil {
/**
* Set MyCassHost - Cassandra Hostname
- *
+ *
* @param myCassaHost
*/
public static void setMyCassaHost(String myCassaHost) {
@@ -358,7 +461,7 @@ public class MusicUtil {
/**
* Get DefaultMusicIp - Default = localhost property file value - music.ip
- *
+ *
* @return
*/
public static String getDefaultMusicIp() {
@@ -367,7 +470,7 @@ public class MusicUtil {
/**
* Set DefaultMusicIp
- *
+ *
* @param defaultMusicIp
*/
public static void setDefaultMusicIp(String defaultMusicIp) {
@@ -375,7 +478,7 @@ public class MusicUtil {
}
/**
- *
+ *
* @return
*/
public static String getTestType() {
@@ -384,7 +487,7 @@ public class MusicUtil {
Scanner fileScanner = new Scanner(new File(""));
testType = fileScanner.next();// ignore the my id line
@SuppressWarnings("unused")
- String batchSize = fileScanner.next();// ignore the my public ip
+ String batchSize = fileScanner.next();// ignore the my public ip
// line
fileScanner.close();
} catch (FileNotFoundException e) {
@@ -395,7 +498,7 @@ public class MusicUtil {
}
/**
- *
+ *
* @param time
*/
public static void sleep(long time) {
@@ -409,7 +512,7 @@ public class MusicUtil {
/**
* Utility function to check if the query object is valid.
- *
+ *
* @param withparams
* @param queryObject
* @return
@@ -439,7 +542,7 @@ public class MusicUtil {
}
@SuppressWarnings("unchecked")
- public static String convertToCQLDataType(DataType type, Object valueObj) throws Exception {
+ public static String convertToCQLDataType(DataType type, Object valueObj) throws Exception {
String value = "";
switch (type.getName()) {
@@ -465,15 +568,15 @@ public class MusicUtil {
}
/**
- *
+ *
* @param colType
* @param valueObj
* @return
- * @throws MusicTypeConversionException
+ * @throws MusicTypeConversionException
* @throws Exception
*/
@SuppressWarnings("unchecked")
- public static Object convertToActualDataType(DataType colType, Object valueObj) throws Exception {
+ public static Object convertToActualDataType(DataType colType, Object valueObj) throws Exception {
String valueObjString = valueObj + "";
switch (colType.getName()) {
case UUID:
@@ -492,8 +595,10 @@ public class MusicUtil {
return Boolean.parseBoolean(valueObjString);
case MAP:
return (Map<String, Object>) valueObj;
+ case LIST:
+ return (List<Object>)valueObj;
case BLOB:
-
+
default:
return valueObjString;
}
@@ -503,11 +608,11 @@ public class MusicUtil {
ByteBuffer buffer = ByteBuffer.wrap(valueObj);
return buffer;
}
-
+
/**
*
* Utility function to parse json map into sql like string
- *
+ *
* @param jMap
* @param lineDelimiter
* @return
@@ -540,13 +645,13 @@ public class MusicUtil {
}
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.
+ * Future plans will change this.
* @param response
* @param major
* @param minor
@@ -558,78 +663,156 @@ public class MusicUtil {
String versionIn = buildVersion(major,minor,patch);
String version = MusicUtil.getVersion();
String[] verArray = version.split("\\.",3);
- if ( minor != null ) {
+ 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 Map<String,String> extractBasicAuthentication(String authorization){
+ Map<String,String> authValues = new HashMap<>();
+ if(authorization == null) {
+ authValues.put("ERROR", "Authorization cannot be null");
+ return authValues;
+ }
+ authorization = authorization.replaceFirst("Basic", "");
+ String decoded = Base64.base64Decode(authorization);
+ StringTokenizer token = new StringTokenizer(decoded, ":");
+ authValues.put(MusicUtil.USERID, token.nextToken());
+ authValues.put(MusicUtil.PASSWORD,token.nextToken());
+ return authValues;
+
+ }
+
+ public static boolean isValidConsistency(String consistency) {
+ for (String string : cosistencyLevel) {
+ if (string.equalsIgnoreCase(consistency))
+ return true;
+ }
+ return false;
+
+ }
+
+ public static ConsistencyLevel getConsistencyLevel(String consistency) {
+ return consistencyName.get(consistency.toUpperCase());
+ }
+
+ 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 zkHosts = prop.getProperty("zookeeper.host");
+ MusicUtil.setMyZkHost(zkHosts);
+ MusicUtil.setCassName(prop.getProperty("cassandra.user"));
+ MusicUtil.setCassPwd(prop.getProperty("cassandra.password"));
+ MusicUtil.setCassandraPort(Integer.parseInt(prop.getProperty("cassandra.port")));
+ MusicUtil.setNotifyTimeOut(Integer.parseInt(prop.getProperty("notify.timeout")));
+ MusicUtil.setNotifyInterval(Integer.parseInt(prop.getProperty("notify.interval")));
+ MusicUtil.setCacheObjectMaxLife(Integer.parseInt(prop.getProperty("cacheobject.maxlife")));
+ }
+
+ public static void setNotifyInterval(int notifyinterval) {
+ MusicUtil.notifyinterval = notifyinterval;
+ }
+ public static void setNotifyTimeOut(int notifytimeout) {
+ MusicUtil.notifytimeout = notifytimeout;
+ }
+
+ public static int getNotifyInterval() {
+ return MusicUtil.notifyinterval;
+ }
+
+ public static int getNotifyTimeout() {
+ return MusicUtil.notifytimeout;
+ }
+
+ public static int getCacheObjectMaxLife() {
+ return MusicUtil.cacheObjectMaxLife;
+ }
+
+ public static void setCacheObjectMaxLife(int cacheObjectMaxLife) {
+ MusicUtil.cacheObjectMaxLife = cacheObjectMaxLife;
+ }
+ /**
+ * Given the time of write for an update in a critical section, this method provides a transformed timestamp
+ * that ensures that a previous lock holder who is still alive can never corrupt a later critical section.
+ * The main idea is to us the lock reference to clearly demarcate the timestamps across critical sections.
+ * @param the UUID lock reference associated with the write.
+ * @param the long timeOfWrite which is the actual time at which the write took place
+ * @throws MusicServiceException
+ * @throws MusicQueryException
+ */
+ public static long v2sTimeStampInMicroseconds(long ordinal, long timeOfWrite) throws MusicServiceException, MusicQueryException {
+ // TODO: use acquire time instead of music eternity epoch
+ long ts = ordinal * MaxLockReferenceTimePart + (timeOfWrite - MusicEternityEpochMillis);
+
+ return ts;
+ }
- public static Map<String,String> extractBasicAuthentication(String authorization){
-
- Map<String,String> authValues = new HashMap<>();
- authorization = authorization.replaceFirst("Basic", "");
- String decoded = Base64.base64Decode(authorization);
- StringTokenizer token = new StringTokenizer(decoded, ":");
- authValues.put(MusicUtil.USERID, token.nextToken());
- authValues.put(MusicUtil.PASSWORD,token.nextToken());
- return authValues;
-
+ public static MusicCoreService getMusicCoreService() {
+ if(getLockUsing().equals(MusicUtil.CASSANDRA))
+ return MusicCassaCore.getInstance();
+ else if (getLockUsing().equals(MusicUtil.ZOOKEEPER))
+ return MusicZKCore.getInstance();
+ else
+ return MusicCassaCore.getInstance();
}
- 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) {
- logger.error(EELFLoggerDelegate.applicationLogger,"Load properties failed "+e.getMessage(),e);
- }
- }
- }
- // get the property value and return it
- MusicUtil.setMyCassaHost(prop.getProperty("cassandra.host"));
- String zkHosts = prop.getProperty("zookeeper.host");
- MusicUtil.setMyZkHost(zkHosts);
- MusicUtil.setCassName(prop.getProperty("cassandra.user"));
- MusicUtil.setCassPwd(prop.getProperty("cassandra.password"));
- MusicUtil.setCassandraPort(Integer.parseInt(prop.getProperty("cassandra.port")));
- MusicUtil.setNotifyTimeOut(Integer.parseInt(prop.getProperty("notify.timeout")));
- MusicUtil.setNotifyInterval(Integer.parseInt(prop.getProperty("notify.interval")));
-
- }
+ /**
+ * @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("Error", "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;
+ }
+
+
+ public static void setIsCadi(boolean isCadi) {
+ // TODO Auto-generated method stub
+ MusicUtil.isCadi = isCadi;
+ }
- public static void setNotifyInterval(int notifyinterval) {
- MusicUtil.notifyinterval = notifyinterval;
- }
- public static void setNotifyTimeOut(int notifytimeout) {
- MusicUtil.notifytimeout = notifytimeout;
- }
-
- public static int getNotifyInterval() {
- return MusicUtil.notifyinterval;
- }
-
- public static int getNotifyTimeout() {
- return MusicUtil.notifytimeout;
-
- }
+ public static boolean getIsCadi() {
+ return MusicUtil.isCadi;
+ }
+
}
+