| /** |
| * 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.falcon.util; |
| |
| import org.apache.commons.io.IOUtils; |
| import org.apache.commons.lang3.StringUtils; |
| import org.apache.falcon.FalconException; |
| import org.apache.falcon.expression.ExpressionHelper; |
| import org.apache.falcon.security.CredentialProviderHelper; |
| import org.apache.hadoop.conf.Configuration; |
| 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.io.InputStream; |
| import java.net.URL; |
| import java.util.HashSet; |
| import java.util.Properties; |
| import java.util.Set; |
| |
| /** |
| * Base class for reading application properties. |
| */ |
| public abstract class ApplicationProperties extends Properties { |
| |
| private static final Logger LOG = LoggerFactory.getLogger(ApplicationProperties.class); |
| |
| public static final String CREDENTIAL_PROVIDER_PROPERTY = "credential.provider.path"; |
| public static final String ALIAS_PROPERTY_PREFIX = "credential.provider.alias.for."; |
| |
| protected abstract String getPropertyFile(); |
| |
| protected String domain; |
| |
| protected ApplicationProperties() throws FalconException { |
| init(); |
| } |
| |
| protected void init() throws FalconException { |
| setDomain(System.getProperty("falcon.domain", System.getenv("FALCON_DOMAIN"))); |
| loadProperties(); |
| } |
| |
| protected void setDomain(String domain) { |
| this.domain = domain; |
| } |
| |
| public String getDomain() { |
| return domain; |
| } |
| |
| protected void loadProperties() throws FalconException { |
| String propertyFileName = getPropertyFile(); |
| String confDir = System.getProperty("config.location"); |
| loadProperties(propertyFileName, confDir); |
| } |
| |
| /** |
| * This method reads the given properties file in the following order: |
| * config.location & classpath. It falls back in that specific order. |
| * |
| * @throws FalconException |
| */ |
| protected void loadProperties(String propertyFileName, String confDir) throws FalconException { |
| try { |
| InputStream resourceAsStream = checkConfigLocation(propertyFileName, confDir); |
| |
| //Fallback to classpath |
| if (resourceAsStream == null) { |
| resourceAsStream = checkClassPath(propertyFileName); |
| } |
| |
| if (resourceAsStream != null) { |
| try { |
| doLoadProperties(resourceAsStream); |
| return; |
| } finally { |
| IOUtils.closeQuietly(resourceAsStream); |
| } |
| } |
| throw new FileNotFoundException("Unable to find: " + propertyFileName); |
| } catch (IOException e) { |
| throw new FalconException("Error loading properties file: " + getPropertyFile(), e); |
| } |
| } |
| |
| private InputStream checkConfigLocation(String propertyFileName, String confDir) |
| throws FileNotFoundException { |
| |
| InputStream resourceAsStream = null; |
| if (confDir != null) { |
| File fileToLoad = new File(confDir, propertyFileName); |
| resourceAsStream = getResourceAsStream(fileToLoad); |
| } |
| return resourceAsStream; |
| } |
| |
| protected InputStream getResourceAsStream(File fileToLoad) throws FileNotFoundException { |
| InputStream resourceAsStream = null; |
| if (fileToLoad.exists() && fileToLoad.isFile() && fileToLoad.canRead()) { |
| LOG.info("config.location is set, using: {}", fileToLoad.getAbsolutePath()); |
| resourceAsStream = new FileInputStream(fileToLoad); |
| } |
| return resourceAsStream; |
| } |
| |
| protected InputStream checkClassPath(String propertyFileName) { |
| |
| InputStream resourceAsStream = null; |
| Class clazz = ApplicationProperties.class; |
| URL resource = clazz.getResource("/" + propertyFileName); |
| if (resource != null) { |
| LOG.info("Fallback to classpath for: {}", resource); |
| resourceAsStream = clazz.getResourceAsStream("/" + propertyFileName); |
| } else { |
| resource = clazz.getResource(propertyFileName); |
| if (resource != null) { |
| LOG.info("Fallback to classpath for: {}", resource); |
| resourceAsStream = clazz.getResourceAsStream(propertyFileName); |
| } |
| } |
| return resourceAsStream; |
| } |
| |
| private void doLoadProperties(InputStream resourceAsStream) throws IOException, FalconException { |
| Properties origProps = new Properties(); |
| origProps.load(resourceAsStream); |
| if (domain == null) { |
| domain = origProps.getProperty("*.domain"); |
| if (domain == null) { |
| throw new FalconException("Domain is not set!"); |
| } else { |
| domain = ExpressionHelper.substitute(domain); |
| } |
| } |
| |
| LOG.info("Initializing {} properties with domain {}", this.getClass().getName(), domain); |
| Set<String> keys = getKeys(origProps.keySet()); |
| for (String key : keys) { |
| String value = origProps.getProperty(domain + "." + key, origProps.getProperty("*." + key)); |
| if (value != null) { |
| value = ExpressionHelper.substitute(value); |
| LOG.debug("{}={}", key, value); |
| put(key, value); |
| } |
| } |
| } |
| |
| protected Set<String> getKeys(Set<Object> keySet) { |
| Set<String> keys = new HashSet<String>(); |
| for (Object keyObj : keySet) { |
| String key = (String) keyObj; |
| keys.add(key.substring(key.indexOf('.') + 1)); |
| } |
| return keys; |
| } |
| |
| public void resolveAlias() throws FalconException { |
| try { |
| final Configuration conf = new Configuration(); |
| String providerPath = getProperty(CREDENTIAL_PROVIDER_PROPERTY); |
| if (providerPath != null) { |
| conf.set(CredentialProviderHelper.CREDENTIAL_PROVIDER_PATH, providerPath); |
| } |
| |
| Properties aliasProperties = new Properties(); |
| for (Object keyObj : keySet()) { |
| String key = (String) keyObj; |
| if (key.startsWith(ALIAS_PROPERTY_PREFIX)) { |
| String propertyKey = key.substring(ALIAS_PROPERTY_PREFIX.length()); |
| String propertyValue = CredentialProviderHelper.resolveAlias(conf, getProperty(key)); |
| aliasProperties.setProperty(propertyKey, propertyValue); |
| } |
| } |
| LOG.info("Resolved alias properties: {}", aliasProperties.stringPropertyNames()); |
| putAll(aliasProperties); |
| } catch (Exception e) { |
| LOG.error("Exception while resolving credential alias", e); |
| throw new FalconException("Exception while resolving credential alias", e); |
| } |
| } |
| |
| @Override |
| public String getProperty(String key) { |
| return StringUtils.trim(super.getProperty(key)); |
| } |
| |
| @Override |
| public String getProperty(String key, String defaultValue) { |
| return StringUtils.trim(super.getProperty(key, defaultValue)); |
| } |
| } |