org.apache.karaf.tooling.utils.PropertiesLoader Maven / Gradle / Ivy
/*
* 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.karaf.tooling.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import org.apache.felix.utils.properties.Properties;
import java.util.StringTokenizer;
import static org.apache.felix.utils.properties.InterpolationHelper.substVars;
public class PropertiesLoader {
private static final String INCLUDES_PROPERTY = "${includes}"; // mandatory includes
private static final String OPTIONALS_PROPERTY = "${optionals}"; // optionals include
private static final String OVERRIDE_PREFIX = "karaf.override."; // prefix that marks that system property should override defaults.
/**
*
* Loads the configuration properties in the configuration property file
* associated with the framework installation; these properties
* are accessible to the framework and to bundles and are intended
* for configuration purposes. By default, the configuration property
* file is located in the conf/ directory of the Felix
* installation directory and is called "config.properties".
* The installation directory of Felix is assumed to be the parent
* directory of the felix.jar file as found on the system class
* path property. The precise file from which to load configuration
* properties can be set by initializing the "felix.config.properties"
* system property to an arbitrary URL.
*
*
* @return A Properties instance or null if there was an error.
* @throws Exception if something wrong occurs
*/
public static Properties loadConfigProperties(File file) throws Exception {
// See if the property URL was specified as a property.
URL configPropURL;
try {
configPropURL = file.toURI().toURL();
}
catch (MalformedURLException ex) {
System.err.print("Main: " + ex);
return null;
}
Properties configProps = loadPropertiesFile(configPropURL, false);
copySystemProperties(configProps);
configProps.substitute();
// Perform variable substitution for system properties.
// for (Enumeration e = configProps.propertyNames(); e.hasMoreElements();) {
// String name = (String) e.nextElement();
// configProps.setProperty(name,
// SubstHelper.substVars(configProps.getProperty(name), name, null, configProps));
// }
return configProps;
}
/**
*
* Loads the properties in the system property file associated with the
* framework installation into System.setProperty(). These properties
* are not directly used by the framework in anyway. By default, the system
* property file is located in the conf/ directory of the Felix
* installation directory and is called "system.properties". The
* installation directory of Felix is assumed to be the parent directory of
* the felix.jar file as found on the system class path property.
* The precise file from which to load system properties can be set by
* initializing the "felix.system.properties" system property to an
* arbitrary URL.
*
*
* @param karafBase the karaf base folder
* @throws IOException
*/
public static void loadSystemProperties(File file) throws IOException {
Properties props = new Properties(false);
try {
InputStream is = new FileInputStream(file);
props.load(is);
is.close();
} catch (Exception e1) {
// Ignore
}
for (Enumeration e = props.propertyNames(); e.hasMoreElements();) {
String name = (String) e.nextElement();
if (name.startsWith(OVERRIDE_PREFIX)) {
String overrideName = name.substring(OVERRIDE_PREFIX.length());
String value = props.getProperty(name);
System.setProperty(overrideName, substVars(value, name, null, props));
} else {
String value = System.getProperty(name, props.getProperty(name));
System.setProperty(name, substVars(value, name, null, props));
}
}
}
public static void copySystemProperties(Properties configProps) {
for (Enumeration e = System.getProperties().propertyNames();
e.hasMoreElements();) {
String key = (String) e.nextElement();
if (key.startsWith("felix.") ||
key.startsWith("karaf.") ||
key.startsWith("org.osgi.framework.")) {
configProps.setProperty(key, System.getProperty(key));
}
}
}
public static Properties loadPropertiesOrFail(File configFile) {
try {
URL configPropURL = configFile.toURI().toURL();
return loadPropertiesFile(configPropURL, true);
} catch (Exception e) {
throw new RuntimeException("Error loading properties from " + configFile, e);
}
}
public static Properties loadPropertiesFile(URL configPropURL, boolean failIfNotFound) throws Exception {
Properties configProps = new Properties(null, false);
InputStream is = null;
try {
is = configPropURL.openConnection().getInputStream();
configProps.load(is);
is.close();
} catch (FileNotFoundException ex) {
if (failIfNotFound) {
throw ex;
} else {
System.err.println("WARN: " + configPropURL + " is not found, so not loaded");
}
} catch (Exception ex) {
System.err.println("Error loading config properties from " + configPropURL);
System.err.println("Main: " + ex);
return configProps;
} finally {
try {
if (is != null) {
is.close();
}
}
catch (IOException ex2) {
// Nothing we can do.
}
}
loadIncludes(INCLUDES_PROPERTY, true, configPropURL, configProps);
loadIncludes(OPTIONALS_PROPERTY, false, configPropURL, configProps);
trimValues(configProps);
return configProps;
}
private static void loadIncludes(String propertyName, boolean mandatory, URL configPropURL, Properties configProps)
throws MalformedURLException, Exception {
String includes = (String) configProps.get(propertyName);
if (includes != null) {
StringTokenizer st = new StringTokenizer(includes, "\" ", true);
if (st.countTokens() > 0) {
String location;
do {
location = nextLocation(st);
if (location != null) {
URL url = new URL(configPropURL, location);
Properties props = loadPropertiesFile(url, mandatory);
configProps.putAll(props);
}
}
while (location != null);
}
}
configProps.remove(propertyName);
}
private static void trimValues(Properties configProps) {
for (String key : configProps.keySet()) {
configProps.put(key, configProps.get(key).trim());
}
}
private static String nextLocation(StringTokenizer st) {
String retVal = null;
if (st.countTokens() > 0) {
String tokenList = "\" ";
StringBuffer tokBuf = new StringBuffer(10);
String tok;
boolean inQuote = false;
boolean tokStarted = false;
boolean exit = false;
while ((st.hasMoreTokens()) && (!exit)) {
tok = st.nextToken(tokenList);
if (tok.equals("\"")) {
inQuote = !inQuote;
if (inQuote) {
tokenList = "\"";
} else {
tokenList = "\" ";
}
} else if (tok.equals(" ")) {
if (tokStarted) {
retVal = tokBuf.toString();
tokStarted = false;
tokBuf = new StringBuffer(10);
exit = true;
}
} else {
tokStarted = true;
tokBuf.append(tok.trim());
}
}
// Handle case where end of token stream and
// still got data
if ((!exit) && (tokStarted)) {
retVal = tokBuf.toString();
}
}
return retVal;
}
}