Implemented global configuration publishing mechanism.
Project: http://git-wip-us.apache.org/repos/asf/oodt/repo Commit: http://git-wip-us.apache.org/repos/asf/oodt/commit/4b88f714 Tree: http://git-wip-us.apache.org/repos/asf/oodt/tree/4b88f714 Diff: http://git-wip-us.apache.org/repos/asf/oodt/diff/4b88f714 Branch: refs/heads/master Commit: 4b88f71497263675bb313462075fd552696ba717 Parents: ac7170b Author: Imesha Sudasingha <[email protected]> Authored: Fri Jun 16 15:53:43 2017 +0530 Committer: Imesha Sudasingha <[email protected]> Committed: Fri Jun 16 15:53:43 2017 +0530 ---------------------------------------------------------------------- config/pom.xml | 26 + .../oodt/config/ConfigurationManager.java | 44 +- .../config/ConfigurationManagerFactory.java | 35 +- .../java/org/apache/oodt/config/Constants.java | 58 +- .../DistributedConfigurationManager.java | 199 +- .../DistributedConfigurationPublisher.java | 200 + .../apache/oodt/config/distributed/ZPaths.java | 67 + .../StandaloneConfigurationManager.java | 60 +- .../apache/oodt/config/utils/CuratorUtils.java | 80 + .../DistributedConfigurationPublisherTest.java | 88 + config/src/test/resources/filemgr.properties | 114 + config/src/test/resources/log4j.xml | 34 + config/src/test/resources/mime-types.xml | 4119 ++++++++++++++++++ core/pom.xml | 9 + .../cas/filemgr/system/XmlRpcFileManager.java | 6 +- 15 files changed, 4940 insertions(+), 199 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/oodt/blob/4b88f714/config/pom.xml ---------------------------------------------------------------------- diff --git a/config/pom.xml b/config/pom.xml index 64a4b03..0ab4457 100644 --- a/config/pom.xml +++ b/config/pom.xml @@ -16,9 +16,35 @@ <description>OODT project for distributed configuration management support</description> <dependencies> + <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> </dependency> + + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.curator</groupId> + <artifactId>curator-test</artifactId> + </dependency> </dependencies> </project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/oodt/blob/4b88f714/config/src/main/java/org/apache/oodt/config/ConfigurationManager.java ---------------------------------------------------------------------- diff --git a/config/src/main/java/org/apache/oodt/config/ConfigurationManager.java b/config/src/main/java/org/apache/oodt/config/ConfigurationManager.java index 05b33fd..e5dc82f 100644 --- a/config/src/main/java/org/apache/oodt/config/ConfigurationManager.java +++ b/config/src/main/java/org/apache/oodt/config/ConfigurationManager.java @@ -30,28 +30,24 @@ import java.util.List; */ public abstract class ConfigurationManager { - protected String component; - protected List<String> propertiesFiles; - protected List<String> otherFiles; - - public ConfigurationManager(String component, List<String> propertiesFiles, List<String> otherFiles) { - this.component = component; - this.propertiesFiles = propertiesFiles != null ? propertiesFiles : new ArrayList<String>(); - this.otherFiles = otherFiles != null ? otherFiles : new ArrayList<String>(); - } - - /** - * Retrieves a given property from the underlying configuration storage. For example, If we want to get the - * value of the property org.foo.bar, we have to call this method with <pre>org.foo.bar</pre> as the parameter. - * - * @param key Name of the property to be retrieved. - * @return Value of the requested property | null - */ - public abstract String getProperty(String key); - - public abstract void loadProperties() throws IOException; - - public abstract File getPropertiesFile(String filePath) throws FileNotFoundException; - - public abstract File getConfigurationFile(String filePath) throws FileNotFoundException; + protected String component; + protected List<String> propertiesFiles; + + public ConfigurationManager(String component, List<String> propertiesFiles) { + this.component = component; + this.propertiesFiles = propertiesFiles != null ? propertiesFiles : new ArrayList<String>(); + } + + /** + * Retrieves a given property from the underlying configuration storage. For example, If we want to get the + * value of the property org.foo.bar, we have to call this method with <pre>org.foo.bar</pre> as the parameter. + * + * @param key Name of the property to be retrieved. + * @return Value of the requested property | null + */ + public abstract String getProperty(String key); + + public abstract void loadProperties() throws IOException; + + public abstract File getPropertiesFile(String filePath) throws FileNotFoundException; } http://git-wip-us.apache.org/repos/asf/oodt/blob/4b88f714/config/src/main/java/org/apache/oodt/config/ConfigurationManagerFactory.java ---------------------------------------------------------------------- diff --git a/config/src/main/java/org/apache/oodt/config/ConfigurationManagerFactory.java b/config/src/main/java/org/apache/oodt/config/ConfigurationManagerFactory.java index 7c026b7..0fd995d 100644 --- a/config/src/main/java/org/apache/oodt/config/ConfigurationManagerFactory.java +++ b/config/src/main/java/org/apache/oodt/config/ConfigurationManagerFactory.java @@ -32,22 +32,23 @@ import static org.apache.oodt.config.Constants.Properties.ENABLE_DISTRIBUTED_CON */ public class ConfigurationManagerFactory { - /** Logger instance for this class */ - private static final Logger logger = Logger.getLogger(ConfigurationManagerFactory.class.getName()); - - private ConfigurationManagerFactory() {} - - /** - * Returns the {@link ConfigurationManager} to be used by the calling class. Whether to use the standalone version or - * the distributed version of the configuration manager will be determined by the value of the property - * <pre>org.apache.oodt.config.zookeeper == true</pre> - * - * @return ConfigurationManager instance to used by the corresponding component. - */ - public static ConfigurationManager getConfigurationManager(String component, List<String> propertiesFiles, List<String> otherFiles) { - if (System.getProperty(ENABLE_DISTRIBUTED_CONFIGURATION) != null) { - return new DistributedConfigurationManager(component, propertiesFiles, otherFiles); + /** Logger instance for this class */ + private static final Logger logger = Logger.getLogger(ConfigurationManagerFactory.class.getName()); + + private ConfigurationManagerFactory() { + } + + /** + * Returns the {@link ConfigurationManager} to be used by the calling class. Whether to use the standalone version or + * the distributed version of the configuration manager will be determined by the value of the property + * <pre>org.apache.oodt.config.zookeeper == true</pre> + * + * @return ConfigurationManager instance to used by the corresponding component. + */ + public static ConfigurationManager getConfigurationManager(String component, List<String> propertiesFiles) { + if (System.getProperty(ENABLE_DISTRIBUTED_CONFIGURATION) != null) { + return new DistributedConfigurationManager(component, propertiesFiles); + } + return new StandaloneConfigurationManager(component, propertiesFiles); } - return new StandaloneConfigurationManager(component, propertiesFiles, otherFiles); - } } http://git-wip-us.apache.org/repos/asf/oodt/blob/4b88f714/config/src/main/java/org/apache/oodt/config/Constants.java ---------------------------------------------------------------------- diff --git a/config/src/main/java/org/apache/oodt/config/Constants.java b/config/src/main/java/org/apache/oodt/config/Constants.java index 03c3e1c..6f74f97 100644 --- a/config/src/main/java/org/apache/oodt/config/Constants.java +++ b/config/src/main/java/org/apache/oodt/config/Constants.java @@ -24,33 +24,51 @@ package org.apache.oodt.config; */ public class Constants { - private Constants() {} + private Constants() { + } - /** Node name to be used when the configuration manager is the standalone version */ - public static final String STANDALONE_NODE_NAME = "local"; + /** Node name to be used when the configuration manager is the standalone version */ + public static final String STANDALONE_NODE_NAME = "local"; - /** Default environment name to be used */ - public static final String DEFAULT_ENVIRONMENT = "default"; + /** Default environment name to be used */ + public static final String DEFAULT_ENVIRONMENT = "default"; - public static class Properties { + public static class Properties { + /** The system property to be set in order to enable distributed configuration management */ + public static final String ENABLE_DISTRIBUTED_CONFIGURATION = "org.apache.oodt.config.distributed"; - /** The system property to be set in order to enable distributed configuration management */ - public static final String ENABLE_DISTRIBUTED_CONFIGURATION = "org.apache.oodt.config.distributed"; + /** System property, which will holf the location of the zookeeper properties file */ + public static final String ZK_PROPERTIES_FILE = "org.apache.oodt.config.zkProperties"; - /** System property, which will holf the location of the zookeeper properties file */ - public static final String ZK_PROPERTIES_FILE = "org.apache.oodt.config.zkProperties"; + /** Property name to fetch connect string to connect to a zookeeper ensemble. */ + public static final String ZK_CONNECT_STRING = "org.apache.oodt.config.zk.connectString"; - /** Property name to fetch connect string to connect to a zookeeper ensemble. */ - public static final String ZK_CONNECT_STRING = "org.apache.oodt.config.zk.connectString"; + public static final String ZK_CONNECTION_TIMEOUT = "org.apache.oodt.config.zk.connectionTimeoutMs"; + public static final String ZK_SESSION_TIMEOUT = "org.apache.oodt.config.zk.sessionTimeoutMs"; - public static final String ZK_CONNECTION_TIMEOUT = "org.apache.oodt.config.zk.connectionTimeoutMs"; - public static final String ZK_SESSION_TIMEOUT = "org.apache.oodt.config.zk.sessionTimeoutMs"; + public static final String ZK_RETRY_INITIAL_WAIT = "org.apache.oodt.config.zk.retryInitialWaitMs"; + public static final String ZK_RETRY_MAX_RETRIES = "org.apache.oodt.config.zk.maxRetries"; + public static final String ZK_STARTUP_TIMEOUT = "org.apache.oodt.config.zk.startupTimeoutMs"; - public static final String ZK_RETRY_INITIAL_WAIT = "org.apache.oodt.config.zk.retryInitialWaitMs"; - public static final String ZK_RETRY_MAX_RETRIES = "org.apache.oodt.config.zk.maxRetries"; - public static final String ZK_STARTUP_TIMEOUT = "org.apache.oodt.config.zk.startupTimeoutMs"; + public static final String ZK_USERNAME = "org.apache.oodt.config.zk.username"; + public static final String ZK_PASSWORD = "org.apache.oodt.config.zk.password"; + } - public static final String ZK_USERNAME = "org.apache.oodt.config.zk.username"; - public static final String ZK_PASSWORD = "org.apache.oodt.config.zk.password"; - } + public static class Components { + public static final String FILE_MANAGER = "filemgr"; + } + + public static class ZPaths { + /** Separator for ZNode paths */ + public static final String SEPARATOR = "/"; + + /** Namespace to be used when creating ZNodes in Zookeeper */ + public static final String NAMESPACE = "oodt"; + + /** Where OODT components related configuration are stored */ + public static final String COMPONENTS_PATH_NAME = "components"; + + /** Where properties files are stored inside each component */ + public static final String PROPERTIES_PATH_NAME = "properties"; + } } http://git-wip-us.apache.org/repos/asf/oodt/blob/4b88f714/config/src/main/java/org/apache/oodt/config/distributed/DistributedConfigurationManager.java ---------------------------------------------------------------------- diff --git a/config/src/main/java/org/apache/oodt/config/distributed/DistributedConfigurationManager.java b/config/src/main/java/org/apache/oodt/config/distributed/DistributedConfigurationManager.java index e7a3ed2..f6502bb 100644 --- a/config/src/main/java/org/apache/oodt/config/distributed/DistributedConfigurationManager.java +++ b/config/src/main/java/org/apache/oodt/config/distributed/DistributedConfigurationManager.java @@ -24,17 +24,18 @@ import org.apache.curator.retry.ExponentialBackoffRetry; import org.apache.oodt.config.ConfigurationManager; import org.apache.oodt.config.Constants; import org.apache.oodt.config.Constants.Properties; +import org.apache.oodt.config.utils.CuratorUtils; import org.apache.zookeeper.ZooDefs; import org.apache.zookeeper.data.ACL; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.util.List; import java.util.concurrent.TimeUnit; -import java.util.logging.Level; -import java.util.logging.Logger; +import static org.apache.oodt.config.Constants.Properties.ZK_CONNECT_STRING; import static org.apache.oodt.config.Constants.Properties.ZK_PROPERTIES_FILE; /** @@ -45,119 +46,117 @@ import static org.apache.oodt.config.Constants.Properties.ZK_PROPERTIES_FILE; */ public class DistributedConfigurationManager extends ConfigurationManager { - private static final Logger logger = Logger.getLogger(DistributedConfigurationManager.class.getName()); + private static final Logger logger = LoggerFactory.getLogger(DistributedConfigurationManager.class); - private static String environment = Constants.DEFAULT_ENVIRONMENT; - private static String nodeName; + /** Variables required to connect to zookeeper */ + private String connectString; + private CuratorFramework client; - /** Variables required to connect to zookeeper */ - private String connectString; - private CuratorFramework client; + public DistributedConfigurationManager(String component, List<String> propertiesFiles) { + super(component, propertiesFiles); - public DistributedConfigurationManager(String component, List<String> propertiesFiles, List<String> otherFiles) { - super(component, propertiesFiles, otherFiles); - loadZookeeperProperties(); - startZookeeper(); - } + if (System.getProperty(ZK_PROPERTIES_FILE) == null && System.getProperty(Constants.Properties.ZK_CONNECT_STRING) == null) { + throw new IllegalArgumentException("Zookeeper requires system properties " + ZK_PROPERTIES_FILE + " or " + ZK_CONNECT_STRING + " to be set"); + } - /** - * Loads zookeeper related properties from ZK_PROPERTIES_FILE. WIll throw a {@link RuntimeException} if that file is - * not available or couldn't be opened. - */ - private void loadZookeeperProperties() { - if (System.getProperty(ZK_PROPERTIES_FILE) != null) { - throw new IllegalArgumentException("DistributedCOnfigurationManager requires " + ZK_PROPERTIES_FILE + " to be set"); - } + if (System.getProperty(ZK_PROPERTIES_FILE) != null) { + try { + CuratorUtils.loadZookeeperProperties(); + } catch (IOException e) { + logger.error("Error occurred when loading properties from properties file"); + } + } - try { - System.getProperties().load(new FileInputStream(System.getProperty(ZK_PROPERTIES_FILE))); - } catch (IOException e) { - logger.log(Level.SEVERE, "Unable to read ZK_PROPERTIES_FILE " + System.getProperty(ZK_PROPERTIES_FILE)); - throw new IllegalStateException("Couldn't load Zookeeper configuration"); - } + if (System.getProperty(Constants.Properties.ZK_CONNECT_STRING) == null) { + throw new IllegalArgumentException("Zookeeper requires a proper connect string to connect to zookeeper ensemble"); + } + + connectString = System.getProperty(Constants.Properties.ZK_CONNECT_STRING); + logger.info("Using zookeeper connect string : {}", connectString); - if (System.getProperty(Properties.ZK_CONNECT_STRING) == null) { - throw new IllegalArgumentException("Zookeeper requires a proper connect string to connect to zookeeper ensemble"); + startZookeeper(); } - connectString = System.getProperty(Properties.ZK_CONNECT_STRING); - logger.log(Level.CONFIG, String.format("Using zookeeper connect string : %s", connectString)); - } - - /** - * Creates a {@link CuratorFramework} instance and start it. This method will wait a maximum amount of - * {@link Properties#ZK_STARTUP_TIMEOUT} milli-seconds until the client connects to the zookeeper ensemble. - */ - private void startZookeeper() { - int connectionTimeoutMs = Integer.parseInt(System.getProperty(Properties.ZK_CONNECTION_TIMEOUT, "15")); - int sessionTimeoutMs = Integer.parseInt(System.getProperty(Properties.ZK_CONNECTION_TIMEOUT, "60")); - int retryInitialWaitMs = Integer.parseInt(System.getProperty(Properties.ZK_CONNECTION_TIMEOUT, "1000")); - int maxRetryCount = Integer.parseInt(System.getProperty(Properties.ZK_CONNECTION_TIMEOUT, "3")); - int startupTimeOutMs = Integer.parseInt(System.getProperty(Properties.ZK_STARTUP_TIMEOUT, "30000")); - - CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder() - .connectString(connectString) - .retryPolicy(new ExponentialBackoffRetry(retryInitialWaitMs, maxRetryCount)) - .connectionTimeoutMs(connectionTimeoutMs) - .sessionTimeoutMs(sessionTimeoutMs); - - /* - * If authorization information is available, those will be added to the client. NOTE: These auth info are - * for access control, therefore no authentication will happen when the client is being started. These - * info will only be required whenever a client is accessing an already create ZNode. For another client of - * another node to make use of a ZNode created by this node, it should also provide the same auth info. + /** + * Creates a {@link CuratorFramework} instance and start it. This method will wait a maximum amount of + * {@link Properties#ZK_STARTUP_TIMEOUT} milli-seconds until the client connects to the zookeeper ensemble. */ - if (System.getProperty(Properties.ZK_USERNAME) != null && System.getProperty(Properties.ZK_PASSWORD) != null) { - String authenticationString = System.getProperty(Properties.ZK_USERNAME) + ":" + System.getProperty(Properties.ZK_PASSWORD); - builder.authorization("digest", authenticationString.getBytes()) - .aclProvider(new ACLProvider() { - public List<ACL> getDefaultAcl() { - return ZooDefs.Ids.CREATOR_ALL_ACL; - } - - public List<ACL> getAclForPath(String path) { - return ZooDefs.Ids.CREATOR_ALL_ACL; - } - }); + private void startZookeeper() { + int connectionTimeoutMs = Integer.parseInt(System.getProperty(Properties.ZK_CONNECTION_TIMEOUT, "15")); + int sessionTimeoutMs = Integer.parseInt(System.getProperty(Properties.ZK_CONNECTION_TIMEOUT, "60")); + int retryInitialWaitMs = Integer.parseInt(System.getProperty(Properties.ZK_CONNECTION_TIMEOUT, "1000")); + int maxRetryCount = Integer.parseInt(System.getProperty(Properties.ZK_CONNECTION_TIMEOUT, "3")); + int startupTimeOutMs = Integer.parseInt(System.getProperty(Properties.ZK_STARTUP_TIMEOUT, "30000")); + + CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder() + .connectString(connectString) + .retryPolicy(new ExponentialBackoffRetry(retryInitialWaitMs, maxRetryCount)) + .connectionTimeoutMs(connectionTimeoutMs) + .sessionTimeoutMs(sessionTimeoutMs); + + /* + * If authorization information is available, those will be added to the client. NOTE: These auth info are + * for access control, therefore no authentication will happen when the client is being started. These + * info will only be required whenever a client is accessing an already create ZNode. For another client of + * another node to make use of a ZNode created by this node, it should also provide the same auth info. + */ + if (System.getProperty(Properties.ZK_USERNAME) != null && System.getProperty(Properties.ZK_PASSWORD) != null) { + String authenticationString = System.getProperty(Properties.ZK_USERNAME) + ":" + System.getProperty(Properties.ZK_PASSWORD); + builder.authorization("digest", authenticationString.getBytes()) + .aclProvider(new ACLProvider() { + public List<ACL> getDefaultAcl() { + return ZooDefs.Ids.CREATOR_ALL_ACL; + } + + public List<ACL> getAclForPath(String path) { + return ZooDefs.Ids.CREATOR_ALL_ACL; + } + }); + } + + client = builder.build(); + logger.debug("CuratorFramework client built successfully with connectString: {}, sessionTimeout: {} and connectionTimeout: {}", + connectString, sessionTimeoutMs, connectionTimeoutMs); + + client.start(); + logger.info("Curator framework start operation invoked"); + + try { + logger.info("Waiting to connect to zookeeper, startupTimeout : {}", startupTimeOutMs); + client.blockUntilConnected(startupTimeOutMs, TimeUnit.MILLISECONDS); + } catch (InterruptedException ex) { + logger.error("Interrupted while waiting to connect zookeeper (connectString : {}) : {}", ex, connectString); + } + + if (!client.getZookeeperClient().isConnected()) { + throw new IllegalStateException("Could not connect to ZooKeeper : " + connectString); + } + + logger.info("CuratorFramework client started successfully"); } - client = builder.build(); - logger.log(Level.CONFIG, String.format("CuratorFramework client built successfully with " + - "connectString: %s, sessionTimeout: %d and connectionTimeout: %d", connectString, sessionTimeoutMs, connectionTimeoutMs)); - - client.start(); - logger.log(Level.CONFIG, "Curator framework start operation invoked"); - - try { - logger.info(String.format("Waiting to connect to zookeeper, startupTimeout : %d", startupTimeOutMs)); - client.blockUntilConnected(startupTimeOutMs, TimeUnit.MILLISECONDS); - } catch (InterruptedException ex) { - logger.severe(String.format("Interrupted while waiting to connect zookeeper (connectString : %s) : %s", ex.getMessage(), connectString)); + @Override + public String getProperty(String key) { + // Todo Implement using curator + return null; } - if (!client.getZookeeperClient().isConnected()) { - throw new IllegalStateException("Could not connect to ZooKeeper : " + connectString); + @Override + public void loadProperties() { + // todo Implement the logic with Curator } - logger.info("CuratorFramework client started successfully"); - } - - @Override - public String getProperty(String key) { - // Todo Implement using curator - return null; - } + public File getPropertiesFile(String filePath) { + return null; + } - @Override - public void loadProperties() { - // todo Implement the logic with Curator - } + public File getConfigurationFile(String filePath) { + return null; + } - public File getPropertiesFile(String filePath) { - return null; - } + public void publishConfiguration() { + for (String propertyFile : propertiesFiles) { - public File getConfigurationFile(String filePath) { - return null; - } + } + } } http://git-wip-us.apache.org/repos/asf/oodt/blob/4b88f714/config/src/main/java/org/apache/oodt/config/distributed/DistributedConfigurationPublisher.java ---------------------------------------------------------------------- diff --git a/config/src/main/java/org/apache/oodt/config/distributed/DistributedConfigurationPublisher.java b/config/src/main/java/org/apache/oodt/config/distributed/DistributedConfigurationPublisher.java new file mode 100644 index 0000000..38aea56 --- /dev/null +++ b/config/src/main/java/org/apache/oodt/config/distributed/DistributedConfigurationPublisher.java @@ -0,0 +1,200 @@ +/* + * 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.oodt.config.distributed; + +import org.apache.commons.io.FileUtils; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.framework.api.ACLProvider; +import org.apache.curator.retry.ExponentialBackoffRetry; +import org.apache.oodt.config.Constants; +import org.apache.oodt.config.utils.CuratorUtils; +import org.apache.zookeeper.ZooDefs; +import org.apache.zookeeper.data.ACL; +import org.apache.zookeeper.data.Stat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import static org.apache.oodt.config.Constants.Properties.ZK_CONNECT_STRING; +import static org.apache.oodt.config.Constants.Properties.ZK_PROPERTIES_FILE; + +/** + * The class to publish configuration to Zookeeper + * + * @author Imesha Sudasingha + */ +public class DistributedConfigurationPublisher { + + private static final Logger logger = LoggerFactory.getLogger(DistributedConfigurationPublisher.class); + + private Map<String, String> propertiesFiles; + private String connectString; + private CuratorFramework client; + private ZPaths zPaths; + + public DistributedConfigurationPublisher(String component, Map<String, String> propertiesFiles) { + this.propertiesFiles = propertiesFiles; + this.zPaths = new ZPaths(component); + + if (System.getProperty(ZK_PROPERTIES_FILE) == null && System.getProperty(Constants.Properties.ZK_CONNECT_STRING) == null) { + throw new IllegalArgumentException("Zookeeper requires system properties " + ZK_PROPERTIES_FILE + " or " + ZK_CONNECT_STRING + " to be set"); + } + + if (System.getProperty(ZK_PROPERTIES_FILE) != null) { + try { + CuratorUtils.loadZookeeperProperties(); + } catch (IOException e) { + logger.error("Error occurred when loading properties from properties file"); + } + } + + if (System.getProperty(Constants.Properties.ZK_CONNECT_STRING) == null) { + throw new IllegalArgumentException("Zookeeper requires a proper connect string to connect to zookeeper ensemble"); + } + + connectString = System.getProperty(Constants.Properties.ZK_CONNECT_STRING); + logger.info("Using zookeeper connect string : {}", connectString); + + startZookeeper(); + } + + /** + * Creates a {@link CuratorFramework} instance and start it. This method will wait a maximum amount of + * {@link Constants.Properties#ZK_STARTUP_TIMEOUT} milli-seconds until the client connects to the zookeeper ensemble. + */ + private void startZookeeper() { + int connectionTimeoutMs = Integer.parseInt(System.getProperty(Constants.Properties.ZK_CONNECTION_TIMEOUT, "15000")); + int sessionTimeoutMs = Integer.parseInt(System.getProperty(Constants.Properties.ZK_CONNECTION_TIMEOUT, "60000")); + int retryInitialWaitMs = Integer.parseInt(System.getProperty(Constants.Properties.ZK_CONNECTION_TIMEOUT, "1000")); + int maxRetryCount = Integer.parseInt(System.getProperty(Constants.Properties.ZK_CONNECTION_TIMEOUT, "3")); + int startupTimeOutMs = Integer.parseInt(System.getProperty(Constants.Properties.ZK_STARTUP_TIMEOUT, "30000")); + + CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder() + .connectString(connectString) + .retryPolicy(new ExponentialBackoffRetry(retryInitialWaitMs, maxRetryCount)) + .connectionTimeoutMs(connectionTimeoutMs) + .sessionTimeoutMs(sessionTimeoutMs); + + /* + * If authorization information is available, those will be added to the client. NOTE: These auth info are + * for access control, therefore no authentication will happen when the client is being started. These + * info will only be required whenever a client is accessing an already create ZNode. For another client of + * another node to make use of a ZNode created by this node, it should also provide the same auth info. + */ + if (System.getProperty(Constants.Properties.ZK_USERNAME) != null && System.getProperty(Constants.Properties.ZK_PASSWORD) != null) { + String authenticationString = System.getProperty(Constants.Properties.ZK_USERNAME) + ":" + System.getProperty(Constants.Properties.ZK_PASSWORD); + builder.authorization("digest", authenticationString.getBytes()) + .aclProvider(new ACLProvider() { + public List<ACL> getDefaultAcl() { + return ZooDefs.Ids.CREATOR_ALL_ACL; + } + + public List<ACL> getAclForPath(String path) { + return ZooDefs.Ids.CREATOR_ALL_ACL; + } + }); + } + + client = builder.build(); + logger.debug("CuratorFramework client built successfully with connectString: {}, sessionTimeout: {} and connectionTimeout: {}", + connectString, sessionTimeoutMs, connectionTimeoutMs); + + client.start(); + logger.info("Curator framework start operation invoked"); + + try { + logger.info("Waiting to connect to zookeeper, startupTimeout : {}", startupTimeOutMs); + client.blockUntilConnected(startupTimeOutMs, TimeUnit.MILLISECONDS); + } catch (InterruptedException ex) { + logger.error("Interrupted while waiting to connect zookeeper (connectString : {}) : {}", ex, connectString); + } + + if (!client.getZookeeperClient().isConnected()) { + throw new IllegalStateException("Could not connect to ZooKeeper : " + connectString); + } + + logger.info("CuratorFramework client started successfully"); + } + + public void publishConfiguration() throws Exception { + for (Map.Entry<String, String> entry : propertiesFiles.entrySet()) { + logger.info("Publishing configuration {} - {}", entry.getKey(), entry.getValue()); + URL resource = Thread.currentThread().getContextClassLoader().getResource(entry.getKey()); + + String content; + try { + content = FileUtils.readFileToString(new File(resource.toURI())); + } catch (IOException | URISyntaxException e) { + logger.error("Unable to read file : {}", entry.getKey(), e); + continue; + } + + String zNodePath = zPaths.getPropertiesZNodePath(entry.getValue()); + if (client.checkExists().forPath(zNodePath) != null) { + byte[] bytes = client.getData().forPath(zNodePath); + String existingData = new String(bytes); + if (content.equals(existingData)) { + logger.info("{} already exists in zookeeper at {}", entry.getKey(), entry.getValue()); + continue; + } else { + Stat stat = client.setData().forPath(zNodePath, content.getBytes()); + if (stat != null) { + logger.info("Published {} to {}", entry.getKey(), entry.getValue()); + } + } + } else { + client.create().creatingParentContainersIfNeeded().forPath(zNodePath, content.getBytes()); + } + } + } + + public static void main(String[] args) { + if (args.length < 2) { + logger.warn("Component name and at least one properties file needs to be given configuration publishing"); + throw new IllegalArgumentException("Requires at least two arguments, component and one properties file"); + } + + logger.debug("Starting publishing configuration. Component : {}", args[0]); + + String[] fileMapping = Arrays.copyOfRange(args, 1, args.length); + Map<String, String> propertiesFiles = new HashMap<>(); + for (String entry : fileMapping) { + String[] strings = entry.split("="); + propertiesFiles.put(strings[0], strings[1]); + } + + DistributedConfigurationPublisher distributedConfigurationPublisher = new DistributedConfigurationPublisher(args[0], propertiesFiles); + try { + distributedConfigurationPublisher.publishConfiguration(); + } catch (Exception e) { + logger.error("Error occurred when publishing configuration to zookeeper", e); + } + + logger.info("Published configuration successfully"); + } +} http://git-wip-us.apache.org/repos/asf/oodt/blob/4b88f714/config/src/main/java/org/apache/oodt/config/distributed/ZPaths.java ---------------------------------------------------------------------- diff --git a/config/src/main/java/org/apache/oodt/config/distributed/ZPaths.java b/config/src/main/java/org/apache/oodt/config/distributed/ZPaths.java new file mode 100644 index 0000000..0e1d10c --- /dev/null +++ b/config/src/main/java/org/apache/oodt/config/distributed/ZPaths.java @@ -0,0 +1,67 @@ +/* + * 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.oodt.config.distributed; + +import java.util.List; + +import static org.apache.oodt.config.Constants.ZPaths.*; + +/** + * Class responsible for handling all the Zookeeper ZNode paths related to configuration + * + * @author Imesha Sudasingha + */ +public class ZPaths { + + /** ZNode for distinct components. /components/${component} */ + public String componentZNodePath; + public String componentZNodeRoot; + + /** ZNode path for properties files. /components/${component}/properties */ + public String propertiesZNodePath; + public String propertiesZNodeRoot; + + /** + * Creates the ZNode path structure accordingly to the <pre>componentName</pre> and <pre>propertiesFileNames</pre> given. + * + * @param componentName Name of the OODT component + */ + public ZPaths(String componentName) { + if (componentName == null) { + throw new IllegalArgumentException("Component name cannot be null"); + } + + componentZNodePath = SEPARATOR + COMPONENTS_PATH_NAME + SEPARATOR + componentName; + componentZNodeRoot = componentZNodePath + SEPARATOR; + + propertiesZNodePath = componentZNodeRoot + PROPERTIES_PATH_NAME; + propertiesZNodeRoot = propertiesZNodePath + SEPARATOR; + } + + public String getComponentZNodePath() { + return componentZNodePath; + } + + public String getPropertiesZNodePath() { + return propertiesZNodePath; + } + + public String getPropertiesZNodePath(String subPath) { + return propertiesZNodeRoot + (subPath.startsWith(SEPARATOR) ? subPath.substring(1) : subPath); + } +} http://git-wip-us.apache.org/repos/asf/oodt/blob/4b88f714/config/src/main/java/org/apache/oodt/config/standalone/StandaloneConfigurationManager.java ---------------------------------------------------------------------- diff --git a/config/src/main/java/org/apache/oodt/config/standalone/StandaloneConfigurationManager.java b/config/src/main/java/org/apache/oodt/config/standalone/StandaloneConfigurationManager.java index 0cf0c78..23cf0a2 100644 --- a/config/src/main/java/org/apache/oodt/config/standalone/StandaloneConfigurationManager.java +++ b/config/src/main/java/org/apache/oodt/config/standalone/StandaloneConfigurationManager.java @@ -18,13 +18,14 @@ package org.apache.oodt.config.standalone; import org.apache.oodt.config.ConfigurationManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.List; -import java.util.logging.Logger; /** * {@link ConfigurationManager} implementation to be used with standalone configuration management. @@ -33,46 +34,35 @@ import java.util.logging.Logger; */ public class StandaloneConfigurationManager extends ConfigurationManager { - /** Logger instance for logging */ - private static final Logger logger = Logger.getLogger(StandaloneConfigurationManager.class.getName()); + /** Logger instance for logging */ + private static final Logger logger = LoggerFactory.getLogger(StandaloneConfigurationManager.class); - public StandaloneConfigurationManager(String component, List<String> propertiesFiles, List<String> otherFiles) { - super(component, propertiesFiles, otherFiles); - } - - /** {@inheritDoc} */ - @Override - public String getProperty(String key) { - return System.getProperty(key); - } + public StandaloneConfigurationManager(String component, List<String> propertiesFiles) { + super(component, propertiesFiles); + } - /** {@inheritDoc} */ - @Override - public void loadProperties() throws IOException { - for (String file : propertiesFiles) { - System.getProperties().load(new FileInputStream(new File(file))); + /** {@inheritDoc} */ + @Override + public String getProperty(String key) { + return System.getProperty(key); } - } - /** {@inheritDoc} */ - @Override - public File getPropertiesFile(String filePath) throws FileNotFoundException { - File file = new File(filePath); - if (!propertiesFiles.contains(filePath) || !file.exists()) { - throw new FileNotFoundException("Couldn't find properties file located at: " + filePath); + /** {@inheritDoc} */ + @Override + public void loadProperties() throws IOException { + for (String file : propertiesFiles) { + System.getProperties().load(new FileInputStream(new File(file))); + } } - return file; - } + /** {@inheritDoc} */ + @Override + public File getPropertiesFile(String filePath) throws FileNotFoundException { + File file = new File(filePath); + if (!propertiesFiles.contains(filePath) || !file.exists()) { + throw new FileNotFoundException("Couldn't find properties file located at: " + filePath); + } - /** {@inheritDoc} */ - @Override - public File getConfigurationFile(String filePath) throws FileNotFoundException { - File file = new File(filePath); - if (!otherFiles.contains(filePath) || !file.exists()) { - throw new FileNotFoundException("Couldn't find properties file located at: " + filePath); + return file; } - - return file; - } } http://git-wip-us.apache.org/repos/asf/oodt/blob/4b88f714/config/src/main/java/org/apache/oodt/config/utils/CuratorUtils.java ---------------------------------------------------------------------- diff --git a/config/src/main/java/org/apache/oodt/config/utils/CuratorUtils.java b/config/src/main/java/org/apache/oodt/config/utils/CuratorUtils.java new file mode 100644 index 0000000..d064080 --- /dev/null +++ b/config/src/main/java/org/apache/oodt/config/utils/CuratorUtils.java @@ -0,0 +1,80 @@ +/* + * 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.oodt.config.utils; + +import org.apache.curator.framework.CuratorFramework; +import org.apache.zookeeper.CreateMode; +import org.apache.zookeeper.KeeperException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.FileInputStream; +import java.io.IOException; + +import static org.apache.oodt.config.Constants.Properties.ZK_PROPERTIES_FILE; + +public class CuratorUtils { + + private static final Logger logger = LoggerFactory.getLogger(CuratorUtils.class); + + private CuratorUtils() { + } + + /** + * Loads zookeeper related properties from ZK_PROPERTIES_FILE. + * + * @throws IOException if properties file could not be read + */ + public static void loadZookeeperProperties() throws IOException { + System.getProperties().load(new FileInputStream(System.getProperty(ZK_PROPERTIES_FILE))); + } + + /** + * Create a ZNode in the given path if not exists, with the given data + * + * @param curatorFramework {@link CuratorFramework} client + * @param zNodePath the path in which the ZNode to be created + */ + public static void createZNodeIfNotExists(CuratorFramework curatorFramework, String zNodePath, CreateMode mode, byte[] content) throws Exception { + try { + String path = curatorFramework.create().creatingParentsIfNeeded().withMode(mode).forPath(zNodePath, content); + logger.debug("Created ZNode at path : {}", path); + } catch (Exception e) { + if (e instanceof KeeperException && KeeperException.Code.NODEEXISTS.equals(((KeeperException) e).code())) { + // This is a desired behaviour, trying to create an already existing znode. + logger.debug("Attempting to create an already existing ZNode at path {} : {}", zNodePath, e); + } else { + logger.error("Error when creating ZNode for path {} : {}", zNodePath, e.getMessage()); + throw e; + } + } + } + + /** + * Gets the <code>String</code> value of the data in the given znode path + * + * @param client {@link CuratorFramework} client + * @param path ZNode path to be checked + * @return ZNode's data as a string or null + * @throws Exception zookeeper errors and etc + */ + public static String getIfExists(CuratorFramework client, String path) throws Exception { + return client.checkExists().forPath(path) != null ? new String(client.getData().forPath(path)) : null; + } + +} http://git-wip-us.apache.org/repos/asf/oodt/blob/4b88f714/config/src/test/java/org/apache/oodt/config/distributed/DistributedConfigurationPublisherTest.java ---------------------------------------------------------------------- diff --git a/config/src/test/java/org/apache/oodt/config/distributed/DistributedConfigurationPublisherTest.java b/config/src/test/java/org/apache/oodt/config/distributed/DistributedConfigurationPublisherTest.java new file mode 100644 index 0000000..665f785 --- /dev/null +++ b/config/src/test/java/org/apache/oodt/config/distributed/DistributedConfigurationPublisherTest.java @@ -0,0 +1,88 @@ +/* + * 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.oodt.config.distributed; + +import org.apache.commons.io.FileUtils; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.retry.RetryNTimes; +import org.apache.curator.test.TestingServer; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.util.Arrays; + +import static org.apache.oodt.config.Constants.Components.FILE_MANAGER; +import static org.apache.oodt.config.Constants.Properties.ZK_CONNECT_STRING; + +public class DistributedConfigurationPublisherTest { + + private static TestingServer zookeeper; + private static CuratorFramework client; + + @BeforeClass + public static void setUp() throws Exception { + zookeeper = new TestingServer(); + zookeeper.start(); + + client = CuratorFrameworkFactory.builder() + .connectString(zookeeper.getConnectString()) + .retryPolicy(new RetryNTimes(3, 1000)) + .build(); + client.start(); + + System.setProperty(ZK_CONNECT_STRING, zookeeper.getConnectString()); + } + + @Test + public void publishConfiguration() throws Exception { + String args[] = new String[]{ + FILE_MANAGER, + "filemgr.properties=/etc/filemgr.properties", + "mime-types.xml=/etc/mime-types.xml" + }; + DistributedConfigurationPublisher.main(args); + + String[] fileMappings = Arrays.copyOfRange(args, 1, args.length); + ZPaths zPaths = new ZPaths(FILE_MANAGER); + for (String mapping : fileMappings) { + String[] parts = mapping.split("="); + String zNodePath = zPaths.getPropertiesZNodePath(parts[1]); + + Assert.assertNotNull(client.checkExists().forPath(zNodePath)); + + String storedContent = new String(client.getData().forPath(zNodePath)); + + URI file = Thread.currentThread().getContextClassLoader().getResource(parts[0]).toURI(); + String fileContent = FileUtils.readFileToString(new File(file)); + + Assert.assertEquals(fileContent, storedContent); + } + } + + @AfterClass + public static void tearDown() throws IOException { + client.close(); + zookeeper.stop(); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/oodt/blob/4b88f714/config/src/test/resources/filemgr.properties ---------------------------------------------------------------------- diff --git a/config/src/test/resources/filemgr.properties b/config/src/test/resources/filemgr.properties new file mode 100644 index 0000000..4d8d957 --- /dev/null +++ b/config/src/test/resources/filemgr.properties @@ -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. +# + +# Configuration properties for the File Manager + +# repository factory +filemgr.repository.factory=org.apache.oodt.cas.filemgr.repository.XMLRepositoryManagerFactory + +# Lucene catalog factory +filemgr.catalog.factory=org.apache.oodt.cas.filemgr.catalog.LuceneCatalogFactory + +# data transfer factory +filemgr.datatransfer.factory=org.apache.oodt.cas.filemgr.datatransfer.LocalDataTransferFactory + +# validation layer factory +filemgr.validationLayer.factory=org.apache.oodt.cas.filemgr.validation.XMLValidationLayerFactory + +# xml rpc client configuration +org.apache.oodt.cas.filemgr.system.xmlrpc.connectionTimeout.minutes=20 +org.apache.oodt.cas.filemgr.system.xmlrpc.requestTimeout.minutes=60 +#org.apache.oodt.cas.filemgr.system.xmlrpc.connection.retries=0 +#org.apache.oodt.cas.filemgr.system.xmlrpc.connection.retry.interval.seconds=3 + +# mapped data source catalog configuration +#org.apache.oodt.cas.filemgr.catalog.mappeddatasource.mapFile=/path/to/ops.catalog.typemap.properties + +# lucene catalog configuration +org.apache.oodt.cas.filemgr.catalog.lucene.idxPath=[OODT_HOME]/data/catalog +org.apache.oodt.cas.filemgr.catalog.lucene.pageSize=20 +org.apache.oodt.cas.filemgr.catalog.lucene.commitLockTimeout.seconds=60 +org.apache.oodt.cas.filemgr.catalog.lucene.writeLockTimeout.seconds=60 +org.apache.oodt.cas.filemgr.catalog.lucene.mergeFactor=20 + +# XML repository manager configuration +org.apache.oodt.cas.filemgr.repositorymgr.dirs=file:[FILEMGR_HOME]/policy/oodt + +# XML validation layer configuration +org.apache.oodt.cas.filemgr.validation.dirs=file:[FILEMGR_HOME]/policy/oodt + +# remote data transfer configuration +org.apache.oodt.cas.filemgr.datatransfer.remote.chunkSize=1024 + +# location of Mime-Type repository +org.apache.oodt.cas.filemgr.mime.type.repository=[FILEMGR_HOME]/etc/mime-types.xml + + +############ data source configuration ################################## +# +# These 3 blocks of config properties can be used to setup a catalog, +# repository manager, and validation layer based on a RDBMS such as +# Oracle, MySQL, PostgreSQL, or any others that support a jdbc connection. +# Just un-comment the following blocks of properties and configure as +# needed. +# +######################################################################### + +# datasource catalog config +#org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.url=some_jdbc_url +#org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.user=user +#org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.pass=pass +#org.apache.oodt.cas.filemgr.catalog.datasource.jdbc.driver=driver.class.name +#org.apache.oodt.cas.filemgr.catalog.datasource.quoteFields=false +#org.apache.oodt.cas.filemgr.catalog.datasource.pageSize=20 +#org.apache.oodt.cas.filemgr.catalog.datasource.cacheUpdateMinutes=5 + +# data source repository manager configuration +#org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.url=some_jdbc_url +#org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.user=user +#org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.pass=pass +#org.apache.oodt.cas.filemgr.repositorymgr.datasource.jdbc.driver=driver.class.name + +# data source validation layer configuration +#org.apache.oodt.cas.filemgr.validation.datasource.jdbc.url=some_jdbc_url +#org.apache.oodt.cas.filemgr.validation.datasource.jdbc.user=user +#org.apache.oodt.cas.filemgr.validation.datasource.jdbc.pass=pass +#org.apache.oodt.cas.filemgr.validation.datasource.jdbc.driver=driver.class.name +#org.apache.oodt.cas.filemgr.validation.datasource.quoteFields=false + + +# tells the file manager system layer to include product instance metadata +# NOTE: here are the expected field mappings +# +# product.getProductId() -> ProductId +# product.getProductName() -> ProductName +# product.getProductStructure() -> ProductStructure +# product.getTransferStatus() -> ProductTransferStatus +# product.getRootRef() -> ProductRootReference + +# for the references returned by product.getProductReferences() the following +# metadata fields will be added (order will be maintained, such that data store +# ref at index 0 will map to orig ref at index 0, etc.) +# +# ProductDataStoreReferences (list of all data store references: +# note already translated into path, not URI) +# ProductOrigReferences (list of all orig references: +# note already translated into path, not URI) +# ProductMimeType (list of all references' mime-types) +# ProductFileSize (list of all references' file sizes) + +org.apache.oodt.cas.filemgr.metadata.expandProduct=false \ No newline at end of file http://git-wip-us.apache.org/repos/asf/oodt/blob/4b88f714/config/src/test/resources/log4j.xml ---------------------------------------------------------------------- diff --git a/config/src/test/resources/log4j.xml b/config/src/test/resources/log4j.xml new file mode 100644 index 0000000..8f49451 --- /dev/null +++ b/config/src/test/resources/log4j.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!-- + ~ 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. + --> + +<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> + +<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> + <appender name="console" class="org.apache.log4j.ConsoleAppender"> + <param name="Target" value="System.out"/> + <layout class="org.apache.log4j.PatternLayout"> + <param name="ConversionPattern" value="%-5p %c{1} - %m%n"/> + </layout> + </appender> + + <root> + <priority value="INFO"/> + <appender-ref ref="console"/> + </root> + +</log4j:configuration> \ No newline at end of file
