From 0e4556215f426832bb66ab86e2eca9b448bc61e5 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Thu, 30 Jul 2015 07:23:02 -0500 Subject: Bug 446571 - Many settings not configurable via config.ini (including osgi.compatibility.bootdelegation) --- .../osgi/tests/bundles/SystemBundleTests.java | 57 +++ .../eclipse/osgi/tests/configuration/AllTests.java | 3 +- .../configuration/EclipseStarterConfigIniTest.java | 81 ++++ .../core/runtime/adaptor/EclipseStarter.java | 14 +- .../internal/framework/EquinoxConfiguration.java | 467 +++++++++++++-------- .../osgi/internal/framework/EquinoxContainer.java | 64 +-- .../osgi/internal/location/BasicLocation.java | 27 +- .../osgi/internal/location/EquinoxLocations.java | 23 +- .../osgi/internal/log/EquinoxLogServices.java | 5 +- 9 files changed, 489 insertions(+), 252 deletions(-) create mode 100644 bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/configuration/EclipseStarterConfigIniTest.java mode change 100644 => 100755 bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/location/BasicLocation.java mode change 100644 => 100755 bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/location/EquinoxLocations.java diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java index c70590f14..33cda2022 100644 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java @@ -17,6 +17,7 @@ import java.security.PrivilegedAction; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.jar.*; +import javax.net.SocketFactory; import junit.framework.Test; import junit.framework.TestSuite; import org.eclipse.core.runtime.adaptor.EclipseStarter; @@ -2390,6 +2391,62 @@ public class SystemBundleTests extends AbstractBundleTests { equinox.stop(); } + public void testBootDelegationConfigIni() throws BundleException, IOException, InterruptedException { + String compatBootDelegate = "osgi.compatibility.bootdelegation"; + File config = OSGiTestsActivator.getContext().getDataFile(getName()); + config.mkdirs(); + Properties configIni = new Properties(); + // use config.ini to override the default for the embedded case. + // note that the embedded case the default for this setting is false + configIni.setProperty(compatBootDelegate, "true"); + configIni.store(new FileWriter(new File(config, "config.ini")), null); + Map configuration = new HashMap(); + configuration.put(Constants.FRAMEWORK_STORAGE, config.getAbsolutePath()); + Equinox equinox = new Equinox(configuration); + equinox.start(); + BundleContext systemContext = equinox.getBundleContext(); + assertEquals("Wrong value for: " + compatBootDelegate, "true", systemContext.getProperty(compatBootDelegate)); + + File bundleFile = null; + try { + File baseDir = new File(config, "bundles"); + baseDir.mkdirs(); + bundleFile = createBundle(baseDir, getName(), true, true); + } catch (IOException e) { + fail("Unexpected error creating bundles.", e); + } + Bundle b = null; + try { + b = systemContext.installBundle("reference:file:///" + bundleFile.getAbsolutePath()); //$NON-NLS-1$ + } catch (BundleException e) { + fail("Unexpected install error", e); //$NON-NLS-1$ + } + try { + b.loadClass(SocketFactory.class.getName()); + } catch (ClassNotFoundException e) { + fail("Expected to be able to load the class from boot.", e); + } + long bId = b.getBundleId(); + equinox.stop(); + equinox.waitForStop(5000); + + // remove the setting to ensure false is used for the embedded case + configIni.remove(compatBootDelegate); + configIni.store(new FileWriter(new File(config, "config.ini")), null); + equinox = new Equinox(configuration); + equinox.start(); + + systemContext = equinox.getBundleContext(); + b = systemContext.getBundle(bId); + try { + b.loadClass(SocketFactory.class.getName()); + fail("Expected to fail to load the class from boot."); + } catch (ClassNotFoundException e) { + // expected + } + equinox.stop(); + } + private static File[] createBundles(File outputDir, int bundleCount) throws IOException { outputDir.mkdirs(); diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/configuration/AllTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/configuration/AllTests.java index cd71d8f81..e22acfac7 100644 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/configuration/AllTests.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/configuration/AllTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2013 IBM Corporation and others. + * Copyright (c) 2004, 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -16,6 +16,7 @@ import junit.framework.TestSuite; public class AllTests { public static Test suite() { TestSuite suite = new TestSuite(AllTests.class.getName()); + suite.addTest(EclipseStarterConfigIniTest.suite()); suite.addTest(EclipseStarterConfigurationAreaTest.suite()); suite.addTest(ReadOnlyConfigurationAreaTest.suite()); suite.addTest(MovableConfigurationAreaTest.suite()); diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/configuration/EclipseStarterConfigIniTest.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/configuration/EclipseStarterConfigIniTest.java new file mode 100644 index 000000000..2e2cf4f02 --- /dev/null +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/configuration/EclipseStarterConfigIniTest.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2015 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.osgi.tests.configuration; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; +import junit.framework.Test; +import junit.framework.TestSuite; +import org.eclipse.core.tests.session.ConfigurationSessionTestSuite; +import org.eclipse.osgi.tests.OSGiTest; +import org.eclipse.osgi.tests.OSGiTestsActivator; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; + +public class EclipseStarterConfigIniTest extends OSGiTest { + + public static Test suite() { + TestSuite suite = new TestSuite(EclipseStarterConfigIniTest.class.getName()); + + ConfigurationSessionTestSuite falseCompatBootDelegation = new ConfigurationSessionTestSuite(PI_OSGI_TESTS, EclipseStarterConfigIniTest.class.getName()); + String[] ids = ConfigurationSessionTestSuite.MINIMAL_BUNDLE_SET; + for (int i = 0; i < ids.length; i++) + falseCompatBootDelegation.addBundle(ids[i]); + falseCompatBootDelegation.addBundle(PI_OSGI_TESTS); + falseCompatBootDelegation.addTest(new EclipseStarterConfigIniTest("testFalseCompatBootDelegation")); + falseCompatBootDelegation.setConfigIniValue("osgi.compatibility.bootdelegation", "false"); + suite.addTest(falseCompatBootDelegation); + + ConfigurationSessionTestSuite defaultCompatBootDelegation = new ConfigurationSessionTestSuite(PI_OSGI_TESTS, EclipseStarterConfigIniTest.class.getName()); + for (int i = 0; i < ids.length; i++) + defaultCompatBootDelegation.addBundle(ids[i]); + defaultCompatBootDelegation.addBundle(PI_OSGI_TESTS); + defaultCompatBootDelegation.addTest(new EclipseStarterConfigIniTest("testDefaultCompatBootDelegation")); + suite.addTest(defaultCompatBootDelegation); + return suite; + } + + public EclipseStarterConfigIniTest(String name) { + super(name); + } + + public void testFalseCompatBootDelegation() throws Exception { + doTestCompatBootDelegation(true); + } + + public void testDefaultCompatBootDelegation() throws Exception { + doTestCompatBootDelegation(false); + } + + public void doTestCompatBootDelegation(boolean expectFailure) throws Exception { + BundleContext context = OSGiTestsActivator.getContext(); + ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); + ZipOutputStream zipOut = new ZipOutputStream(bytesOut); + zipOut.putNextEntry(new ZipEntry("nothing")); + zipOut.closeEntry(); + zipOut.close(); + Bundle b = context.installBundle(getName(), new ByteArrayInputStream(bytesOut.toByteArray())); + String testClassName = javax.net.SocketFactory.class.getName(); + // The bundle does not import anything so should not find javax stuff + try { + b.loadClass(testClassName); + if (expectFailure) { + fail("Expected to fail to load VM class from bundle that does not import it"); + } + } catch (ClassNotFoundException e) { + if (!expectFailure) { + fail("Expected to successfully load VM class from bundle that does not import it", e); + } + } + } +} diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/adaptor/EclipseStarter.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/adaptor/EclipseStarter.java index 7961a7367..07acf360c 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/adaptor/EclipseStarter.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/adaptor/EclipseStarter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2014 IBM Corporation and others. + * Copyright (c) 2003, 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -186,9 +186,17 @@ public class EclipseStarter { if (configuration == null) { configuration = new HashMap(); // TODO hack to set these to defaults for EclipseStarter - // Note that this hack does not allow these properties to be specified in config.ini + // Note that this hack does not allow this property to be specified in config.ini configuration.put(EquinoxConfiguration.PROP_USE_SYSTEM_PROPERTIES, System.getProperty(EquinoxConfiguration.PROP_USE_SYSTEM_PROPERTIES, "true")); //$NON-NLS-1$ - configuration.put(EquinoxConfiguration.PROP_COMPATIBILITY_BOOTDELEGATION, System.getProperty(EquinoxConfiguration.PROP_COMPATIBILITY_BOOTDELEGATION, "true")); //$NON-NLS-1$ + // we handle this compatibility setting special for EclipseStarter + String systemCompatibilityBoot = System.getProperty(EquinoxConfiguration.PROP_COMPATIBILITY_BOOTDELEGATION); + if (systemCompatibilityBoot != null) { + // The system properties have a specific setting; use it + configuration.put(EquinoxConfiguration.PROP_COMPATIBILITY_BOOTDELEGATION, systemCompatibilityBoot); + } else { + // set a default value; but this value can be overriden by the config.ini + configuration.put(EquinoxConfiguration.PROP_COMPATIBILITY_BOOTDELEGATION + EquinoxConfiguration.PROP_DEFAULT_SUFFIX, "true"); //$NON-NLS-1$ + } } return configuration; } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java index bb50bb8eb..f8fb4ec04 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java @@ -27,12 +27,14 @@ import java.net.*; import java.security.CodeSource; import java.security.ProtectionDomain; import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.core.runtime.internal.adaptor.ConsoleManager; import org.eclipse.osgi.internal.debug.Debug; import org.eclipse.osgi.internal.debug.FrameworkDebugOptions; import org.eclipse.osgi.internal.hookregistry.HookRegistry; import org.eclipse.osgi.internal.location.EquinoxLocations; import org.eclipse.osgi.internal.messages.Msg; +import org.eclipse.osgi.service.datalocation.Location; import org.eclipse.osgi.service.debug.DebugOptions; import org.eclipse.osgi.service.environment.Constants; import org.eclipse.osgi.service.environment.EnvironmentInfo; @@ -44,6 +46,7 @@ import org.osgi.framework.Version; * Internal class. */ public class EquinoxConfiguration implements EnvironmentInfo { + private static final String CONFIG_FILE = "config.ini"; //$NON-NLS-1$ // While we recognize the SunOS operating system, we change // this internally to be Solaris. private static final String INTERNAL_OS_SUNOS = "SunOS"; //$NON-NLS-1$ @@ -65,14 +68,13 @@ public class EquinoxConfiguration implements EnvironmentInfo { public static final String VARIABLE_DELIM_STRING = "$"; //$NON-NLS-1$ public static final char VARIABLE_DELIM_CHAR = '$'; - private final Map initialConfig; - private final Properties configuration; - private final boolean useSystemProperties; + private final ConfigValues configValues; private final Debug debug; private final DebugOptions debugOptions; private final HookRegistry hookRegistry; private final AliasMapper aliasMapper = new AliasMapper(); + private final EquinoxLocations equinoxLocations; private volatile String[] allArgs; private volatile String[] frameworkArgs; @@ -194,46 +196,286 @@ public class EquinoxConfiguration implements EnvironmentInfo { public static final String PROP_RESOLVER_REVISION_BATCH_SIZE = "equinox.resolver.revision.batch.size"; //$NON-NLS-1$ - private final static Collection populateInitConfig = Arrays.asList(PROP_OSGI_ARCH, PROP_OSGI_OS, PROP_OSGI_WS, PROP_OSGI_NL, FRAMEWORK_OS_NAME, FRAMEWORK_OS_VERSION, FRAMEWORK_PROCESSOR, FRAMEWORK_LANGUAGE); + public static final String PROP_DEFAULT_SUFFIX = ".default"; //$NON-NLS-1$ + public static final Collection PROP_WITH_ECLIPSE_STARTER_DEFAULTS = Collections.singletonList(PROP_COMPATIBILITY_BOOTDELEGATION); - /** - * Value of {@link #configuration} properties that should be considered - * null and for which access should not fall back to - * {@link System#getProperty(String)}. - * The instance must be compared by identity (==, not equals) and must not - * be leaked outside this class. - */ - private final static String NULL_CONFIG = new String("org.eclipse.equinox.configuration.null.value"); //$NON-NLS-1$ - - EquinoxConfiguration(Map initialConfiguration, HookRegistry hookRegistry) { - this.initialConfig = initialConfiguration == null ? new HashMap(0) : new HashMap(initialConfiguration); - this.hookRegistry = hookRegistry; - Object useSystemPropsValue = initialConfig.get(PROP_USE_SYSTEM_PROPERTIES); - this.useSystemProperties = useSystemPropsValue == null ? false : Boolean.parseBoolean(useSystemPropsValue.toString()); - this.configuration = useSystemProperties ? System.getProperties() : new Properties(); - // do this the hard way to handle null values - for (Map.Entry initialEntry : this.initialConfig.entrySet()) { - if (initialEntry.getValue() == null) { - if (useSystemProperties) { - this.configuration.remove(initialEntry.getKey()); + public static final class ConfigValues { + /** + * Value of {@link #configuration} properties that should be considered + * null and for which access should not fall back to + * {@link System#getProperty(String)}. + * The instance must be compared by identity (==, not equals) and must not + * be leaked outside this class. + */ + private final static String NULL_CONFIG = new String("org.eclipse.equinox.configuration.null.value"); //$NON-NLS-1$ + private final static Collection populateInitConfig = Arrays.asList(PROP_OSGI_ARCH, PROP_OSGI_OS, PROP_OSGI_WS, PROP_OSGI_NL, FRAMEWORK_OS_NAME, FRAMEWORK_OS_VERSION, FRAMEWORK_PROCESSOR, FRAMEWORK_LANGUAGE); + + private final boolean useSystemProperties; + private final Map initialConfig; + private final Properties configuration; + + public ConfigValues(Map initialConfiguration) { + this.initialConfig = initialConfiguration == null ? new HashMap(0) : new HashMap(initialConfiguration); + Object useSystemPropsValue = initialConfig.get(PROP_USE_SYSTEM_PROPERTIES); + this.useSystemProperties = useSystemPropsValue == null ? false : Boolean.parseBoolean(useSystemPropsValue.toString()); + this.configuration = useSystemProperties ? System.getProperties() : new Properties(); + // do this the hard way to handle null values + for (Map.Entry initialEntry : this.initialConfig.entrySet()) { + if (initialEntry.getValue() == null) { + if (useSystemProperties) { + this.configuration.remove(initialEntry.getKey()); + } else { + this.configuration.put(initialEntry.getKey(), NULL_CONFIG); + } } else { - this.configuration.put(initialEntry.getKey(), NULL_CONFIG); + this.configuration.put(initialEntry.getKey(), initialEntry.getValue()); } + } + } + + void loadConfigIni(URL configIni) { + if (configIni != null) { + mergeConfiguration(loadProperties(configIni)); + } + } + + void finalizeValues() { + // populate initConfig after loading the configIni + for (String initialKey : populateInitConfig) { + String value = getConfiguration(initialKey); + if (value != null) { + this.initialConfig.put(initialKey, value); + } + } + + // look for special case EclipseStarter defaults + for (String keyWithEclipseStarterDefault : PROP_WITH_ECLIPSE_STARTER_DEFAULTS) { + String currentValue = getConfiguration(keyWithEclipseStarterDefault); + if (currentValue == null) { + String defaultValue = getConfiguration(keyWithEclipseStarterDefault + PROP_DEFAULT_SUFFIX); + if (defaultValue != null) { + setConfiguration(keyWithEclipseStarterDefault, defaultValue); + } + } + } + + // set other defaults + if (FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT.equals(getConfiguration(FRAMEWORK_STORAGE_CLEAN))) { + setConfiguration(PROP_CLEAN, "true"); //$NON-NLS-1$ + } + + if (getConfiguration(PROP_STATE_SAVE_DELAY_INTERVAL) == null) + // Property not specified. Use the default. + setConfiguration(PROP_STATE_SAVE_DELAY_INTERVAL, DEFAULT_STATE_SAVE_DELAY_INTERVAL); + try { + // Verify type compatibility. + Long.parseLong(getConfiguration(PROP_STATE_SAVE_DELAY_INTERVAL)); + } catch (NumberFormatException e) { + // TODO Consider logging here. + // The specified value is not type compatible. Use the default. + setConfiguration(PROP_STATE_SAVE_DELAY_INTERVAL, DEFAULT_STATE_SAVE_DELAY_INTERVAL); + } + + String consoleProp = getConfiguration(ConsoleManager.PROP_CONSOLE); + consoleProp = consoleProp == null ? null : consoleProp.trim(); + if (consoleProp == null || consoleProp.length() > 0) { + // no -console was specified or it has specified none or a port for telnet; + // need to make sure the gogo shell does not create an interactive console on standard in/out + setConfiguration("gosh.args", "--nointeractive"); //$NON-NLS-1$//$NON-NLS-2$ } else { - this.configuration.put(initialEntry.getKey(), initialEntry.getValue()); + // Need to make sure we don't shutdown the framework if no console is around (bug 362412) + setConfiguration("gosh.args", "--noshutdown"); //$NON-NLS-1$//$NON-NLS-2$ } } - initializeProperties(); - for (String initialKey : populateInitConfig) { - String value = getConfiguration(initialKey); - if (value != null) { - this.initialConfig.put(initialKey, value); + private void mergeConfiguration(Properties source) { + for (Enumeration e = source.keys(); e.hasMoreElements();) { + String key = (String) e.nextElement(); + String value = source.getProperty(key); + if (getConfiguration(key) == null) { + setProperty(key, value); + initialConfig.put(key, value); + } else { + initialConfig.put(key, getConfiguration(key)); + } + } + } + + private Properties loadProperties(URL location) { + Properties result = new Properties(); + if (location == null) + return result; + try { + InputStream in = location.openStream(); + try { + result.load(in); + } finally { + in.close(); + } + } catch (IOException e) { + // its ok if there is no file. We'll just use the defaults for everything + // TODO but it might be nice to log something with gentle wording (i.e., it is not an error) } + return substituteVars(result); } + private Properties substituteVars(Properties result) { + if (result == null) { + //nothing todo. + return null; + } + for (Enumeration eKeys = result.keys(); eKeys.hasMoreElements();) { + Object key = eKeys.nextElement(); + if (key instanceof String) { + String value = result.getProperty((String) key); + if (value != null) + result.put(key, substituteVars(value, true)); + } + } + return result; + } + + public String substituteVars(String path, boolean preserveDelimiters) { + StringBuffer buf = new StringBuffer(path.length()); + StringTokenizer st = new StringTokenizer(path, VARIABLE_DELIM_STRING, true); + boolean varStarted = false; // indicates we are processing a var subtitute + String var = null; // the current var key + while (st.hasMoreElements()) { + String tok = st.nextToken(); + if (VARIABLE_DELIM_STRING.equals(tok)) { + if (!varStarted) { + varStarted = true; // we found the start of a var + var = ""; //$NON-NLS-1$ + } else { + // we have found the end of a var + String prop = null; + // get the value of the var from system properties + if (var != null && var.length() > 0) + prop = getProperty(var); + if (prop == null) { + try { + // try using the System.getenv method if it exists (bug 126921) + Method getenv = System.class.getMethod("getenv", new Class[] {String.class}); //$NON-NLS-1$ + prop = (String) getenv.invoke(null, new Object[] {var}); + } catch (Throwable t) { + // do nothing; + // on 1.4 VMs this throws an error + // on J2ME this method does not exist + } + } + if (prop != null) { + // found a value; use it + buf.append(prop); + } else { + // could not find a value append the var + if (preserveDelimiters) { + buf.append(VARIABLE_DELIM_CHAR); + } + buf.append(var == null ? "" : var); //$NON-NLS-1$ + if (preserveDelimiters) { + buf.append(VARIABLE_DELIM_CHAR); + } + } + varStarted = false; + var = null; + } + } else { + if (!varStarted) + buf.append(tok); // the token is not part of a var + else + var = tok; // the token is the var key; save the key to process when we find the end token + } + } + if (var != null) + // found a case of $var at the end of the path with no trailing $; just append it as is. + buf.append(VARIABLE_DELIM_CHAR).append(var); + return buf.toString(); + } + + public String getProperty(String key) { + // have to access configuration directly instead of using getConfiguration to get access to NULL_CONFIG values + String result = configuration.getProperty(key); + if (result == NULL_CONFIG) { + return null; + } + return result == null ? System.getProperty(key) : result; + } + + public String setProperty(String key, String value) { + if (value == null) { + return clearConfiguration(key); + } + return setConfiguration(key, value); + } + + public String getConfiguration(String key) { + String result = configuration.getProperty(key); + return result == NULL_CONFIG ? null : result; + } + + public String getConfiguration(String key, String defaultValue) { + String result = getConfiguration(key); + return result == null ? defaultValue : result; + } + + public String setConfiguration(String key, String value) { + Object result = configuration.put(key, value); + return result instanceof String && result != NULL_CONFIG ? (String) result : null; + } + + public String clearConfiguration(String key) { + Object result = configuration.remove(key); + if (!useSystemProperties) { + configuration.put(key, NULL_CONFIG); + } + return result instanceof String && result != NULL_CONFIG ? (String) result : null; + } + + public Map getConfiguration() { + // must sync on configuration to avoid concurrent modification exception + synchronized (configuration) { + Map result = new HashMap(configuration.size()); + for (Object key : configuration.keySet()) { + if (key instanceof String) { + String skey = (String) key; + String sValue = configuration.getProperty(skey); + if (sValue != NULL_CONFIG) { + result.put(skey, sValue); + } + } + } + return result; + } + } + + public Map getInitialConfig() { + return Collections.unmodifiableMap(initialConfig); + } + } + + EquinoxConfiguration(Map initialConfiguration, HookRegistry hookRegistry) { + this.hookRegistry = hookRegistry; + // Care must be taken to bootstrap of the config values properly + // A separate class is used to hold the configuration maps so that we can pass them + // to the EquionxLocations before the EquinoxConfiguration has been fully constructed + this.configValues = new ConfigValues(initialConfiguration); + + // We need to initialize some properties always before constructing the EquinoxLocations + initializeProperties(); + + // At this point we do not know if we want to debug locations because we have not detemined if osgi.debug is set yet + // We use an AttomicBoolean to hold the setting so we can set it after the config.ini has been loaded + AtomicBoolean debugLocations = new AtomicBoolean(); + this.equinoxLocations = new EquinoxLocations(this.configValues, this.hookRegistry.getContainer(), debugLocations); + this.configValues.loadConfigIni(getConfigIni(equinoxLocations)); + this.configValues.finalizeValues(); + this.debugOptions = new FrameworkDebugOptions(this); this.debug = new Debug(this.debugOptions); + // finally we know if locations should be debugged. + debugLocations.set(debug.DEBUG_LOCATION); + + // Finally we can set all our variables according to the configuration values String osgiDev = getConfiguration(PROP_DEV); File f = null; @@ -285,7 +527,7 @@ public class EquinoxConfiguration implements EnvironmentInfo { BSN_VERSION = BSN_VERSION_MANAGED; } - BUNDLE_SET_TCCL = "true".equals(getConfiguration("eclipse.bundle.setTCCL", "true")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + BUNDLE_SET_TCCL = "true".equals(getConfiguration(PROP_BUNDLE_SETTCCL, "true")); //$NON-NLS-1$ //$NON-NLS-2$ throwErrorOnFailedStart = "true".equals(getConfiguration(PROP_COMPATIBILITY_ERROR_FAILED_START, "true")); //$NON-NLS-1$//$NON-NLS-2$ @@ -301,8 +543,22 @@ public class EquinoxConfiguration implements EnvironmentInfo { } } + private URL getConfigIni(EquinoxLocations equinoxLocations2) { + if (Boolean.TRUE.toString().equals(getConfiguration(EquinoxConfiguration.PROP_IGNORE_USER_CONFIGURATION))) + return null; + Location configArea = equinoxLocations.getConfigurationLocation(); + if (configArea == null) + return null; + try { + return new URL(configArea.getURL().toExternalForm() + CONFIG_FILE); + } catch (MalformedURLException e) { + // its ok. This should never happen + } + return null; + } + public Map getInitialConfig() { - return Collections.unmodifiableMap(initialConfig); + return this.configValues.getInitialConfig(); } private static List buildEclipseLibraryVariants(String ws, String os, String arch, String nl) { @@ -443,43 +699,23 @@ public class EquinoxConfiguration implements EnvironmentInfo { } public String getConfiguration(String key) { - String result = configuration.getProperty(key); - return result == NULL_CONFIG ? null : result; + return this.configValues.getConfiguration(key); } public String getConfiguration(String key, String defaultValue) { - String result = getConfiguration(key); - return result == null ? defaultValue : result; + return this.configValues.getConfiguration(key, defaultValue); } public String setConfiguration(String key, String value) { - Object result = configuration.put(key, value); - return result instanceof String && result != NULL_CONFIG ? (String) result : null; + return this.configValues.setConfiguration(key, value); } public String clearConfiguration(String key) { - Object result = configuration.remove(key); - if (!useSystemProperties) { - configuration.put(key, NULL_CONFIG); - } - return result instanceof String && result != NULL_CONFIG ? (String) result : null; + return this.configValues.clearConfiguration(key); } public Map getConfiguration() { - // must sync on configuration to avoid concurrent modification exception - synchronized (configuration) { - Map result = new HashMap(configuration.size()); - for (Object key : configuration.keySet()) { - if (key instanceof String) { - String skey = (String) key; - String sValue = configuration.getProperty(skey); - if (sValue != NULL_CONFIG) { - result.put(skey, sValue); - } - } - } - return result; - } + return this.configValues.getConfiguration(); } public Debug getDebug() { @@ -496,20 +732,12 @@ public class EquinoxConfiguration implements EnvironmentInfo { @Override public String getProperty(String key) { - // have to access configuration directly instead of using getConfiguration to get access to NULL_CONFIG values - String result = configuration.getProperty(key); - if (result == NULL_CONFIG) { - return null; - } - return result == null ? System.getProperty(key) : result; + return this.configValues.getProperty(key); } @Override public String setProperty(String key, String value) { - if (value == null) { - return clearConfiguration(key); - } - return setConfiguration(key, value); + return this.configValues.setProperty(key, value); } public AliasMapper getAliasMapper() { @@ -603,35 +831,8 @@ public class EquinoxConfiguration implements EnvironmentInfo { } } - void mergeConfiguration(Properties source) { - for (Enumeration e = source.keys(); e.hasMoreElements();) { - String key = (String) e.nextElement(); - String value = source.getProperty(key); - if (getConfiguration(key) == null) { - setProperty(key, value); - initialConfig.put(key, value); - } else { - initialConfig.put(key, getConfiguration(key)); - } - } - } - - private void initializeStateSaveDelayIntervalProperty() { - if (getConfiguration(PROP_STATE_SAVE_DELAY_INTERVAL) == null) - // Property not specified. Use the default. - setConfiguration(PROP_STATE_SAVE_DELAY_INTERVAL, DEFAULT_STATE_SAVE_DELAY_INTERVAL); - try { - // Verify type compatibility. - Long.parseLong(getConfiguration(PROP_STATE_SAVE_DELAY_INTERVAL)); - } catch (NumberFormatException e) { - // TODO Consider logging here. - // The specified value is not type compatible. Use the default. - setConfiguration(PROP_STATE_SAVE_DELAY_INTERVAL, DEFAULT_STATE_SAVE_DELAY_INTERVAL); - } - } - private void initializeProperties() { - // initialize some framework properties that must always be set + // initialize some framework properties that must always be set AND cannot be set with config.ini if (getConfiguration(PROP_FRAMEWORK) == null || getConfiguration(EquinoxLocations.PROP_INSTALL_AREA) == null) { ProtectionDomain pd = EquinoxConfiguration.class.getProtectionDomain(); CodeSource cs = pd == null ? null : pd.getCodeSource(); @@ -733,9 +934,6 @@ public class EquinoxConfiguration implements EnvironmentInfo { setConfiguration(SUPPORTS_FRAMEWORK_FRAGMENT, "true"); //$NON-NLS-1$ setConfiguration(SUPPORTS_FRAMEWORK_REQUIREBUNDLE, "true"); //$NON-NLS-1$ setConfiguration(SUPPORTS_FRAMEWORK_EXTENSION, "true"); //$NON-NLS-1$ - if (FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT.equals(getConfiguration(FRAMEWORK_STORAGE_CLEAN))) { - setConfiguration(PROP_CLEAN, "true"); //$NON-NLS-1$ - } /* * Initializes the execution context for this run of the platform. The context @@ -788,18 +986,6 @@ public class EquinoxConfiguration implements EnvironmentInfo { archValue = name; setConfiguration(PROP_OSGI_ARCH, archValue); } - initializeStateSaveDelayIntervalProperty(); - - String consoleProp = getConfiguration(ConsoleManager.PROP_CONSOLE); - consoleProp = consoleProp == null ? null : consoleProp.trim(); - if (consoleProp == null || consoleProp.length() > 0) { - // no -console was specified or it has specified none or a port for telnet; - // need to make sure the gogo shell does not create an interactive console on standard in/out - setConfiguration("gosh.args", "--nointeractive"); //$NON-NLS-1$//$NON-NLS-2$ - } else { - // Need to make sure we don't shutdown the framework if no console is around (bug 362412) - setConfiguration("gosh.args", "--noshutdown"); //$NON-NLS-1$//$NON-NLS-2$ - } } private static String getFrameworkPath(String path, boolean parent) { @@ -867,60 +1053,7 @@ public class EquinoxConfiguration implements EnvironmentInfo { } public String substituteVars(String path, boolean preserveDelimiters) { - StringBuffer buf = new StringBuffer(path.length()); - StringTokenizer st = new StringTokenizer(path, VARIABLE_DELIM_STRING, true); - boolean varStarted = false; // indicates we are processing a var subtitute - String var = null; // the current var key - while (st.hasMoreElements()) { - String tok = st.nextToken(); - if (VARIABLE_DELIM_STRING.equals(tok)) { - if (!varStarted) { - varStarted = true; // we found the start of a var - var = ""; //$NON-NLS-1$ - } else { - // we have found the end of a var - String prop = null; - // get the value of the var from system properties - if (var != null && var.length() > 0) - prop = getProperty(var); - if (prop == null) { - try { - // try using the System.getenv method if it exists (bug 126921) - Method getenv = System.class.getMethod("getenv", new Class[] {String.class}); //$NON-NLS-1$ - prop = (String) getenv.invoke(null, new Object[] {var}); - } catch (Throwable t) { - // do nothing; - // on 1.4 VMs this throws an error - // on J2ME this method does not exist - } - } - if (prop != null) { - // found a value; use it - buf.append(prop); - } else { - // could not find a value append the var - if (preserveDelimiters) { - buf.append(VARIABLE_DELIM_CHAR); - } - buf.append(var == null ? "" : var); //$NON-NLS-1$ - if (preserveDelimiters) { - buf.append(VARIABLE_DELIM_CHAR); - } - } - varStarted = false; - var = null; - } - } else { - if (!varStarted) - buf.append(tok); // the token is not part of a var - else - var = tok; // the token is the var key; save the key to process when we find the end token - } - } - if (var != null) - // found a case of $var at the end of the path with no trailing $; just append it as is. - buf.append(VARIABLE_DELIM_CHAR).append(var); - return buf.toString(); + return this.configValues.substituteVars(path, preserveDelimiters); } /** @@ -997,4 +1130,8 @@ public class EquinoxConfiguration implements EnvironmentInfo { return new Locale(language, country, variant); } + + public EquinoxLocations getEquinoxLocations() { + return equinoxLocations; + } } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainer.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainer.java index f3b7fc444..6a4b19d21 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainer.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2014 IBM Corporation and others. + * Copyright (c) 2012, 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -11,9 +11,6 @@ package org.eclipse.osgi.internal.framework; import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; import java.security.AccessController; import java.util.*; import java.util.concurrent.*; @@ -28,7 +25,6 @@ import org.eclipse.osgi.internal.location.EquinoxLocations; import org.eclipse.osgi.internal.log.EquinoxLogServices; import org.eclipse.osgi.internal.messages.Msg; import org.eclipse.osgi.internal.serviceregistry.ServiceRegistry; -import org.eclipse.osgi.service.datalocation.Location; import org.eclipse.osgi.signedcontent.SignedContentFactory; import org.eclipse.osgi.storage.Storage; import org.eclipse.osgi.util.ManifestElement; @@ -41,11 +37,9 @@ import org.osgi.util.tracker.ServiceTracker; @SuppressWarnings("deprecation") public class EquinoxContainer implements ThreadFactory, Runnable { public static final String NAME = "org.eclipse.osgi"; //$NON-NLS-1$ - private static final String CONFIG_FILE = "config.ini"; //$NON-NLS-1$ static final SecureAction secureAction = AccessController.doPrivileged(SecureAction.createSecureAction()); private final EquinoxConfiguration equinoxConfig; - private final EquinoxLocations equinoxLocations; private final EquinoxLogServices logServices; private final Storage storage; private final PackageAdmin packageAdmin; @@ -67,9 +61,7 @@ public class EquinoxContainer implements ThreadFactory, Runnable { public EquinoxContainer(Map configuration) { this.equinoxConfig = new EquinoxConfiguration(configuration, new HookRegistry(this)); - this.equinoxLocations = new EquinoxLocations(this.equinoxConfig); - loadConfig(equinoxConfig, equinoxLocations); - this.logServices = new EquinoxLogServices(this.equinoxConfig, this.equinoxLocations.getConfigurationLocation()); + this.logServices = new EquinoxLogServices(this.equinoxConfig); this.equinoxConfig.getHookRegistry().initialize(); try { this.storage = Storage.createStorage(this); @@ -107,56 +99,6 @@ public class EquinoxContainer implements ThreadFactory, Runnable { bootDelegationStems = stemMatch.isEmpty() ? null : stemMatch.toArray(new String[stemMatch.size()]); } - private static void loadConfig(EquinoxConfiguration equinoxConfig, EquinoxLocations equinoxLocations) { - if (Boolean.TRUE.toString().equals(equinoxConfig.getConfiguration(EquinoxConfiguration.PROP_IGNORE_USER_CONFIGURATION))) - return; - Location configArea = equinoxLocations.getConfigurationLocation(); - if (configArea == null) - return; - - URL location = null; - try { - location = new URL(configArea.getURL().toExternalForm() + CONFIG_FILE); - } catch (MalformedURLException e) { - // its ok. This should never happen - } - equinoxConfig.mergeConfiguration(loadProperties(location, equinoxConfig)); - } - - private static Properties loadProperties(URL location, EquinoxConfiguration equinoxConfig) { - Properties result = new Properties(); - if (location == null) - return result; - try { - InputStream in = location.openStream(); - try { - result.load(in); - } finally { - in.close(); - } - } catch (IOException e) { - // its ok if there is no file. We'll just use the defaults for everything - // TODO but it might be nice to log something with gentle wording (i.e., it is not an error) - } - return substituteVars(result, equinoxConfig); - } - - private static Properties substituteVars(Properties result, EquinoxConfiguration equinoxConfig) { - if (result == null) { - //nothing todo. - return null; - } - for (Enumeration eKeys = result.keys(); eKeys.hasMoreElements();) { - Object key = eKeys.nextElement(); - if (key instanceof String) { - String value = result.getProperty((String) key); - if (value != null) - result.put(key, equinoxConfig.substituteVars(value, true)); - } - } - return result; - } - public Storage getStorage() { return storage; } @@ -166,7 +108,7 @@ public class EquinoxContainer implements ThreadFactory, Runnable { } public EquinoxLocations getLocations() { - return equinoxLocations; + return equinoxConfig.getEquinoxLocations(); } public EquinoxLogServices getLogServices() { diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/location/BasicLocation.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/location/BasicLocation.java old mode 100644 new mode 100755 index b0969bc5b..d8519ac87 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/location/BasicLocation.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/location/BasicLocation.java @@ -13,8 +13,9 @@ package org.eclipse.osgi.internal.location; import java.io.File; import java.io.IOException; import java.net.URL; +import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.osgi.framework.log.FrameworkLogEntry; -import org.eclipse.osgi.internal.framework.EquinoxConfiguration; +import org.eclipse.osgi.internal.framework.EquinoxConfiguration.ConfigValues; import org.eclipse.osgi.internal.framework.EquinoxContainer; import org.eclipse.osgi.internal.log.EquinoxLogServices; import org.eclipse.osgi.internal.messages.Msg; @@ -31,8 +32,9 @@ public class BasicLocation implements Location { final private URL defaultValue; final private String property; final private String dataAreaPrefix; - final private EquinoxConfiguration environmentInfo; - final private boolean debug; + final private ConfigValues configValues; + final private AtomicBoolean debug; + final private EquinoxContainer container; private URL location = null; private Location parent; @@ -41,7 +43,7 @@ public class BasicLocation implements Location { private File lockFile; private Locker locker; - public BasicLocation(String property, URL defaultValue, boolean isReadOnly, String dataAreaPrefix, EquinoxConfiguration environmentInfo) { + public BasicLocation(String property, URL defaultValue, boolean isReadOnly, String dataAreaPrefix, ConfigValues configValues, EquinoxContainer container, AtomicBoolean debug) { this.property = property; this.defaultValue = defaultValue; this.isReadOnly = isReadOnly; @@ -52,8 +54,9 @@ public class BasicLocation implements Location { tempDataAreaPrefix += '/'; } this.dataAreaPrefix = tempDataAreaPrefix; - this.environmentInfo = environmentInfo; - this.debug = environmentInfo.getDebug().DEBUG_LOCATION; + this.configValues = configValues; + this.container = container; + this.debug = debug; } public boolean allowsDefault() { @@ -70,8 +73,8 @@ public class BasicLocation implements Location { public synchronized URL getURL() { if (location == null && defaultValue != null) { - if (debug) { - EquinoxLogServices logServices = environmentInfo.getHookRegistry().getContainer().getLogServices(); + if (debug.get()) { + EquinoxLogServices logServices = container.getLogServices(); // Note that logServices can be null if we are very early in the startup. if (logServices != null) { logServices.log(EquinoxContainer.NAME, FrameworkLogEntry.INFO, "Called Location.getURL() when it has not been set for: \"" + property + "\"", new RuntimeException("Call stack for Location.getURL()")); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ @@ -135,7 +138,7 @@ public class BasicLocation implements Location { lockFile = file; location = value; if (property != null) - environmentInfo.setConfiguration(property, location.toExternalForm()); + configValues.setConfiguration(property, location.toExternalForm()); return lock; } @@ -205,8 +208,8 @@ public class BasicLocation implements Location { private void setLocker(File lock) { if (locker != null) return; - String lockMode = environmentInfo.getConfiguration(LocationHelper.PROP_OSGI_LOCKING, LocationHelper.LOCKING_NIO); - locker = LocationHelper.createLocker(lock, lockMode, debug); + String lockMode = configValues.getConfiguration(LocationHelper.PROP_OSGI_LOCKING, LocationHelper.LOCKING_NIO); + locker = LocationHelper.createLocker(lock, lockMode, debug.get()); } public synchronized void release() { @@ -215,7 +218,7 @@ public class BasicLocation implements Location { } public Location createLocation(Location parentLocation, URL defaultLocation, boolean readonly) { - BasicLocation result = new BasicLocation(null, defaultLocation, readonly, dataAreaPrefix, environmentInfo); + BasicLocation result = new BasicLocation(null, defaultLocation, readonly, dataAreaPrefix, configValues, container, debug); result.setParent(parentLocation); return result; } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/location/EquinoxLocations.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/location/EquinoxLocations.java old mode 100644 new mode 100755 index a39cc26d9..e5cf6db99 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/location/EquinoxLocations.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/location/EquinoxLocations.java @@ -15,7 +15,10 @@ import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.util.Properties; +import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.osgi.internal.framework.EquinoxConfiguration; +import org.eclipse.osgi.internal.framework.EquinoxConfiguration.ConfigValues; +import org.eclipse.osgi.internal.framework.EquinoxContainer; import org.eclipse.osgi.service.datalocation.Location; import org.eclipse.osgi.storage.StorageUtil; import org.osgi.framework.Constants; @@ -56,7 +59,9 @@ public class EquinoxLocations { private static final String INSTANCE_DATA_AREA_PREFIX = ".metadata/.plugins/"; //$NON-NLS-1$ - private final EquinoxConfiguration equinoxConfig; + private final ConfigValues equinoxConfig; + private final EquinoxContainer container; + private final AtomicBoolean debugLocations; private final Location installLocation; private final Location configurationLocation; @@ -64,8 +69,10 @@ public class EquinoxLocations { private final Location instanceLocation; private final Location eclipseHomeLocation; - public EquinoxLocations(EquinoxConfiguration equinoxConfig) { + public EquinoxLocations(ConfigValues equinoxConfig, EquinoxContainer container, AtomicBoolean debugLocations) { this.equinoxConfig = equinoxConfig; + this.container = container; + this.debugLocations = debugLocations; // Initializes the Location objects for the LocationManager. // set the osgi storage area if it exists @@ -102,7 +109,7 @@ public class EquinoxLocations { // cascaded. URL parentLocation = computeSharedConfigurationLocation(); if (parentLocation != null && !parentLocation.equals(configurationLocation.getURL())) { - Location parent = new BasicLocation(null, parentLocation, true, null, equinoxConfig); + Location parent = new BasicLocation(null, parentLocation, true, null, equinoxConfig, container, debugLocations); ((BasicLocation) configurationLocation).setParent(parent); } @@ -142,7 +149,7 @@ public class EquinoxLocations { } } - private static String getEclipseHomeLocation(String launcher, EquinoxConfiguration equinoxConfig) { + private static String getEclipseHomeLocation(String launcher, ConfigValues configValues) { if (launcher == null) return null; File launcherFile = new File(launcher); @@ -151,7 +158,7 @@ public class EquinoxLocations { File launcherDir = new File(launcherFile.getParent()); // check for mac os; the os check is copied from EclipseEnvironmentInfo. String macosx = org.eclipse.osgi.service.environment.Constants.OS_MACOSX; - if (macosx.equals(equinoxConfig.getOS())) + if (macosx.equals(configValues.getConfiguration(EquinoxConfiguration.PROP_OSGI_OS))) launcherDir = getMacOSEclipseHomeLocation(launcherDir); return (launcherDir.exists() && launcherDir.isDirectory()) ? launcherDir.getAbsolutePath() : null; } @@ -171,12 +178,12 @@ public class EquinoxLocations { // if the instance location is not set, predict where the workspace will be and // put the instance area inside the workspace meta area. if (location == null) - return new BasicLocation(property, defaultLocation, userReadOnlySetting != null || !computeReadOnly ? readOnly : !canWrite(defaultLocation), dataAreaPrefix, equinoxConfig); + return new BasicLocation(property, defaultLocation, userReadOnlySetting != null || !computeReadOnly ? readOnly : !canWrite(defaultLocation), dataAreaPrefix, equinoxConfig, container, debugLocations); String trimmedLocation = location.trim(); if (trimmedLocation.equalsIgnoreCase(NONE)) return null; if (trimmedLocation.equalsIgnoreCase(NO_DEFAULT)) - return new BasicLocation(property, null, readOnly, dataAreaPrefix, equinoxConfig); + return new BasicLocation(property, null, readOnly, dataAreaPrefix, equinoxConfig, container, debugLocations); if (trimmedLocation.startsWith(USER_HOME)) { String base = substituteVar(location, USER_HOME, PROP_USER_HOME); location = new File(base, userDefaultAppendage).getAbsolutePath(); @@ -193,7 +200,7 @@ public class EquinoxLocations { URL url = buildURL(location, true); BasicLocation result = null; if (url != null) { - result = new BasicLocation(property, null, userReadOnlySetting != null || !computeReadOnly ? readOnly : !canWrite(url), dataAreaPrefix, equinoxConfig); + result = new BasicLocation(property, null, userReadOnlySetting != null || !computeReadOnly ? readOnly : !canWrite(url), dataAreaPrefix, equinoxConfig, container, debugLocations); result.setURL(url, false); } return result; diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogServices.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogServices.java index 02afb004c..6fe4862a2 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogServices.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogServices.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2014 IBM Corporation and others. + * Copyright (c) 2006, 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -36,7 +36,8 @@ public class EquinoxLogServices { private final EquinoxLogWriter perfWriter; private final FrameworkLog rootFrameworkLog; - public EquinoxLogServices(EquinoxConfiguration environmentInfo, Location configuration) { + public EquinoxLogServices(EquinoxConfiguration environmentInfo) { + Location configuration = environmentInfo.getEquinoxLocations().getConfigurationLocation(); String logFilePath = environmentInfo.getConfiguration(EclipseStarter.PROP_LOGFILE); if (logFilePath == null) { logFilePath = Long.toString(System.currentTimeMillis()) + EquinoxLogServices.LOG_EXT; -- cgit v1.2.3