in src/main/java/org/apache/sling/launchpad/base/impl/Sling.java [389:568]
private Map<String, String> loadConfigProperties(
final Map<String, String> propOverwrite) throws BundleException {
// The config properties file is either specified by a system
// property or it is in the same directory as the Felix JAR file.
// Try to load it from one of these places.
final Map<String, String> staticProps = new HashMap<String, String>();
// Read the embedded (default) properties file.
this.load(staticProps, CONFIG_PROPERTIES);
// resolve inclusions (and remove property)
this.loadIncludes(staticProps, null);
// overwrite default properties with initial overwrites
if (propOverwrite != null) {
staticProps.putAll(propOverwrite);
}
// check whether sling.home is overwritten by system property
String slingHome = staticProps.get(SharedConstants.SLING_HOME);
if (slingHome == null || slingHome.length() == 0) {
throw new BundleException("sling.home property is missing, cannot start");
}
// resolve variables and ensure sling.home is an absolute path
slingHome = Util.substVars(slingHome, SharedConstants.SLING_HOME, null, staticProps);
File slingHomeFile = new File(slingHome).getAbsoluteFile();
slingHome = slingHomeFile.getAbsolutePath();
// overlay with ${sling.home}/sling.properties
this.logger.log(Logger.LOG_INFO, "Starting Apache Sling in " + slingHome);
File propFile = getSlingProperties(slingHome, staticProps);
this.load(staticProps, propFile);
// migrate old properties to new properties
migrateProp(staticProps, "framework.cache.profiledir", Constants.FRAMEWORK_STORAGE);
migrateProp(staticProps, "sling.osgi-core-packages", "osgi-core-packages");
migrateProp(staticProps, "sling.osgi-compendium-services", "osgi-compendium-services");
// migrate initial start level property: Felix used to have
// framework.startlevel.framework, later moved to org.osgi.framework.startlevel
// and finally now uses org.osgi.framework.startlevel.beginning as
// speced in the latest R 4.2 draft (2009/03/10). We first check the
// intermediate Felix property, then the initial property, thus allowing
// the older (and more probable value) to win
migrateProp(staticProps, "org.osgi.framework.startlevel", Constants.FRAMEWORK_BEGINNING_STARTLEVEL);
migrateProp(staticProps, "framework.startlevel.framework", Constants.FRAMEWORK_BEGINNING_STARTLEVEL);
// create a copy of the properties to perform variable substitution
final Map<String, String> runtimeProps = new HashMap<String, String>();
runtimeProps.putAll(staticProps);
// check system properties for any overrides (except sling.home !)
String ignoreSystemProperties = runtimeProps.get(SLING_IGNORE_SYSTEM_PROPERTIES);
if (!"true".equalsIgnoreCase(ignoreSystemProperties)) {
for (String name : runtimeProps.keySet()) {
String sysProp = System.getProperty(name);
if (sysProp != null) {
runtimeProps.put(name, sysProp);
}
}
}
// resolve inclusions again
this.loadIncludes(runtimeProps, slingHome);
// overwrite properties, this is not persisted as such
this.loadPropertiesOverride(runtimeProps);
// resolve boot delegation and system packages
this.resolve(runtimeProps, "org.osgi.framework.bootdelegation",
"sling.bootdelegation.");
this.resolve(runtimeProps, "org.osgi.framework.system.packages",
"sling.system.packages.");
// reset back the sling home property
// might have been overwritten by system properties, included
// files or the sling.properties file
staticProps.put(SharedConstants.SLING_HOME, slingHome);
runtimeProps.put(SharedConstants.SLING_HOME, slingHome);
runtimeProps.put(SLING_HOME_URL, slingHomeFile.toURI().toString());
// add property file locations
runtimeProps.put(SharedConstants.SLING_PROPERTIES, propFile.getAbsolutePath());
runtimeProps.put(SharedConstants.SLING_PROPERTIES_URL, propFile.toURI().toString());
// Perform variable substitution for system properties.
for (Entry<String, String> entry : runtimeProps.entrySet()) {
entry.setValue(Util.substVars(entry.getValue(), entry.getKey(), null,
runtimeProps));
}
// look for context:/ URLs to substitute
for (Entry<String, String> entry : runtimeProps.entrySet()) {
String name = entry.getKey();
String value = entry.getValue();
if (value != null && value.startsWith("context:/")) {
String path = value.substring("context:/".length() - 1);
InputStream src = this.resourceProvider.getResourceAsStream(path);
if (src != null) {
File target = new File(slingHome, path);
OutputStream dest = null;
try {
// only copy file if not existing
if (!target.exists()) {
target.getParentFile().mkdirs();
dest = new FileOutputStream(target);
byte[] buf = new byte[2048];
int rd;
while ((rd = src.read(buf)) >= 0) {
dest.write(buf, 0, rd);
}
}
// after copying replace property and add url property
entry.setValue(target.getAbsolutePath());
// also set the new property on the unsubstituted props
staticProps.put(name, "${sling.home}" + path);
} catch (IOException ioe) {
this.logger.log(Logger.LOG_ERROR, "Cannot copy file "
+ value + " to " + target, ioe);
} finally {
if (dest != null) {
try {
dest.close();
} catch (IOException ignore) {
}
}
try {
src.close();
} catch (IOException ignore) {
}
}
}
}
}
// write the unsubstituted properties back to the overlay file
OutputStream os = null;
try {
// ensure parent folder(s)
propFile.getParentFile().mkdirs();
os = new FileOutputStream(propFile);
// copy the values into a temporary properties structure to store
Properties tmp = new Properties();
tmp.putAll(staticProps);
// remove properties where overlay makes no sense
tmp.remove(SharedConstants.SLING_HOME);
tmp.remove(SharedConstants.SLING_LAUNCHPAD);
tmp.remove(SharedConstants.SLING_PROPERTIES);
tmp.store(os, "Overlay properties for configuration");
} catch (Exception ex) {
this.logger.log(Logger.LOG_ERROR,
"Error loading overlay properties from " + propFile, ex);
} finally {
if (os != null) {
try {
os.close();
} catch (IOException ex2) {
// Nothing we can do.
}
}
}
Map<String, String> result = new HashMap<>();
for (Entry<String, String> entry : runtimeProps.entrySet()) {
result.put(entry.getKey(), entry.getValue().replace("{dollar}", "$"));
}
return result;
}