blob: 1251940b163f6cd2e8be7a4a323caf3678700d17 [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.ofbiz.base.start;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.TimeZone;
public class Config {
public final InetAddress adminAddress;
public final String adminKey;
public final int adminPort;
public final String awtHeadless;
public final String containerConfig;
public final String instrumenterClassName;
public final String instrumenterFile;
public final List<Map<String, String>> loaders;
public final String logDir;
public final String ofbizHome;
public final boolean shutdownAfterLoad;
public final String splashLogo;
public final boolean useShutdownHook;
public final Integer portOffset;
Config(String[] args) throws IOException {
String firstArg = args.length > 0 ? args[0] : "";
// Needed when portoffset is used with these commands, start.properties fits for all of them
if ("start-batch".equalsIgnoreCase(firstArg)
|| "start-debug".equalsIgnoreCase(firstArg)
|| "stop".equalsIgnoreCase(firstArg)
|| "-shutdown".equalsIgnoreCase(firstArg) // shutdown & status hack (was pre-existing to portoffset introduction, also useful with it)
|| "-status".equalsIgnoreCase(firstArg)) {
firstArg = "start";
}
// default command is "start"
if (firstArg == null || firstArg.trim().length() == 0) {
firstArg = "start";
}
String config = "org/ofbiz/base/start/" + firstArg + ".properties";
Properties props = this.getPropertiesFile(config);
System.out.println("Start.java using configuration file " + config);
// set the ofbiz.home
String ofbizHomeTmp = props.getProperty("ofbiz.home", ".");
// get a full path
if (ofbizHomeTmp.equals(".")) {
ofbizHomeTmp = System.getProperty("user.dir");
ofbizHomeTmp = ofbizHomeTmp.replace('\\', '/');
}
ofbizHome = ofbizHomeTmp;
System.setProperty("ofbiz.home", ofbizHome);
System.out.println("Set OFBIZ_HOME to - " + ofbizHome);
// log directory
logDir = getOfbizHomeProp(props, "ofbiz.log.dir", "runtime/logs");
// container configuration
containerConfig = getOfbizHomeProp(props, "ofbiz.container.config", "framework/base/config/ofbiz-containers.xml");
// get the admin server info
String serverHost = getProp(props, "ofbiz.admin.host", "127.0.0.1");
String adminPortStr = getProp(props, "ofbiz.admin.port", "0");
// set the admin key
adminKey = getProp(props, "ofbiz.admin.key", "NA");
// create the host InetAddress
adminAddress = InetAddress.getByName(serverHost);
// parse the port number
int adminPortTmp;
try {
adminPortTmp = Integer.parseInt(adminPortStr);
if (args.length > 0) {
for (String arg : args) {
if (arg.toLowerCase().contains("portoffset=") && !arg.toLowerCase().contains("${portoffset}")) {
adminPortTmp = adminPortTmp != 0 ? adminPortTmp : 10523; // This is necessary because the ASF machines don't allow ports 1 to 3, see INFRA-6790
adminPortTmp += Integer.parseInt(arg.split("=")[1]);
}
}
}
} catch (Exception e) {
System.out.println("Error while parsing admin port number (so default to 10523) = " + e);
adminPortTmp = 10523;
}
adminPort = adminPortTmp;
// set the Derby system home
String derbyPath = getProp(props, "derby.system.home", "runtime/data/derby");
System.setProperty("derby.system.home", derbyPath);
// check for shutdown hook
if (System.getProperty("ofbiz.enable.hook") != null && System.getProperty("ofbiz.enable.hook").length() > 0) {
useShutdownHook = "true".equalsIgnoreCase(System.getProperty("ofbiz.enable.hook"));
} else if (props.getProperty("ofbiz.enable.hook") != null && props.getProperty("ofbiz.enable.hook").length() > 0) {
useShutdownHook = "true".equalsIgnoreCase(props.getProperty("ofbiz.enable.hook"));
} else {
useShutdownHook = true;
}
// check for auto-shutdown
if (System.getProperty("ofbiz.auto.shutdown") != null && System.getProperty("ofbiz.auto.shutdown").length() > 0) {
shutdownAfterLoad = "true".equalsIgnoreCase(System.getProperty("ofbiz.auto.shutdown"));
} else if (props.getProperty("ofbiz.auto.shutdown") != null && props.getProperty("ofbiz.auto.shutdown").length() > 0) {
shutdownAfterLoad = "true".equalsIgnoreCase(props.getProperty("ofbiz.auto.shutdown"));
} else {
shutdownAfterLoad = false;
}
// set AWT headless mode
awtHeadless = getProp(props, "java.awt.headless", null);
if (awtHeadless != null) {
System.setProperty("java.awt.headless", awtHeadless);
}
// get the splash logo
splashLogo = props.getProperty("ofbiz.start.splash.logo", null);
// set the default locale
String localeString = props.getProperty("ofbiz.locale.default");
if (localeString != null && localeString.length() > 0) {
String locales[] = localeString.split("_");
switch (locales.length) {
case 1:
Locale.setDefault(new Locale(locales[0]));
break;
case 2:
Locale.setDefault(new Locale(locales[0], locales[1]));
break;
case 3:
Locale.setDefault(new Locale(locales[0], locales[1], locales[2]));
}
System.setProperty("user.language", localeString);
}
// set the default time zone
String tzString = props.getProperty("ofbiz.timeZone.default");
if (tzString != null && tzString.length() > 0) {
TimeZone.setDefault(TimeZone.getTimeZone(tzString));
}
instrumenterClassName = getProp(props, "ofbiz.instrumenterClassName", null);
instrumenterFile = getProp(props, "ofbiz.instrumenterFile", null);
// loader classes
List loadersTmp = new ArrayList<Map<String, String>>();
int currentPosition = 1;
Map<String, String> loader = null;
while (true) {
loader = new HashMap<String, String>();
String loaderClass = props.getProperty("ofbiz.start.loader" + currentPosition);
if (loaderClass == null || loaderClass.length() == 0) {
break;
} else {
loader.put("class", loaderClass);
loader.put("profiles", props.getProperty("ofbiz.start.loader" + currentPosition + ".loaders"));
loadersTmp.add(Collections.unmodifiableMap(loader));
currentPosition++;
}
}
loaders = Collections.unmodifiableList(loadersTmp);
// set the port offset
Integer portOffset = 0;
if (args != null) {
for (String argument : args) {
// arguments can prefix w/ a '-'. Just strip them off
if (argument.startsWith("-")) {
int subIdx = 1;
if (argument.startsWith("--")) {
subIdx = 2;
}
argument = argument.substring(subIdx);
}
// parse the arguments
if (argument.indexOf("=") != -1) {
String argumentName = argument.substring(0, argument.indexOf("="));
String argumentVal = argument.substring(argument.indexOf("=") + 1);
if ("portoffset".equalsIgnoreCase(argumentName) && !"${portoffset}".equals(argumentVal)) {
try {
portOffset = Integer.valueOf(argumentVal);
} catch (NumberFormatException e) {
System.out.println("Error while parsing portoffset (the default value 0 will be used) = " + e);
}
}
}
}
}
this.portOffset = portOffset;
}
private String getOfbizHomeProp(Properties props, String key, String def) {
String value = System.getProperty(key);
if (value != null)
return value;
return ofbizHome + "/" + props.getProperty(key, def);
}
private String getProp(Properties props, String key, String def) {
String value = System.getProperty(key);
if (value != null)
return value;
return props.getProperty(key, def);
}
private Properties getPropertiesFile(String config) throws IOException {
InputStream propsStream = null;
Properties props = new Properties();
try {
// first try classpath
propsStream = getClass().getClassLoader().getResourceAsStream(config);
if (propsStream != null) {
props.load(propsStream);
} else {
throw new IOException();
}
} catch (IOException e) {
// next try file location
File propsFile = new File(config);
if (propsFile != null) {
FileInputStream fis = null;
try {
fis = new FileInputStream(propsFile);
if (fis != null) {
props.load(fis);
}
} catch (FileNotFoundException e2) {
// do nothing; we will see empty props below
} finally {
if (fis != null) {
fis.close();
}
}
}
} finally {
if (propsStream != null) {
propsStream.close();
}
}
// check for empty properties
if (props.isEmpty()) {
throw new IOException("Cannot load configuration properties : " + config);
}
return props;
}
void initClasspath(Classpath classPath, Classpath libraryPath) throws Exception {
// add OFBIZ_HOME to class path
classPath.addClasspath(this.ofbizHome);
File home = new File(this.ofbizHome);
collectClasspathEntries(new File(home, "framework"), classPath, libraryPath);
collectClasspathEntries(new File(home, "applications"), classPath, libraryPath);
collectClasspathEntries(new File(home, "specialpurpose"), classPath, libraryPath);
collectClasspathEntries(new File(home, "hot-deploy"), classPath, libraryPath);
System.setProperty("java.library.path", libraryPath.toString());
classPath.instrument(this.instrumenterFile, this.instrumenterClassName);
}
private void collectClasspathEntries(File folder, Classpath classpath, Classpath libraryPath) throws ParserConfigurationException, IOException, SAXException {
if (!folder.exists() && !folder.isDirectory()) {
return;
}
FileFilter componentLoadFilter = new FileFilter() {
public boolean accept(File pathname) {
return "component-load.xml".equals(pathname.getName());
}
};
FileFilter folderFilter = new FileFilter() {
public boolean accept(File pathname) {
return pathname.isDirectory();
}
};
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
File[] componentLoadFiles;
List<File> ofbizComponents = new ArrayList<File>();
componentLoadFiles = folder.listFiles(componentLoadFilter);
if (componentLoadFiles != null && componentLoadFiles.length == 1) {
File componentLoadFile = componentLoadFiles[0];
// parse and get folder names to be processed
Document document = builder.parse(componentLoadFile);
Element element = document.getDocumentElement();
NodeList loadComponents = element.getElementsByTagName("load-component");
for (int i = 0; i < loadComponents.getLength(); i++) {
Node loadComponent = loadComponents.item(i);
NamedNodeMap attributes = loadComponent.getAttributes();
Node componentLocation = attributes.getNamedItem("component-location");
if (componentLocation == null) {
continue;
}
ofbizComponents.add(new File(new File(folder, componentLocation.getNodeValue()), "ofbiz-component.xml"));
}
} else {
File[] componentFolders = folder.listFiles(folderFilter);
for (File componentFolder: componentFolders) {
File ofbizComponent = new File(componentFolder, "ofbiz-component.xml");
if (ofbizComponent.exists()) {
ofbizComponents.add(ofbizComponent);
}
}
}
String nativeLibExt = System.mapLibraryName("someLib").replace("someLib", "").toLowerCase();
for (File ofbizComponent: ofbizComponents) {
Document document = builder.parse(ofbizComponent);
Element element = document.getDocumentElement();
if (element.hasAttribute("enabled")) {
if ("false".equals(element.getAttribute("enabled"))) {
continue;
}
}
NodeList classpathEntries = element.getElementsByTagName("classpath");
for (int i = 0; i < classpathEntries.getLength(); i++) {
Node classpathEntry = classpathEntries.item(i);
NamedNodeMap attributes = classpathEntry.getAttributes();
Node type = attributes.getNamedItem("type");
if (type == null || !("jar".equals(type.getNodeValue()) || "dir".equals(type.getNodeValue()))) {
continue;
}
Node location = attributes.getNamedItem("location");
String locationValue = location.getNodeValue();
locationValue = locationValue.replace('\\', '/');
// set the location to not have a leading slash
if (locationValue.startsWith("/")) {
locationValue = locationValue.substring(1);
}
String dirLoc = locationValue;
if (dirLoc.endsWith("/*")) {
// strip off the slash splat
dirLoc = locationValue.substring(0, locationValue.length() - 2);
}
String fileNameSeparator = ("\\".equals(File.separator) ? "\\" + File.separator : File.separator);
dirLoc = dirLoc.replaceAll("/+|\\\\+", fileNameSeparator);
File path = new File(ofbizComponent.getParent(), dirLoc);
if (path.exists()) {
if (path.isDirectory()) {
if ("dir".equals(type.getNodeValue())) {
classpath.addComponent(path.toString());
}
// load all .jar, .zip files and native libs in this directory
boolean containsNativeLibs = false;
for (File file: path.listFiles()) {
String fileName = file.getName().toLowerCase();
if (fileName.endsWith(".jar") || fileName.endsWith(".zip")) {
classpath.addComponent(file);
} else if (fileName.endsWith(nativeLibExt)) {
containsNativeLibs = true;
}
}
if (containsNativeLibs) {
libraryPath.addComponent(path);
}
} else {
classpath.addComponent(path.toString());
}
}
}
}
}
}