Return-Path: X-Original-To: apmail-airavata-commits-archive@www.apache.org Delivered-To: apmail-airavata-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 4368B18FBC for ; Thu, 11 Jun 2015 21:34:43 +0000 (UTC) Received: (qmail 79508 invoked by uid 500); 11 Jun 2015 21:34:43 -0000 Delivered-To: apmail-airavata-commits-archive@airavata.apache.org Received: (qmail 79389 invoked by uid 500); 11 Jun 2015 21:34:43 -0000 Mailing-List: contact commits-help@airavata.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@airavata.apache.org Delivered-To: mailing list commits@airavata.apache.org Received: (qmail 79177 invoked by uid 99); 11 Jun 2015 21:34:43 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 11 Jun 2015 21:34:43 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id B8C71E0A05; Thu, 11 Jun 2015 21:34:42 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: shameera@apache.org To: commits@airavata.apache.org Date: Thu, 11 Jun 2015 21:34:48 -0000 Message-Id: In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [7/8] airavata git commit: moved commons-utils to commons module http://git-wip-us.apache.org/repos/asf/airavata/blob/8d16d0ec/modules/commons/src/main/java/org/apache/airavata/common/utils/AiravataZKUtils.java ---------------------------------------------------------------------- diff --git a/modules/commons/src/main/java/org/apache/airavata/common/utils/AiravataZKUtils.java b/modules/commons/src/main/java/org/apache/airavata/common/utils/AiravataZKUtils.java new file mode 100644 index 0000000..f753bc1 --- /dev/null +++ b/modules/commons/src/main/java/org/apache/airavata/common/utils/AiravataZKUtils.java @@ -0,0 +1,205 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * +*/ +package org.apache.airavata.common.utils; + +import org.apache.airavata.common.exception.ApplicationSettingsException; +import org.apache.curator.framework.CuratorFramework; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.data.Stat; +import org.apache.zookeeper.server.ServerCnxnFactory; +import org.apache.zookeeper.server.ServerConfig; +import org.apache.zookeeper.server.ZooKeeperServer; +import org.apache.zookeeper.server.persistence.FileTxnSnapLog; +import org.apache.zookeeper.server.quorum.QuorumPeerConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.ByteBuffer; + +public class AiravataZKUtils implements Watcher { + private final static Logger logger = LoggerFactory.getLogger(AiravataZKUtils.class); + + public static final String ZK_EXPERIMENT_STATE_NODE = "state"; + public static final String DELIVERY_TAG_POSTFIX = "-deliveryTag"; + public static final String CANCEL_DELIVERY_TAG_POSTFIX = "-cancel-deliveryTag"; + + @Override + public void process(WatchedEvent event) { + + } + + public static String getExpZnodePath(String experimentId) throws ApplicationSettingsException { + return ServerSettings.getSetting(Constants.ZOOKEEPER_GFAC_EXPERIMENT_NODE) + + File.separator + + ServerSettings.getSetting(Constants.ZOOKEEPER_GFAC_SERVER_NAME) + File.separator + + experimentId; + } + + public static String getExpZnodeHandlerPath(String experimentId, String className) throws ApplicationSettingsException { + return ServerSettings.getSetting(Constants.ZOOKEEPER_GFAC_EXPERIMENT_NODE) + + File.separator + + ServerSettings.getSetting(Constants.ZOOKEEPER_GFAC_SERVER_NAME) + File.separator + + experimentId + File.separator + className; + } + + public static String getZKhostPort() throws ApplicationSettingsException { + return ServerSettings.getSetting(Constants.ZOOKEEPER_SERVER_HOST,"localhost") + + ":" + ServerSettings.getSetting(Constants.ZOOKEEPER_SERVER_PORT,"2181"); + } + + public static int getZKTimeout()throws ApplicationSettingsException { + return Integer.parseInt(ServerSettings.getSetting(Constants.ZOOKEEPER_TIMEOUT,"30000")); + } + + public static String getExpStatePath(String experimentId) throws ApplicationSettingsException { + return AiravataZKUtils.getExpZnodePath(experimentId) + + File.separator + + "state"; + } + + public static String getExpState(CuratorFramework curatorClient, String expId) throws Exception { + Stat exists = curatorClient.checkExists().forPath(getExpStatePath(expId)); + if (exists != null) { + return new String(curatorClient.getData().storingStatIn(exists).forPath(getExpStatePath(expId))); + } + return null; + } + + public static void runZKFromConfig(ServerConfig config,ServerCnxnFactory cnxnFactory) throws IOException { + AiravataZKUtils.logger.info("Starting Zookeeper server..."); + FileTxnSnapLog txnLog = null; + try { + // Note that this thread isn't going to be doing anything else, + // so rather than spawning another thread, we will just call + // run() in this thread. + // create a file logger url from the command line args + ZooKeeperServer zkServer = new ZooKeeperServer(); + + txnLog = new FileTxnSnapLog(new File(config.getDataDir()), new File( + config.getDataDir())); + zkServer.setTxnLogFactory(txnLog); + zkServer.setTickTime(config.getTickTime()); + zkServer.setMinSessionTimeout(config.getMinSessionTimeout()); + zkServer.setMaxSessionTimeout(config.getMaxSessionTimeout()); + cnxnFactory = ServerCnxnFactory.createFactory(); + cnxnFactory.configure(config.getClientPortAddress(), + config.getMaxClientCnxns()); + cnxnFactory.startup(zkServer); + cnxnFactory.join(); + if (zkServer.isRunning()) { + zkServer.shutdown(); + } + } catch (InterruptedException e) { + // warn, but generally this is ok + AiravataZKUtils.logger.warn("Server interrupted", e); + System.exit(1); + } finally { + if (txnLog != null) { + txnLog.close(); + } + } + } + + public static void startEmbeddedZK(ServerCnxnFactory cnxnFactory) { + if (ServerSettings.isEmbeddedZK()) { + ServerConfig serverConfig = new ServerConfig(); + URL resource = AiravataZKUtils.class.getClassLoader().getResource("zoo.cfg"); + if (resource == null) { + logger.error("There is no zoo.cfg file in the classpath... Failed to start Zookeeper Server"); + System.exit(1); + } + try { + serverConfig.parse(resource.getPath()); + } catch (QuorumPeerConfig.ConfigException e) { + logger.error("Error while starting embedded Zookeeper", e); + System.exit(2); + } + + final ServerConfig fServerConfig = serverConfig; + final ServerCnxnFactory fserverCnxnFactory = cnxnFactory; + (new Thread() { + public void run() { + try { + AiravataZKUtils.runZKFromConfig(fServerConfig,fserverCnxnFactory); + } catch (IOException e) { + logger.error("Error while starting embedded Zookeeper", e); + System.exit(3); + } + } + }).start(); + }else{ + logger.info("Skipping Zookeeper embedded startup ..."); + } + } + + public static byte[] toByteArray(double value) { + byte[] bytes = new byte[8]; + ByteBuffer.wrap(bytes).putDouble(value); + return bytes; + } + + public static long getDeliveryTag(String experimentID, CuratorFramework curatorClient, String experimentNode, + String pickedChild) throws Exception { + String deliveryTagPath = experimentNode + File.separator + pickedChild + File.separator + experimentID + + DELIVERY_TAG_POSTFIX; + Stat exists = curatorClient.checkExists().forPath(deliveryTagPath); + if(exists==null) { + logger.error("Cannot find delivery Tag in path:" + deliveryTagPath + " for this experiment"); + return -1; + } + return bytesToLong(curatorClient.getData().storingStatIn(exists).forPath(deliveryTagPath)); + } + public static byte[] longToBytes(long x) { + ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES); + buffer.putLong(x); + return buffer.array(); + } + + public static long bytesToLong(byte[] bytes) { + ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES); + buffer.put(bytes); + buffer.flip();//need flip + return buffer.getLong(); + } + + public static double toDouble(byte[] bytes) { + return ByteBuffer.wrap(bytes).getDouble(); + } + + public static long getCancelDeliveryTagIfExist(String experimentId, CuratorFramework curatorClient, + String experimentNode, String pickedChild) throws Exception { + + String cancelDeliveryTagPath = experimentNode + File.separator + pickedChild + File.separator + experimentId + + AiravataZKUtils.CANCEL_DELIVERY_TAG_POSTFIX; + Stat exists = curatorClient.checkExists().forPath(cancelDeliveryTagPath); + if (exists == null) { + return -1; // no cancel deliverytag found + } else { + return bytesToLong(curatorClient.getData().storingStatIn(exists).forPath(cancelDeliveryTagPath)); + } + + + } +} http://git-wip-us.apache.org/repos/asf/airavata/blob/8d16d0ec/modules/commons/src/main/java/org/apache/airavata/common/utils/ApplicationSettings.java ---------------------------------------------------------------------- diff --git a/modules/commons/src/main/java/org/apache/airavata/common/utils/ApplicationSettings.java b/modules/commons/src/main/java/org/apache/airavata/common/utils/ApplicationSettings.java new file mode 100644 index 0000000..9a59573 --- /dev/null +++ b/modules/commons/src/main/java/org/apache/airavata/common/utils/ApplicationSettings.java @@ -0,0 +1,444 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + */ + +package org.apache.airavata.common.utils; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.airavata.common.exception.ApplicationSettingsException; +import org.apache.airavata.common.exception.ApplicationSettingsLoadException; +import org.apache.airavata.common.exception.ApplicationSettingsStoreException; +import org.apache.airavata.common.exception.UnspecifiedApplicationSettingsException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ApplicationSettings { + public static final String SERVER_PROPERTIES="airavata-server.properties"; + + public static String ADDITIONAL_SETTINGS_FILES = "external.settings"; + + protected Properties properties = new Properties(); + private Exception propertyLoadException; + + + protected static final String TRUST_STORE_PATH="trust.store"; + protected static final String TRUST_STORE_PASSWORD="trust.store.password"; + + private static final String REGULAR_EXPRESSION = "\\$\\{[a-zA-Z.-]*\\}"; + + private final static Logger logger = LoggerFactory.getLogger(ApplicationSettings.class); + + private static final String SHUTDOWN_STATEGY_STRING="shutdown.strategy"; + + protected static ApplicationSettings INSTANCE; + public static enum ShutdownStrategy{ + NONE, + SELF_TERMINATE + } + { + loadProperties(); + } + + private void loadProperties() { + URL url = getPropertyFileURL(); + try { + + properties.load(url.openStream()); + logger.info("Settings loaded from "+url.toString()); + URL[] externalSettingsFileURLs = getExternalSettingsFileURLs(); + for (URL externalSettings : externalSettingsFileURLs) { + mergeSettingsImpl(externalSettings.openStream()); + logger.info("External settings merged from "+url.toString()); + } + } catch (Exception e) { + propertyLoadException=e; + } + } + + protected URL getPropertyFileURL() { + return ApplicationSettings.class.getClassLoader().getResource(SERVER_PROPERTIES); + } + + protected URL[] getExternalSettingsFileURLs(){ + try { + List externalSettingsFileURLs=new ArrayList(); + String externalSettingsFileNames = getSettingImpl(ADDITIONAL_SETTINGS_FILES); + String[] externalSettingFiles = externalSettingsFileNames.split(","); + for (String externalSettingFile : externalSettingFiles) { + URL externalSettingFileURL = ApplicationSettings.class.getClassLoader().getResource(externalSettingFile); + if (externalSettingFileURL==null){ + logger.warn("Could not file external settings file "+externalSettingFile); + }else{ + externalSettingsFileURLs.add(externalSettingFileURL); + } + } + return externalSettingsFileURLs.toArray(new URL[]{}); + } catch (ApplicationSettingsException e) { + return new URL[]{}; + } + } + protected static ApplicationSettings getInstance(){ + if (INSTANCE==null){ + INSTANCE=new ApplicationSettings(); + } + return INSTANCE; + } + + protected static void setInstance(ApplicationSettings settingsInstance){ + INSTANCE=settingsInstance; + } + + private void saveProperties() throws ApplicationSettingsStoreException{ + URL url = getPropertyFileURL(); + if (url.getProtocol().equalsIgnoreCase("file")){ + try { + properties.store(new FileOutputStream(url.getPath()), Calendar.getInstance().toString()); + } catch (Exception e) { + throw new ApplicationSettingsStoreException(url.getPath(), e); + } + }else{ + logger.warn("Properties cannot be updated to location "+url.toString()); + } + } + + private void validateSuccessfulPropertyFileLoad() throws ApplicationSettingsException{ + if (propertyLoadException!=null){ + throw new ApplicationSettingsLoadException(propertyLoadException); + } + } + + /** + * Returns the configuration value relevant for the given key. + * If configuration value contains references to other configuration values they will also + * be replaced. E.g :- If configuration key reads http://${ip}:${port}/axis2/services/RegistryService?wsdl, + * the variables ip and port will get replaced by their appropriated values in the configuration. + * @param key The configuration key to read value of + * @return The configuration value. For above example caller will get a value like + * http://192.2.33.12:8080/axis2/services/RegistryService?wsdl + * @throws ApplicationSettingsException If an error occurred while reading configurations. + * @deprecated use #getSetting(String) instead + */ + public String getAbsoluteSetting(String key) throws ApplicationSettingsException { + + String configurationValueWithVariables = ApplicationSettings.getSetting(key); + + List variableList + = getAllMatches(configurationValueWithVariables, REGULAR_EXPRESSION); + + if (variableList == null || variableList.isEmpty()) { + return configurationValueWithVariables; + } + + for(String variableIdentifier : variableList) { + String variableName = getVariableNameOnly(variableIdentifier); + String value = getAbsoluteSetting(variableName); + + configurationValueWithVariables = configurationValueWithVariables.replace(variableIdentifier, value); + } + + return configurationValueWithVariables; + + } + + private static String getVariableNameOnly(String variableWithIdentifiers) { + return variableWithIdentifiers.substring(2, (variableWithIdentifiers.length() - 1)); + } + + private static List getAllMatches(String text, String regex) { + List matches = new ArrayList(); + Matcher m = Pattern.compile("(?=(" + regex + "))").matcher(text); + while(m.find()) { + matches.add(m.group(1)); + } + return matches; + } + + public String getSettingImpl(String key) throws ApplicationSettingsException{ + String rawValue=null; + if (System.getProperties().containsKey(key)){ + rawValue=System.getProperties().getProperty(key); + }else{ + validateSuccessfulPropertyFileLoad(); + if (properties.containsKey(key)){ + rawValue=properties.getProperty(key); + }else{ + throw new UnspecifiedApplicationSettingsException(key); + } + } + return deriveAbsoluteValueImpl(rawValue); + } + + public String getSettingImpl(String key, String defaultValue){ + try { + return getSettingImpl(key); + } catch (ApplicationSettingsException e) { + //we'll ignore this error since a default value is provided + } + return defaultValue; + } + + private String deriveAbsoluteValueImpl(String property){ + if (property!=null){ + Map containedParameters = StringUtil.getContainedParameters(property); + List parametersAlreadyProcessed=new ArrayList(); + for (String parameter : containedParameters.values()) { + if (!parametersAlreadyProcessed.contains(parameter)) { + String parameterName = parameter.substring(2,parameter.length() - 1); + String parameterValue = getSetting(parameterName,parameter); + property = property.replaceAll(Pattern.quote(parameter), parameterValue); + parametersAlreadyProcessed.add(parameter); + } + } + } + return property; + } + + public void setSettingImpl(String key, String value) throws ApplicationSettingsException{ + properties.setProperty(key, value); + saveProperties(); + } + + public boolean isSettingDefinedImpl(String key) throws ApplicationSettingsException{ + validateSuccessfulPropertyFileLoad(); + return properties.containsKey(key); + } + + public String getTrustStorePathImpl() throws ApplicationSettingsException { + return getSetting(TRUST_STORE_PATH); + } + + public String getTrustStorePasswordImpl() throws ApplicationSettingsException { + return getSetting(TRUST_STORE_PASSWORD); + } + + public String getCredentialStoreKeyStorePathImpl() throws ApplicationSettingsException { + return getSetting("credential.store.keystore.url"); + } + + public String getCredentialStoreKeyAliasImpl() throws ApplicationSettingsException { + return getSetting("credential.store.keystore.alias"); + } + + public String getCredentialStoreKeyStorePasswordImpl() throws ApplicationSettingsException { + return getSetting("credential.store.keystore.password"); + } + + public String getCredentialStoreNotifierEnabledImpl() throws ApplicationSettingsException { + return getSetting("notifier.enabled"); + } + + public String getCredentialStoreNotifierDurationImpl() throws ApplicationSettingsException { + return getSetting("notifier.duration"); + } + + public String getCredentialStoreEmailServerImpl() throws ApplicationSettingsException { + return getSetting("email.server"); + } + + public String getCredentialStoreEmailServerPortImpl() throws ApplicationSettingsException { + return getSetting("email.server.port"); + } + + public String getCredentialStoreEmailUserImpl() throws ApplicationSettingsException { + return getSetting("email.user"); + } + + public String getCredentialStoreEmailPasswordImpl() throws ApplicationSettingsException { + return getSetting("email.password"); + } + + public String getCredentialStoreEmailSSLConnectImpl() throws ApplicationSettingsException { + return getSetting("email.ssl"); + } + + public String getCredentialStoreEmailFromEmailImpl() throws ApplicationSettingsException { + return getSetting("email.from"); + } + + /** + * @deprecated use {{@link #getSetting(String)}} + * @return + */ + public Properties getPropertiesImpl() { + return properties; + } + + public void mergeSettingsImpl(Map props){ + properties.putAll(props); + } + + public void mergeSettingsImpl(InputStream stream) throws IOException{ + Properties tmpProp = new Properties(); + tmpProp.load(stream); + properties.putAll(tmpProp); + } + + public void mergeSettingsCommandLineArgsImpl(String[] args){ + properties.putAll(StringUtil.parseCommandLineOptions(args)); + } + + public ShutdownStrategy getShutdownStrategyImpl() throws Exception{ + String strategy = null; + try { + strategy = getSetting(SHUTDOWN_STATEGY_STRING, ShutdownStrategy.SELF_TERMINATE.toString()); + return ShutdownStrategy.valueOf(strategy); + } catch (Exception e) { + //if the string mentioned in config is invalid + throw new Exception("Invalid shutdown strategy configured : "+strategy); + } + } + + /* + * Static methods which will be used by the users + */ + + public static String getSetting(String key) throws ApplicationSettingsException{ + return getInstance().getSettingImpl(key); + } + + public static String getSetting(String key, String defaultValue){ + return getInstance().getSettingImpl(key,defaultValue); + + } + + public static void setSetting(String key, String value) throws ApplicationSettingsException{ + getInstance().properties.setProperty(key, value); + getInstance().saveProperties(); + } + + public static boolean isSettingDefined(String key) throws ApplicationSettingsException{ + return getInstance().properties.containsKey(key); + } + + public static String getTrustStorePath() throws ApplicationSettingsException { + return getSetting(TRUST_STORE_PATH); + } + + public static String getTrustStorePassword() throws ApplicationSettingsException { + return getSetting(TRUST_STORE_PASSWORD); + } + + public static void initializeTrustStore() throws ApplicationSettingsException { + SecurityUtil.setTrustStoreParameters(getTrustStorePath(), getTrustStorePassword()); + } + + public static String getCredentialStoreKeyStorePath() throws ApplicationSettingsException { + return getSetting("credential.store.keystore.url"); + } + + public static String getCredentialStoreThriftServerKeyStorePath() throws ApplicationSettingsException { + return getSetting("credential.store.thrift.server.keystore"); + } + + public static boolean isCredentialStoreStartEnabled() throws ApplicationSettingsException { + String enableCredentialStore = getSetting("start.credential.store"); + if (enableCredentialStore.equals("true")){ + return true; + } + return false; + } + + public static String getCredentialStoreKeyAlias() throws ApplicationSettingsException { + return getSetting("credential.store.keystore.alias"); + } + + public static String getCredentialStoreKeyStorePassword() throws ApplicationSettingsException { + return getSetting("credential.store.keystore.password"); + } + + public static String getCredentialStoreThriftServerKeyStorePassword() throws ApplicationSettingsException { + return getSetting("credential.store.thrift.server.keystore.password"); + } + + public static String getCredentialStoreServerHost() throws ApplicationSettingsException { + return getSetting("credential.store.server.host"); + } + + public static String getCredentialStoreServerPort() throws ApplicationSettingsException { + return getSetting("credential.store.server.port"); + } + public static String getCredentialStoreNotifierEnabled() throws ApplicationSettingsException { + return getSetting("notifier.enabled"); + } + + public static String getCredentialStoreNotifierDuration() throws ApplicationSettingsException { + return getSetting("notifier.duration"); + } + + public static String getCredentialStoreEmailServer() throws ApplicationSettingsException { + return getSetting("email.server"); + } + + public static String getCredentialStoreEmailServerPort() throws ApplicationSettingsException { + return getSetting("email.server.port"); + } + + public static String getCredentialStoreEmailUser() throws ApplicationSettingsException { + return getSetting("email.user"); + } + + public static String getCredentialStoreEmailPassword() throws ApplicationSettingsException { + return getSetting("email.password"); + } + + public static String getCredentialStoreEmailSSLConnect() throws ApplicationSettingsException { + return getSetting("email.ssl"); + } + + public static String getCredentialStoreEmailFromEmail() throws ApplicationSettingsException { + return getSetting("email.from"); + } + + /** + * @deprecated use {{@link #getSetting(String)}} + * @return + * @throws ApplicationSettingsException + */ + public static Properties getProperties() throws ApplicationSettingsException { + return getInstance().properties; + } + + public static void mergeSettings(Map props) { + getInstance().mergeSettingsImpl(props); + } + + public static void mergeSettings(InputStream stream) throws IOException{ + getInstance().mergeSettingsImpl(stream); + } + + public static void mergeSettingsCommandLineArgs(String[] args){ + getInstance().mergeSettingsCommandLineArgsImpl(args); + } + + public static ShutdownStrategy getShutdownStrategy() throws Exception{ + return getInstance().getShutdownStrategyImpl(); + } +} http://git-wip-us.apache.org/repos/asf/airavata/blob/8d16d0ec/modules/commons/src/main/java/org/apache/airavata/common/utils/BrowserLauncher.java ---------------------------------------------------------------------- diff --git a/modules/commons/src/main/java/org/apache/airavata/common/utils/BrowserLauncher.java b/modules/commons/src/main/java/org/apache/airavata/common/utils/BrowserLauncher.java new file mode 100644 index 0000000..8946aa3 --- /dev/null +++ b/modules/commons/src/main/java/org/apache/airavata/common/utils/BrowserLauncher.java @@ -0,0 +1,98 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + */ + +package org.apache.airavata.common.utils; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; + +import org.apache.airavata.common.exception.UtilsException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Opens URLs with the OS-specific browser. + */ +public class BrowserLauncher { + + private static final String ERROR_MESSAGE = "Error while attempting to launch web browser"; + + private static Logger logger = LoggerFactory.getLogger(BrowserLauncher.class); + + /** + * Opens a specified URL with the browser. + * + * @param url + * The specified URL. + * @throws UtilsException + */ + public static void openURL(URL url) throws UtilsException { + openURL(url.toString()); + } + + /** + * Opens a specified URL with the browser. + * + * @param url + * The specified URL. + * @throws UtilsException + */ + public static void openURL(String url) throws UtilsException { + logger.debug("Enter:" + url); + String osName = System.getProperty("os.name"); + try { + if (osName.startsWith("Mac OS")) { + Class macUtils = Class.forName("com.apple.mrj.MRJFileUtils"); + Method openURL = macUtils.getDeclaredMethod("openURL", new Class[] { String.class }); + openURL.invoke(null, new Object[] { url }); + } else if (osName.startsWith("Windows")) + Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + url); + else { // assume Unix or Linux + String[] browsers = { "firefox", "mozilla", "netscape", "opera", "konqueror" }; + String browser = null; + for (int count = 0; count < browsers.length && browser == null; count++) + if (Runtime.getRuntime().exec(new String[] { "which", browsers[count] }).waitFor() == 0) + browser = browsers[count]; + if (browser == null) { + throw new UtilsException("Could not find web browser."); + } else { + Runtime.getRuntime().exec(new String[] { browser, url }); + } + } + } catch (ClassNotFoundException e) { + throw new UtilsException(ERROR_MESSAGE, e); + } catch (NoSuchMethodException e) { + throw new UtilsException(ERROR_MESSAGE, e); + } catch (IllegalAccessException e) { + throw new UtilsException(ERROR_MESSAGE, e); + } catch (InvocationTargetException e) { + throw new UtilsException(ERROR_MESSAGE, e); + } catch (IOException e) { + throw new UtilsException(ERROR_MESSAGE, e); + } catch (InterruptedException e) { + throw new UtilsException(ERROR_MESSAGE, e); + } catch (RuntimeException e) { + throw new UtilsException(ERROR_MESSAGE, e); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/airavata/blob/8d16d0ec/modules/commons/src/main/java/org/apache/airavata/common/utils/ClientSettings.java ---------------------------------------------------------------------- diff --git a/modules/commons/src/main/java/org/apache/airavata/common/utils/ClientSettings.java b/modules/commons/src/main/java/org/apache/airavata/common/utils/ClientSettings.java new file mode 100644 index 0000000..5373772 --- /dev/null +++ b/modules/commons/src/main/java/org/apache/airavata/common/utils/ClientSettings.java @@ -0,0 +1,27 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + */ + +package org.apache.airavata.common.utils; + + +public class ClientSettings extends ApplicationSettings { + +} http://git-wip-us.apache.org/repos/asf/airavata/blob/8d16d0ec/modules/commons/src/main/java/org/apache/airavata/common/utils/Constants.java ---------------------------------------------------------------------- diff --git a/modules/commons/src/main/java/org/apache/airavata/common/utils/Constants.java b/modules/commons/src/main/java/org/apache/airavata/common/utils/Constants.java new file mode 100644 index 0000000..6855a8e --- /dev/null +++ b/modules/commons/src/main/java/org/apache/airavata/common/utils/Constants.java @@ -0,0 +1,66 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + */ + +package org.apache.airavata.common.utils; + +/** + * Constants used in Airavata should go here. + */ +public final class Constants { + + public static final String USER_IN_SESSION = "userName"; +// public static final String GATEWAY_NAME = "gateway_id"; + public static final String GFAC_CONFIG_XML = "gfac-config.xml"; + public static final String PUSH = "push"; + public static final String PULL = "pull"; + public static final String API_SERVER_PORT = "apiserver.server.port"; + public static final String API_SERVER_HOST = "apiserver.server.host"; + public static final String REGISTRY_JDBC_URL = "registry.jdbc.url"; + public static final String APPCATALOG_JDBC_URL = "appcatalog.jdbc.url"; + public static final String RABBITMQ_BROKER_URL = "rabbitmq.broker.url"; + public static final String RABBITMQ_EXCHANGE = "rabbitmq.exchange.name"; + public static final String ORCHESTRATOR_SERVER_HOST = "orchestrator.server.host"; + public static final String ORCHESTRATOR_SERVER_PORT = "orchestrator.server.port"; + public static final String GFAC_SERVER_HOST = "gfac.server.host"; + public static final String GFAC_SERVER_PORT = "gfac.server.port"; + public static final String CREDENTIAL_SERVER_HOST = "credential.store.server.host"; + public static final String CREDENTIAL_SERVER_PORT = "credential.store.server.port"; + public static final String ZOOKEEPER_EXPERIMENT_CATALOG = "experiment-catalog"; + public static final String ZOOKEEPER_APPCATALOG = "app-catalog"; + public static final String ZOOKEEPER_RABBITMQ = "rabbit-mq"; + public static final String ZOOKEEPER_SERVER_HOST = "zookeeper.server.host"; + public static final String ZOOKEEPER_SERVER_PORT = "zookeeper.server.port"; + public static final String ZOOKEEPER_API_SERVER_NODE = "airavata-server"; + public static final String ZOOKEEPER_ORCHESTRATOR_SERVER_NODE = "orchestrator-server"; + public static final String ZOOKEEPER_GFAC_SERVER_NODE = "gfac-server"; + public static final String ZOOKEEPER_GFAC_EXPERIMENT_NODE = "gfac-experiments"; + public static final String ZOOKEEPER_GFAC_SERVER_NAME = "gfac-server-name"; + public static final String ZOOKEEPER_ORCHESTRATOR_SERVER_NAME = "orchestrator-server-name"; + public static final String ZOOKEEPER_API_SERVER_NAME = "api-server-name"; + public static final String STAT = "stat"; + public static final String JOB = "job"; + public static final String ZOOKEEPER_TIMEOUT = "zookeeper.timeout"; + //API security relates property names + public static final String IS_API_SECURED = "api.secured"; + public static final String REMOTE_OAUTH_SERVER_URL = "remote.oauth.authorization.server"; + public static final String ADMIN_USERNAME = "admin.user.name"; + public static final String ADMIN_PASSWORD = "admin.password"; +} http://git-wip-us.apache.org/repos/asf/airavata/blob/8d16d0ec/modules/commons/src/main/java/org/apache/airavata/common/utils/DBUtil.java ---------------------------------------------------------------------- diff --git a/modules/commons/src/main/java/org/apache/airavata/common/utils/DBUtil.java b/modules/commons/src/main/java/org/apache/airavata/common/utils/DBUtil.java new file mode 100644 index 0000000..bb2ff1d --- /dev/null +++ b/modules/commons/src/main/java/org/apache/airavata/common/utils/DBUtil.java @@ -0,0 +1,334 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + */ + +package org.apache.airavata.common.utils; + +import org.apache.airavata.common.exception.ApplicationSettingsException; +import org.apache.commons.dbcp.BasicDataSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.sql.DataSource; +import java.sql.*; +import java.util.Properties; + +/** + * Database lookup. Abstracts out JDBC operations. + */ +public class DBUtil { + + private String jdbcUrl; + private String databaseUserName; + private String databasePassword; + private String driverName; + + protected static Logger log = LoggerFactory.getLogger(DBUtil.class); + + private Properties properties; + + public DBUtil(String jdbcUrl, String userName, String password, String driver) throws InstantiationException, + IllegalAccessException, ClassNotFoundException { + + this.jdbcUrl = jdbcUrl; + this.databaseUserName = userName; + this.databasePassword = password; + this.driverName = driver; + + init(); + } + + /** + * Initializes and load driver. Must be called this before calling anyother method. + * + * @throws ClassNotFoundException + * If DB driver is not found. + * @throws InstantiationException + * If unable to create driver class. + * @throws IllegalAccessException + * If security does not allow users to instantiate driver object. + */ + private void init() throws ClassNotFoundException, InstantiationException, IllegalAccessException { + properties = new Properties(); + + properties.put("user", databaseUserName); + properties.put("password", databasePassword); + properties.put("characterEncoding", "ISO-8859-1"); + properties.put("useUnicode", "true"); + + loadDriver(); + } + + /** + * Generic method to query values in the database. + * + * @param tableName + * Table name to query + * @param selectColumn + * The column selecting + * @param whereValue + * The condition query + * @return The value appropriate to the query. + * @throws SQLException + * If an error occurred while querying + */ + public String getMatchingColumnValue(String tableName, String selectColumn, String whereValue) throws SQLException { + return getMatchingColumnValue(tableName, selectColumn, selectColumn, whereValue); + } + + /** + * Generic method to query values in the database. + * + * @param tableName + * Table name to query + * @param selectColumn + * The column selecting + * @param whereColumn + * The column which condition should apply + * @param whereValue + * The condition query + * @return The value appropriate to the query. + * @throws SQLException + * If an error occurred while querying + */ + public String getMatchingColumnValue(String tableName, String selectColumn, String whereColumn, String whereValue) + throws SQLException { + + StringBuilder stringBuilder = new StringBuilder(); + + stringBuilder.append("SELECT ").append(selectColumn).append(" FROM ").append(tableName).append(" WHERE ") + .append(whereColumn).append(" = ?"); + + String sql = stringBuilder.toString(); + + Connection connection = getConnection(); + + PreparedStatement ps = connection.prepareStatement(sql); + ResultSet rs = null; + + try { + ps.setString(1, whereValue); + rs = ps.executeQuery(); + + if (rs.next()) { + return rs.getString(1); + } + + } finally { + try { + if (rs != null) { + rs.close(); + } + + ps.close(); + connection.close(); + + } catch (Exception ignore) { + log.error("An error occurred while closing database connections ", ignore); + } + } + + return null; + } + + /** + * Create table utility method. + * + * @param sql + * SQL to be executed. + * @throws SQLException + * If an error occurred while creating the table. + */ + public void executeSQL(String sql) throws SQLException { + + Connection connection = getConnection(); + + PreparedStatement ps = connection.prepareStatement(sql); + + try { + ps.executeUpdate(); + connection.commit(); + } finally { + try { + if (ps != null) { + ps.close(); + } + + connection.close(); + + } catch (Exception ignore) { + log.error("An error occurred while closing database connections ", ignore); + } + } + + } + + private void loadDriver() throws ClassNotFoundException, IllegalAccessException, InstantiationException { + Class.forName(driverName).newInstance(); + } + + /** + * Gets a new DBCP data source. + * + * @return A new data source. + */ + public DataSource getDataSource() { + BasicDataSource ds = new BasicDataSource(); + ds.setDriverClassName(this.driverName); + ds.setUsername(this.databaseUserName); + ds.setPassword(this.databasePassword); + ds.setUrl(this.jdbcUrl); + + return ds; + } + + /** + * Creates a new JDBC connections based on provided DBCP properties. + * + * @return A new DB connection. + * @throws SQLException + * If an error occurred while creating the connection. + */ + public Connection getConnection() throws SQLException { + Connection connection = DriverManager.getConnection(jdbcUrl, properties); + connection.setAutoCommit(false); + return connection; + } + + /** + * Utility method to close statements and connections. + * + * @param preparedStatement + * The prepared statement to close. + * @param connection + * The connection to close. + */ + public static void cleanup(PreparedStatement preparedStatement, Connection connection) { + if (preparedStatement != null) { + try { + preparedStatement.close(); + } catch (SQLException e) { + log.error("Error closing prepared statement.", e); + } + } + if (connection != null) { + try { + connection.close(); + } catch (SQLException e) { + log.error("Error closing database connection.", e); + } + } + } + + /** + * Utility method to close statements and connections. + * + * @param preparedStatement + * The prepared statement to close. + */ + public static void cleanup(PreparedStatement preparedStatement) { + if (preparedStatement != null) { + try { + preparedStatement.close(); + } catch (SQLException e) { + log.error("Error closing prepared statement.", e); + } + } + } + + /** + * Utility method to close statements and connections. + * + * @param preparedStatement + * The prepared statement to close. + */ + public static void cleanup(PreparedStatement preparedStatement, ResultSet resultSet) { + if (resultSet != null) { + try { + resultSet.close(); + } catch (SQLException e) { + log.error("Error closing prepared statement.", e); + } + } + + cleanup(preparedStatement); + } + + /** + * Cleanup the connection. + * @param connection The connection to close. + */ + public static void cleanup(Connection connection) { + if (connection != null) { + try { + connection.close(); + } catch (SQLException e) { + log.debug("Error closing connection.", e); + log.warn("Error closing connection."); + } + } + } + + /** + * Mainly useful for tests. + * + * @param tableName + * The table name. + * @param connection + * The connection to be used. + */ + public static void truncate(String tableName, Connection connection) throws SQLException { + + String sql = "delete from " + tableName; + + PreparedStatement preparedStatement = connection.prepareStatement(sql); + preparedStatement.executeUpdate(); + + connection.commit(); + + } + + /** + * Creates a DBUtil object based on servlet context configurations. + * + * @return DBUtil object. + * @throws Exception + * If an error occurred while reading configurations or while creating database object. + */ + public static DBUtil getCredentialStoreDBUtil() throws ApplicationSettingsException, IllegalAccessException, + ClassNotFoundException, InstantiationException { + String jdbcUrl = ServerSettings.getCredentialStoreDBURL(); + String userName = ServerSettings.getCredentialStoreDBUser(); + String password = ServerSettings.getCredentialStoreDBPassword(); + String driverName = ServerSettings.getCredentialStoreDBDriver(); + + StringBuilder stringBuilder = new StringBuilder("Starting credential store, connecting to database - "); + stringBuilder.append(jdbcUrl).append(" DB user - ").append(userName).append(" driver name - ") + .append(driverName); + + log.debug(stringBuilder.toString()); + + DBUtil dbUtil = new DBUtil(jdbcUrl, userName, password, driverName); + dbUtil.init(); + + return dbUtil; + } + +} http://git-wip-us.apache.org/repos/asf/airavata/blob/8d16d0ec/modules/commons/src/main/java/org/apache/airavata/common/utils/DatabaseTestCases.java ---------------------------------------------------------------------- diff --git a/modules/commons/src/main/java/org/apache/airavata/common/utils/DatabaseTestCases.java b/modules/commons/src/main/java/org/apache/airavata/common/utils/DatabaseTestCases.java new file mode 100644 index 0000000..6ff528d --- /dev/null +++ b/modules/commons/src/main/java/org/apache/airavata/common/utils/DatabaseTestCases.java @@ -0,0 +1,123 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + */ + +package org.apache.airavata.common.utils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.Connection; +import java.sql.SQLException; + +/** + * An abstraction for database specific test classes. This will create a database and provides methods to execute SQLs. + */ +public class DatabaseTestCases { + + private static final Logger logger = LoggerFactory.getLogger(DatabaseTestCases.class); + + protected static String hostAddress = "localhost"; + protected static int port = 20000; + protected static String userName = "admin"; + protected static String password = "admin"; + protected static String driver = "org.apache.derby.jdbc.ClientDriver"; + + public static String getHostAddress() { + return hostAddress; + } + + public static int getPort() { + return port; + } + + public static String getUserName() { + return userName; + } + + public static String getPassword() { + return password; + } + + public static String getDriver() { + return driver; + } + + public static String getJDBCUrl() { + return new StringBuilder().append("jdbc:derby://").append(getHostAddress()).append(":").append(getPort()) + .append("/experiment_catalog;create=true;user=").append(getUserName()).append(";password=") + .append(getPassword()).toString(); + } + + public static void waitTillServerStarts() { + DBUtil dbUtil = null; + + try { + dbUtil = new DBUtil(getJDBCUrl(), getUserName(), getPassword(), getDriver()); + } catch (Exception e) { + // ignore + } + + Connection connection = null; + try { + if (dbUtil != null) { + connection = dbUtil.getConnection(); + } + } catch (Throwable e) { + // ignore + } + + while (connection == null) { + try { + Thread.sleep(1000); + try { + if (dbUtil != null) { + connection = dbUtil.getConnection(); + } + } catch (SQLException e) { + // ignore + } + } catch (InterruptedException e) { + // ignore + } + } + + } + + public static void executeSQL(String sql) throws Exception { + DBUtil dbUtil = new DBUtil(getJDBCUrl(), getUserName(), getPassword(), getDriver()); + dbUtil.executeSQL(sql); + } + + public DBUtil getDbUtil () throws Exception { + return new DBUtil(getJDBCUrl(), getUserName(), getPassword(), getDriver()); + + } + + public Connection getConnection() throws Exception { + + DBUtil dbUtil = getDbUtil (); + Connection connection = dbUtil.getConnection(); + connection.setAutoCommit(true); + return connection; + + } + +} http://git-wip-us.apache.org/repos/asf/airavata/blob/8d16d0ec/modules/commons/src/main/java/org/apache/airavata/common/utils/DefaultKeyStorePasswordCallback.java ---------------------------------------------------------------------- diff --git a/modules/commons/src/main/java/org/apache/airavata/common/utils/DefaultKeyStorePasswordCallback.java b/modules/commons/src/main/java/org/apache/airavata/common/utils/DefaultKeyStorePasswordCallback.java new file mode 100644 index 0000000..fc7792b --- /dev/null +++ b/modules/commons/src/main/java/org/apache/airavata/common/utils/DefaultKeyStorePasswordCallback.java @@ -0,0 +1,55 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + */ + +package org.apache.airavata.common.utils; + +import org.apache.airavata.common.exception.ApplicationSettingsException; + +/** + * User: AmilaJ (amilaj@apache.org) + * Date: 12/29/13 + * Time: 12:10 PM + */ + +public class DefaultKeyStorePasswordCallback implements KeyStorePasswordCallback { + + public DefaultKeyStorePasswordCallback(){ + + } + + @Override + public char[] getStorePassword() { + try { + return ApplicationSettings.getCredentialStoreKeyStorePassword().toCharArray(); + } catch (ApplicationSettingsException e) { + throw new RuntimeException(e); + } + } + + @Override + public char[] getSecretKeyPassPhrase(String keyAlias) { + try { + return ApplicationSettings.getCredentialStoreKeyStorePassword().toCharArray(); + } catch (ApplicationSettingsException e) { + throw new RuntimeException(e); + } + } +} http://git-wip-us.apache.org/repos/asf/airavata/blob/8d16d0ec/modules/commons/src/main/java/org/apache/airavata/common/utils/DerbyUtil.java ---------------------------------------------------------------------- diff --git a/modules/commons/src/main/java/org/apache/airavata/common/utils/DerbyUtil.java b/modules/commons/src/main/java/org/apache/airavata/common/utils/DerbyUtil.java new file mode 100644 index 0000000..4fb35b9 --- /dev/null +++ b/modules/commons/src/main/java/org/apache/airavata/common/utils/DerbyUtil.java @@ -0,0 +1,114 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + */ + +package org.apache.airavata.common.utils; + +import java.io.IOException; +import java.io.PrintWriter; +import java.net.InetAddress; +import java.sql.DriverManager; +import org.apache.derby.drda.NetworkServerControl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.SQLException; + +/** + * This class includes methods to start stop Derby database. Mainly user for tests. + */ +public class DerbyUtil { + + private static NetworkServerControl server; + + private static final Logger logger = LoggerFactory.getLogger(DerbyUtil.class); + + public static final String DERBY_SERVER_MODE_SYS_PROPERTY = "derby.drda.startNetworkServer"; + + /** + * Starts new derby server instance with given configurations. + * + * @param hostAddress + * The host address start the server. + * @param port + * The port number which server is starting. + * @param user + * JDBC user name. + * @param password + * JDBC password. + * @throws Exception + * If an error occurred while starting the server. + */ + public static void startDerbyInServerMode(String hostAddress, int port, String user, String password) + throws Exception { + PrintWriter consoleWriter = null; + + try { + System.setProperty(DERBY_SERVER_MODE_SYS_PROPERTY, "true"); + server = new NetworkServerControl(InetAddress.getByName(hostAddress), port, user, password); + consoleWriter = new PrintWriter(System.out, true); + server.start(consoleWriter); + + } catch (IOException e) { + logger.error("Unable to start Apache derby in the server mode! Check whether " + + "specified port is available", e); + throw e; + } catch (Exception e) { + logger.error("Unable to start Apache derby in the server mode! Check whether " + + "specified port is available", e); + throw e; + } finally { + + if (consoleWriter != null) { + consoleWriter.close(); + } + + } + + } + + /** + * Starts derby server in embedded mode. + * + * @throws ClassNotFoundException + * If specified driver not found in the class path. + * @throws SQLException + * If an error occurred while creat + */ + public static void startDerbyInEmbeddedMode() throws ClassNotFoundException, SQLException { + Class.forName("org.apache.derby.jdbc.EmbeddedDriver"); + DriverManager.getConnection("jdbc:derby:memory:unit-testing-jpa;create=true").close(); + } + + /** + * Shuts down the server. + * + * @throws Exception + * If an error occurred while shutting down. + */ + public static void stopDerbyServer() throws Exception { + try { + server.shutdown(); + } catch (Exception e) { + logger.error("Error shutting down derby server.", e); + throw e; + } + } +} http://git-wip-us.apache.org/repos/asf/airavata/blob/8d16d0ec/modules/commons/src/main/java/org/apache/airavata/common/utils/ExecutionMode.java ---------------------------------------------------------------------- diff --git a/modules/commons/src/main/java/org/apache/airavata/common/utils/ExecutionMode.java b/modules/commons/src/main/java/org/apache/airavata/common/utils/ExecutionMode.java new file mode 100644 index 0000000..cf17ef0 --- /dev/null +++ b/modules/commons/src/main/java/org/apache/airavata/common/utils/ExecutionMode.java @@ -0,0 +1,28 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + */ + +package org.apache.airavata.common.utils; + +public enum ExecutionMode { + CLIENT, + SERVER, + UNKNOWN +} http://git-wip-us.apache.org/repos/asf/airavata/blob/8d16d0ec/modules/commons/src/main/java/org/apache/airavata/common/utils/IOUtil.java ---------------------------------------------------------------------- diff --git a/modules/commons/src/main/java/org/apache/airavata/common/utils/IOUtil.java b/modules/commons/src/main/java/org/apache/airavata/common/utils/IOUtil.java new file mode 100644 index 0000000..9d1d7dd --- /dev/null +++ b/modules/commons/src/main/java/org/apache/airavata/common/utils/IOUtil.java @@ -0,0 +1,209 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + */ + +package org.apache.airavata.common.utils; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.Writer; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class IOUtil { + + private static final Logger logger = LoggerFactory.getLogger(IOUtil.class); + + /** + * @param path + * @param content + * @throws IOException + */ + public static void writeToFile(String content, String path) throws IOException { + logger.debug("Path:" + path + " Content:" + content); + + FileWriter fw = new FileWriter(path); + writeToWriter(content, fw); + } + + /** + * @param content + * @param file + * @throws IOException + */ + public static void writeToFile(String content, File file) throws IOException { + FileWriter fw = new FileWriter(file); + writeToWriter(content, fw); + } + + /** + * @param inputStream + * @param file + * @throws IOException + */ + public static void writeToFile(InputStream inputStream, File file) throws IOException { + FileOutputStream outputStream = new FileOutputStream(file); + byte[] bytes = new byte[1024]; + int len; + while ((len = inputStream.read(bytes)) != -1) { + outputStream.write(bytes, 0, len); + } + outputStream.close(); + } + + /** + * Writes a specified String to a specified Writer. + * + * @param content + * The content to write + * @param writer + * The specified Writer + * + * @throws IOException + */ + public static void writeToWriter(String content, Writer writer) throws IOException { + writer.write(content); + writer.close(); + } + + /** + * Returns the content of a specified file as a String. + * + * @param path + * @return the content of a specified file as a String + * @throws IOException + */ + public static String readFileToString(String path) throws IOException { + FileReader read = new FileReader(path); + return readToString(read); + } + + /** + * Returns the content of a specified file as a String. + * + * @param file + * @return the content of a specified file as a String + * @throws IOException + */ + public static String readFileToString(File file) throws IOException { + FileReader reader = new FileReader(file); + return readToString(reader); + } + + /** + * Returns a String read from a specified InputStream. + * + * @param stream + * The specified InputStream + * @return The String read from the specified InputStream + * @throws IOException + */ + public static String readToString(InputStream stream) throws IOException { + return readToString(new InputStreamReader(stream)); + } + + /** + * Returns a String read from a specified Reader. + * + * @param reader + * The specified Reader + * @return The String read from the specified Reader + * @throws IOException + */ + public static String readToString(Reader reader) throws IOException { + char[] cbuf = new char[1024]; + StringBuilder sbuf = new StringBuilder(); + int len; + while ((len = reader.read(cbuf)) != -1) { + sbuf.append(cbuf, 0, len); + } + return sbuf.toString(); + } + + /** + * @param file + * @return The byte array + * @throws IOException + */ + public static byte[] readToByteArray(File file) throws IOException { + return readToByteArray(new FileInputStream(file)); + } + + /** + * @param inputStream + * @return The byte array. + * @throws IOException + */ + public static byte[] readToByteArray(InputStream inputStream) throws IOException { + byte[] buf = new byte[1024]; + ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream(); + int len; + while ((len = inputStream.read(buf)) != -1) { + byteArrayStream.write(buf, 0, len); + } + return byteArrayStream.toByteArray(); + } + + /** + * @param path + * @return true if and only if the file or directory is successfully deleted; false + * otherwise + */ + public static boolean deleteDirectory(File path) { + if (path.exists()) { + File[] files = path.listFiles(); + for (File file : files) { + if (file.isDirectory()) { + deleteDirectory(file); + } else { + file.delete(); + } + } + } + return path.delete(); + } + + /** + * Gets the extension of a specified file. + * + * @param file + * the specified file. + * @return the extension of the file in lower case if there is an extension; null otherwise + */ + public static String getExtension(File file) { + String ext = null; + String name = file.getName(); + + int index = name.lastIndexOf('.'); + if (index > 0 && index < name.length() - 1) { + ext = name.substring(index + 1).toLowerCase(); + } + return ext; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/airavata/blob/8d16d0ec/modules/commons/src/main/java/org/apache/airavata/common/utils/IServer.java ---------------------------------------------------------------------- diff --git a/modules/commons/src/main/java/org/apache/airavata/common/utils/IServer.java b/modules/commons/src/main/java/org/apache/airavata/common/utils/IServer.java new file mode 100644 index 0000000..867eb45 --- /dev/null +++ b/modules/commons/src/main/java/org/apache/airavata/common/utils/IServer.java @@ -0,0 +1,51 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + */ + +package org.apache.airavata.common.utils; + +import java.util.Calendar; +import java.util.Date; + +public interface IServer { + public enum ServerStatus{ + STOPING, + STOPPED, + STARTING, + STARTED, + FAILED; + public void updateTime(){ + now=Calendar.getInstance().getTime(); + } + private Date now; + public Date getTime(){ + return now; + } + } + public String getName(); + public String getVersion(); + public void start() throws Exception; + public void stop() throws Exception; + public void restart() throws Exception; + public void configure() throws Exception; + public ServerStatus getStatus() throws Exception; +// public void waitForServerToStart() throws Exception; +// public void waitForServerToStop() throws Exception; +} http://git-wip-us.apache.org/repos/asf/airavata/blob/8d16d0ec/modules/commons/src/main/java/org/apache/airavata/common/utils/JSONUtil.java ---------------------------------------------------------------------- diff --git a/modules/commons/src/main/java/org/apache/airavata/common/utils/JSONUtil.java b/modules/commons/src/main/java/org/apache/airavata/common/utils/JSONUtil.java new file mode 100644 index 0000000..222e5a2 --- /dev/null +++ b/modules/commons/src/main/java/org/apache/airavata/common/utils/JSONUtil.java @@ -0,0 +1,158 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + */ + +package org.apache.airavata.common.utils; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; +import com.google.gson.stream.JsonReader; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; +import java.util.Map; +import java.util.Set; + +public class JSONUtil { + + + public static void saveJSON(JsonElement jsonElement, File file) throws IOException { + IOUtil.writeToFile(jsonElementToString(jsonElement), file); + } + + public static JsonObject stringToJSONObject(String workflowString) { + JsonParser parser = new JsonParser(); + return (JsonObject) parser.parse(workflowString); + } + + public static JsonObject loadJSON(File file) throws IOException { + return loadJSON(new FileReader(file)); + } + + public static JsonObject loadJSON(Reader reader) throws IOException { + JsonParser parser = new JsonParser(); + JsonElement jsonElement = parser.parse(reader); + if (jsonElement instanceof JsonObject) { + return (JsonObject) jsonElement; + } else { + throw new RuntimeException("Error while loading Json from file"); + } + + } + + public static String jsonElementToString(JsonElement jsonElement) { + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + return gson.toJson(jsonElement); + } + + public static boolean isEqual(JsonObject originalJsonObject, JsonObject newJsonObject) { + // TODO - Implement this method + if (originalJsonObject == null && newJsonObject == null) { + return true; + }else if (originalJsonObject == null || newJsonObject == null) { + return false; + } else { + // check the number of childs + Set> entrySetOfOriginalJson = originalJsonObject.entrySet(); + Set> entrySetOfNewJson = newJsonObject.entrySet(); + if (entrySetOfOriginalJson.size() != entrySetOfNewJson.size()) { + return false; + } + + for (Map.Entry keyString : entrySetOfOriginalJson) { + JsonElement valueOrig = keyString.getValue(); + JsonElement valueNew = newJsonObject.get(keyString.getKey()); + if (valueOrig instanceof JsonObject && valueNew instanceof JsonObject && + !isEqual((JsonObject) valueOrig, (JsonObject) valueNew)) { + return false; + }else if (valueOrig instanceof JsonArray && valueNew instanceof JsonArray && + !isEqual((JsonArray) valueOrig, (JsonArray) valueNew)) { + return false; + }else if (valueOrig instanceof JsonPrimitive && valueNew instanceof JsonPrimitive && + !isEqual((JsonPrimitive) valueOrig, (JsonPrimitive) valueNew)) { + return false; + } + } + } + return true; + } + + private static boolean isEqual(JsonArray arrayOriginal, JsonArray arrayNew) { + if (arrayOriginal == null && arrayNew == null) { + return true; + }else if (arrayOriginal == null || arrayNew == null) { + return false; + }else { + // check the number of element + if (arrayOriginal.size() != arrayNew.size()) { + return false; + }else if (arrayOriginal.size() == 0) { + return true; + } else { + for (int i = 0; i < arrayOriginal.size(); i++) { + JsonElement valueOrig = arrayOriginal.get(i); + JsonElement valueNew = arrayNew.get(i); + if (valueOrig instanceof JsonObject && valueNew instanceof JsonObject) { + if (!isEqual((JsonObject) valueOrig, (JsonObject) valueNew)) { + return false; + } + }else if (valueOrig instanceof JsonPrimitive && valueNew instanceof JsonPrimitive) { + if (!isEqual((JsonPrimitive) valueOrig, (JsonPrimitive) valueNew)) { + return false; + } + } + } + } + } + return true; + } + + private static boolean isEqual(JsonPrimitive primitiveOrig, JsonPrimitive primitiveNew) { + if (primitiveOrig == null && primitiveNew == null) { + return true; + }else if (primitiveOrig == null || primitiveNew == null) { + return false; + } else { + if (primitiveOrig.isString() && primitiveNew.isString()){ + if(!primitiveOrig.getAsString().equals(primitiveNew.getAsString())) { + return false; + } + }else if (primitiveOrig.isBoolean() && primitiveNew.isBoolean()) { + if ((Boolean.valueOf(primitiveOrig.getAsBoolean()).compareTo(primitiveNew.getAsBoolean()) != 0)) { + return false; + } + }else if (primitiveOrig.isNumber() && primitiveNew.isNumber() ) { + if (new Double(primitiveOrig.getAsDouble()).compareTo(primitiveNew.getAsDouble()) != 0) { + return false; + } + }else { + return primitiveOrig.isJsonNull() && primitiveNew.isJsonNull(); + } + } + return true; + } +} http://git-wip-us.apache.org/repos/asf/airavata/blob/8d16d0ec/modules/commons/src/main/java/org/apache/airavata/common/utils/KeyStorePasswordCallback.java ---------------------------------------------------------------------- diff --git a/modules/commons/src/main/java/org/apache/airavata/common/utils/KeyStorePasswordCallback.java b/modules/commons/src/main/java/org/apache/airavata/common/utils/KeyStorePasswordCallback.java new file mode 100644 index 0000000..bafaff3 --- /dev/null +++ b/modules/commons/src/main/java/org/apache/airavata/common/utils/KeyStorePasswordCallback.java @@ -0,0 +1,50 @@ +package org.apache.airavata.common.utils;/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + */ + +/** + * User: AmilaJ (amilaj@apache.org) + * Date: 10/11/13 + * Time: 11:30 AM + */ + +/** + * An interface to get keystore password in a form of a callback. + */ +public interface KeyStorePasswordCallback { + + /** + * Caller should implement the interface. Should return the password for + * the keystore. This should return the keystore password. i.e. password used to open the keystore. + * Instead of the actual file. + * @return The password to open the keystore. + */ + char[] getStorePassword() throws RuntimeException; + + /** + * Caller should implement the interface. Should return the pass phrase for + * the secret key. + * Instead of the actual file. + * @param keyAlias The alias of the key + * @return The pass phrase for the secret key. + */ + char[] getSecretKeyPassPhrase(String keyAlias); + +} http://git-wip-us.apache.org/repos/asf/airavata/blob/8d16d0ec/modules/commons/src/main/java/org/apache/airavata/common/utils/MonitorPublisher.java ---------------------------------------------------------------------- diff --git a/modules/commons/src/main/java/org/apache/airavata/common/utils/MonitorPublisher.java b/modules/commons/src/main/java/org/apache/airavata/common/utils/MonitorPublisher.java new file mode 100644 index 0000000..7f64e86 --- /dev/null +++ b/modules/commons/src/main/java/org/apache/airavata/common/utils/MonitorPublisher.java @@ -0,0 +1,47 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * +*/ +package org.apache.airavata.common.utils; + +import com.google.common.eventbus.EventBus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MonitorPublisher{ + private final static Logger logger = LoggerFactory.getLogger(MonitorPublisher.class); + private EventBus eventBus; + + public MonitorPublisher(EventBus eventBus) { + this.eventBus = eventBus; + } + + public void registerListener(Object listener) { + eventBus.register(listener); + } + + public void unregisterListener(Object listener) { + eventBus.unregister(listener); + } + + public void publish(Object o) { + eventBus.post(o); + } + +} http://git-wip-us.apache.org/repos/asf/airavata/blob/8d16d0ec/modules/commons/src/main/java/org/apache/airavata/common/utils/NameValidator.java ---------------------------------------------------------------------- diff --git a/modules/commons/src/main/java/org/apache/airavata/common/utils/NameValidator.java b/modules/commons/src/main/java/org/apache/airavata/common/utils/NameValidator.java new file mode 100644 index 0000000..98530cf --- /dev/null +++ b/modules/commons/src/main/java/org/apache/airavata/common/utils/NameValidator.java @@ -0,0 +1,70 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + */ + +package org.apache.airavata.common.utils; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class NameValidator { + + /** + * @param name + * @return Is it valid name? + */ + public static boolean validate(String name) { + // Set the name pattern string + Pattern p = Pattern.compile("([a-zA-Z]){1,}([0-9]|_|\\.|[a-zA-Z]){0,}$"); + + // Match the given string with the pattern + Matcher m = p.matcher(name); + + // Check whether match is found + boolean matchFound = m.matches(); + + return matchFound; + } + + /** + * @param args + * @Description some quick tests + */ + public static void main(String[] args) { + System.out.println(validate("abc90_90abc")); // true + + System.out.println(validate("abc_abc_123")); // true + + System.out.println(validate("abc_abc_")); // true + + System.out.println(validate("abc_abc")); // true + + System.out.println(validate("abc.abc")); // true + + System.out.println(validate("9abc_abc")); // false, name cannot start with number + + System.out.println(validate("_abc_abc")); // false, name cannot start with "_" + + System.out.println(validate("\\abc_abc")); // false, name cannot start with "\" + + System.out.println(validate("abc\\_abc")); // false, name cannot contain "\" + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/airavata/blob/8d16d0ec/modules/commons/src/main/java/org/apache/airavata/common/utils/Pair.java ---------------------------------------------------------------------- diff --git a/modules/commons/src/main/java/org/apache/airavata/common/utils/Pair.java b/modules/commons/src/main/java/org/apache/airavata/common/utils/Pair.java new file mode 100644 index 0000000..ee24360 --- /dev/null +++ b/modules/commons/src/main/java/org/apache/airavata/common/utils/Pair.java @@ -0,0 +1,79 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + */ + +package org.apache.airavata.common.utils; + +public class Pair { + + private L left; + + private R right; + + /** + * Constructs a Pair. + * + * @param left + * @param right + */ + public Pair(L left, R right) { + this.left = left; + this.right = right; + } + + /** + * Returns the left. + * + * @return The left + */ + public L getLeft() { + return this.left; + } + + /** + * Sets left. + * + * @param left + * The left to set. + */ + public void setLeft(L left) { + this.left = left; + } + + /** + * Returns the right. + * + * @return The right + */ + public R getRight() { + return this.right; + } + + /** + * Sets right. + * + * @param right + * The right to set. + */ + public void setRight(R right) { + this.right = right; + } + +} \ No newline at end of file