blob: c654df1b4457056aee9643bb12cb78e9654db2e6 [file] [log] [blame]
/**
* 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));
}
}