blob: 48e5e5d3da4766b3f9e05502ad3dc08798890f8c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2017 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Ericsson AB (Pascal Rapicault) - Bug 397216 -[Shared] Better shared
* configuration change discovery
*******************************************************************************/
package org.eclipse.equinox.internal.frameworkadmin.equinox;
import java.io.*;
import java.net.*;
import java.util.*;
import org.eclipse.core.runtime.URIUtil;
import org.eclipse.equinox.frameworkadmin.BundleInfo;
import org.eclipse.equinox.internal.frameworkadmin.equinox.utils.FileUtils;
import org.eclipse.equinox.internal.frameworkadmin.utils.Utils;
import org.eclipse.equinox.internal.provisional.frameworkadmin.*;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.service.log.LogService;
public class EquinoxFwConfigFileParser {
private static final Set<String> KNOWN_PROPERTIES = new HashSet<>(Arrays.asList(new String[] {EquinoxConstants.PROP_BUNDLES, EquinoxConstants.PROP_FW_EXTENSIONS, EquinoxConstants.PROP_INITIAL_STARTLEVEL, EquinoxConstants.PROP_BUNDLES_STARTLEVEL}));
private static final String CONFIG_DIR = "@config.dir/"; //$NON-NLS-1$
private static final String KEY_ECLIPSE_PROV_DATA_AREA = "eclipse.p2.data.area"; //$NON-NLS-1$
private static final String KEY_ORG_ECLIPSE_EQUINOX_SIMPLECONFIGURATOR_CONFIGURL = "org.eclipse.equinox.simpleconfigurator.configUrl"; //$NON-NLS-1$
private static final String REFERENCE_SCHEME = "reference:"; //$NON-NLS-1$
private static final String FILE_PROTOCOL = "file:"; //$NON-NLS-1$
private static final String BASE_TIMESTAMP_FILE_CONFIGINI = ".baseConfigIniTimestamp"; //$NON-NLS-1$
private static final String KEY_CONFIGINI_TIMESTAMP = "configIniTimestamp"; //$NON-NLS-1$
private static boolean DEBUG = false;
public EquinoxFwConfigFileParser(BundleContext context) {
//Empty
}
private static StringBuffer toOSGiBundleListForm(BundleInfo bundleInfo, URI location) {
StringBuffer locationString = new StringBuffer(REFERENCE_SCHEME);
if (URIUtil.isFileURI(location))
locationString.append(URIUtil.toUnencodedString(location));
else if (location.getScheme() == null)
locationString.append(FILE_PROTOCOL).append(URIUtil.toUnencodedString(location));
else
locationString = new StringBuffer(URIUtil.toUnencodedString(location));
int startLevel = bundleInfo.getStartLevel();
boolean toBeStarted = bundleInfo.isMarkedAsStarted();
StringBuffer sb = new StringBuffer();
sb.append(locationString);
if (startLevel == BundleInfo.NO_LEVEL && !toBeStarted)
return sb;
sb.append('@');
if (startLevel != BundleInfo.NO_LEVEL)
sb.append(startLevel);
if (toBeStarted)
sb.append(":start"); //$NON-NLS-1$
return sb;
}
private static boolean getMarkedAsStartedFormat(String startInfo) {
if (startInfo == null)
return false;
startInfo = startInfo.trim();
int colon = startInfo.indexOf(':');
if (colon > -1) {
return startInfo.substring(colon + 1).equals("start"); //$NON-NLS-1$
}
return startInfo.equals("start"); //$NON-NLS-1$
}
private static int getStartLevel(String startInfo) {
if (startInfo == null)
return BundleInfo.NO_LEVEL;
startInfo = startInfo.trim();
int colon = startInfo.indexOf(":"); //$NON-NLS-1$
if (colon > 0) {
try {
return Integer.parseInt(startInfo.substring(0, colon));
} catch (NumberFormatException e) {
return BundleInfo.NO_LEVEL;
}
}
return BundleInfo.NO_LEVEL;
}
private void readBundlesList(Manipulator manipulator, URI osgiInstallArea, Properties props) throws NumberFormatException {
ConfigData configData = manipulator.getConfigData();
BundleInfo[] fwExtensions = parseBundleList(manipulator, props.getProperty(EquinoxConstants.PROP_FW_EXTENSIONS));
if (fwExtensions != null) {
for (BundleInfo fwExtension : fwExtensions) {
fwExtension.setFragmentHost(Constants.SYSTEM_BUNDLE_SYMBOLICNAME);
configData.addBundle(fwExtension);
}
}
BundleInfo[] bundles = parseBundleList(manipulator, props.getProperty(EquinoxConstants.PROP_BUNDLES));
if (bundles != null) {
for (BundleInfo bundle : bundles) {
configData.addBundle(bundle);
}
}
}
private BundleInfo[] parseBundleList(Manipulator manipulator, String value) {
if (value == null || value.length() == 0)
return null;
List<BundleInfo> bundles = new ArrayList<>();
String[] bInfoStrings = Utils.getTokens(value, ","); //$NON-NLS-1$
for (String bInfoString : bInfoStrings) {
String entry = bInfoString.trim();
entry = FileUtils.removeEquinoxSpecificProtocols(entry);
int indexStartInfo = entry.indexOf('@');
String location = (indexStartInfo == -1) ? entry : entry.substring(0, indexStartInfo);
URI realLocation = null;
if (manipulator.getLauncherData().getFwJar() != null) {
File parentFile = manipulator.getLauncherData().getFwJar().getParentFile();
try {
realLocation = URIUtil.makeAbsolute(FileUtils.fromFileURL(location), parentFile.toURI());
} catch (URISyntaxException e) {
// try searching as a simple location
realLocation = FileUtils.getEclipsePluginFullLocation(location, parentFile);
}
}
String slAndFlag = (indexStartInfo > -1) ? entry.substring(indexStartInfo + 1) : null;
boolean markedAsStarted = getMarkedAsStartedFormat(slAndFlag);
int startLevel = getStartLevel(slAndFlag);
if (realLocation != null) {
bundles.add(new BundleInfo(realLocation, startLevel, markedAsStarted));
continue;
}
if (location != null && location.startsWith(FILE_PROTOCOL))
try {
bundles.add(new BundleInfo(FileUtils.fromFileURL(location), startLevel, markedAsStarted));
continue;
} catch (URISyntaxException e) {
//Ignore
}
//Fallback case, we use the location as a string
bundles.add(new BundleInfo(location, null, null, startLevel, markedAsStarted));
}
return bundles.toArray(new BundleInfo[bundles.size()]);
}
private void writeBundlesList(File fwJar, Properties props, BundleInfo[] bundles) {
StringBuilder osgiBundlesList = new StringBuilder();
StringBuilder osgiFrameworkExtensionsList = new StringBuilder();
for (BundleInfo bundle : bundles) {
//framework jar does not get stored on the bundle list, figure out who that is.
if (fwJar != null) {
if (URIUtil.sameURI(fwJar.toURI(), bundle.getLocation()))
continue;
} else if (EquinoxConstants.FW_SYMBOLIC_NAME.equals(bundle.getSymbolicName()))
continue;
URI location = fwJar != null ? URIUtil.makeRelative(bundle.getLocation(), fwJar.getParentFile().toURI()) : bundle.getLocation();
String fragmentHost = bundle.getFragmentHost();
boolean isFrameworkExtension = fragmentHost != null && (fragmentHost.startsWith(EquinoxConstants.FW_SYMBOLIC_NAME) || fragmentHost.startsWith(Constants.SYSTEM_BUNDLE_SYMBOLICNAME));
if (isFrameworkExtension) {
bundle.setStartLevel(BundleInfo.NO_LEVEL);
bundle.setMarkedAsStarted(false);
osgiFrameworkExtensionsList.append(toOSGiBundleListForm(bundle, location));
osgiFrameworkExtensionsList.append(',');
} else {
osgiBundlesList.append(toOSGiBundleListForm(bundle, location));
osgiBundlesList.append(',');
}
}
if (osgiFrameworkExtensionsList.length() > 0)
osgiFrameworkExtensionsList.deleteCharAt(osgiFrameworkExtensionsList.length() - 1);
props.setProperty(EquinoxConstants.PROP_FW_EXTENSIONS, osgiFrameworkExtensionsList.toString());
if (osgiBundlesList.length() > 0)
osgiBundlesList.deleteCharAt(osgiBundlesList.length() - 1);
props.setProperty(EquinoxConstants.PROP_BUNDLES, osgiBundlesList.toString());
}
/**
* inputFile must be not a directory but a file.
*
* @param manipulator
* @param inputFile
* @throws IOException
*/
public void readFwConfig(Manipulator manipulator, File inputFile) throws IOException, URISyntaxException {
if (inputFile.isDirectory())
throw new IllegalArgumentException(NLS.bind(Messages.exception_inputFileIsDirectory, inputFile));
boolean baseHasChanged = false;
//Initialize data structures
ConfigData configData = manipulator.getConfigData();
LauncherData launcherData = manipulator.getLauncherData();
configData.initialize();
configData.setBundles(null);
// load configuration properties
Properties props = loadProperties(inputFile);
// load shared configuration properties
Properties sharedConfigProperties = getSharedConfiguration(ParserUtils.getOSGiInstallArea(Arrays.asList(manipulator.getLauncherData().getProgramArgs()), props, manipulator.getLauncherData()), props.getProperty(EquinoxConstants.PROP_SHARED_CONFIGURATION_AREA));
if (sharedConfigProperties != null) {
baseHasChanged = hasBaseChanged(inputFile, manipulator, props);
if (!baseHasChanged)
sharedConfigProperties.putAll(props);
else {
sharedConfigProperties.put(EquinoxConstants.PROP_SHARED_CONFIGURATION_AREA, props.get(EquinoxConstants.PROP_SHARED_CONFIGURATION_AREA));
}
props = sharedConfigProperties;
}
//Start figuring out stuffs
//URI rootURI = launcherData.getLauncher() != null ? launcherData.getLauncher().getParentFile().toURI() : null;
readFwJarLocation(configData, launcherData, props);
URI configArea = inputFile.getParentFile().toURI();
//readLauncherPath(props, rootURI);
readp2DataArea(props, configArea);
readSimpleConfiguratorURL(props, configArea);
if (!baseHasChanged)
readBundlesList(manipulator, ParserUtils.getOSGiInstallArea(Arrays.asList(launcherData.getProgramArgs()), props, launcherData).toURI(), props);
readInitialStartLeve(configData, props);
readDefaultStartLevel(configData, props);
for (Enumeration<Object> enumeration = props.keys(); enumeration.hasMoreElements();) {
String key = (String) enumeration.nextElement();
if (KNOWN_PROPERTIES.contains(key))
continue;
String value = props.getProperty(key);
configData.setProperty(key, value);
}
Log.log(LogService.LOG_INFO, NLS.bind(Messages.log_configFile, inputFile.getAbsolutePath()));
}
private boolean hasBaseChanged(File configIni, Manipulator manipulator, Properties configProps) {
LauncherData launcherData = manipulator.getLauncherData();
File sharedConfigIni = findSharedConfigIniFile(ParserUtils.getOSGiInstallArea(Arrays.asList(launcherData.getProgramArgs()), configProps, launcherData), configProps.getProperty(EquinoxConstants.PROP_SHARED_CONFIGURATION_AREA));
File timestampFile = new File(configIni.getParentFile(), BASE_TIMESTAMP_FILE_CONFIGINI);
Properties timestamps;
try {
timestamps = loadProperties(timestampFile);
} catch (FileNotFoundException e) {
return false;
} catch (IOException e) {
return false;
}
return !String.valueOf(sharedConfigIni.lastModified()).equals(timestamps.getProperty(KEY_CONFIGINI_TIMESTAMP));
}
private void readDefaultStartLevel(ConfigData configData, Properties props) {
if (props.getProperty(EquinoxConstants.PROP_BUNDLES_STARTLEVEL) != null)
configData.setInitialBundleStartLevel(Integer.parseInt(props.getProperty(EquinoxConstants.PROP_BUNDLES_STARTLEVEL)));
}
private void writeDefaultStartLevel(ConfigData configData, Properties props) {
if (configData.getInitialBundleStartLevel() != BundleInfo.NO_LEVEL)
props.setProperty(EquinoxConstants.PROP_BUNDLES_STARTLEVEL, Integer.toString(configData.getInitialBundleStartLevel()));
}
private void readInitialStartLeve(ConfigData configData, Properties props) {
if (props.getProperty(EquinoxConstants.PROP_INITIAL_STARTLEVEL) != null)
configData.setBeginningFwStartLevel(Integer.parseInt(props.getProperty(EquinoxConstants.PROP_INITIAL_STARTLEVEL)));
}
private void writeInitialStartLevel(ConfigData configData, Properties props) {
if (configData.getBeginingFwStartLevel() != BundleInfo.NO_LEVEL)
props.setProperty(EquinoxConstants.PROP_INITIAL_STARTLEVEL, Integer.toString(configData.getBeginingFwStartLevel()));
}
private File readFwJarLocation(ConfigData configData, LauncherData launcherData, Properties props) throws URISyntaxException {
File fwJar = null;
if (props.getProperty(EquinoxConstants.PROP_OSGI_FW) != null) {
URI absoluteFwJar = null;
absoluteFwJar = URIUtil.makeAbsolute(FileUtils.fromFileURL(props.getProperty(EquinoxConstants.PROP_OSGI_FW)), ParserUtils.getOSGiInstallArea(Arrays.asList(launcherData.getProgramArgs()), props, launcherData).toURI());
props.setProperty(EquinoxConstants.PROP_OSGI_FW, absoluteFwJar.toString());
String fwJarString = props.getProperty(EquinoxConstants.PROP_OSGI_FW);
if (fwJarString != null) {
fwJar = URIUtil.toFile(absoluteFwJar);
if (fwJar == null)
throw new IllegalStateException(Messages.exception_noFrameworkLocation);
//Here we overwrite the value read from eclipse.ini, because the value of osgi.framework always takes precedence.
launcherData.setFwJar(fwJar);
} else {
throw new IllegalStateException(Messages.exception_noFrameworkLocation);
}
}
if (launcherData.getFwJar() != null)
configData.addBundle(new BundleInfo(launcherData.getFwJar().toURI()));
return launcherData.getFwJar();
}
private void writeFwJarLocation(ConfigData configData, LauncherData launcherData, Properties props) {
if (launcherData.getFwJar() == null)
return;
props.setProperty(EquinoxConstants.PROP_OSGI_FW, FileUtils.toFileURL(URIUtil.makeRelative(launcherData.getFwJar().toURI(), ParserUtils.getOSGiInstallArea(Arrays.asList(launcherData.getProgramArgs()), configData.getProperties(), launcherData).toURI())));
}
private static Properties loadProperties(File inputFile) throws FileNotFoundException, IOException {
Properties props = new Properties();
InputStream is = null;
try {
is = new FileInputStream(inputFile);
props.load(is);
} finally {
try {
if (is != null)
is.close();
} catch (IOException e) {
Log.log(LogService.LOG_WARNING, NLS.bind(Messages.log_failed_reading_properties, inputFile));
}
is = null;
}
return props;
}
private File findSharedConfigIniFile(File base, String sharedConfigurationArea) {
if (base == null)
return null;
URL rootURL;
try {
rootURL = base.toURL();
} catch (MalformedURLException e1) {
return null;
}
if (rootURL == null)
return null;
URL sharedConfigurationURL = null;
try {
sharedConfigurationURL = new URL(sharedConfigurationArea);
} catch (MalformedURLException e) {
// unexpected since this was written by the framework
Log.log(LogService.LOG_WARNING, NLS.bind(Messages.log_shared_config_url, sharedConfigurationArea));
return null;
}
// check for a relative URL
if (!sharedConfigurationURL.getPath().startsWith("/")) { //$NON-NLS-1$
if (!rootURL.getProtocol().equals(sharedConfigurationURL.getProtocol())) {
Log.log(LogService.LOG_WARNING, NLS.bind(Messages.log_shared_config_relative_url, rootURL.toExternalForm(), sharedConfigurationArea));
return null;
}
try {
sharedConfigurationURL = new URL(rootURL, sharedConfigurationArea);
} catch (MalformedURLException e) {
// unexpected since this was written by the framework
Log.log(LogService.LOG_WARNING, NLS.bind(Messages.log_shared_config_relative_url, rootURL.toExternalForm(), sharedConfigurationArea));
return null;
}
}
File sharedConfigurationFolder = EquinoxManipulatorImpl.toFile(sharedConfigurationURL);
if (!sharedConfigurationFolder.isDirectory()) {
Log.log(LogService.LOG_WARNING, NLS.bind(Messages.log_shared_config_file_missing, sharedConfigurationFolder));
return null;
}
File sharedConfigIni = new File(sharedConfigurationFolder, EquinoxConstants.CONFIG_INI);
if (!sharedConfigIni.exists()) {
Log.log(LogService.LOG_WARNING, NLS.bind(Messages.log_shared_config_file_missing, sharedConfigIni));
return null;
}
return sharedConfigIni;
}
private void readp2DataArea(Properties props, URI configArea) throws URISyntaxException {
if (props.getProperty(KEY_ECLIPSE_PROV_DATA_AREA) != null) {
String url = props.getProperty(KEY_ECLIPSE_PROV_DATA_AREA);
if (url != null) {
if (url.startsWith(CONFIG_DIR))
url = "file:" + url.substring(CONFIG_DIR.length()); //$NON-NLS-1$
props.setProperty(KEY_ECLIPSE_PROV_DATA_AREA, URIUtil.makeAbsolute(FileUtils.fromFileURL(url), configArea).toString());
}
}
}
private void writep2DataArea(ConfigData configData, Properties props, URI configArea) throws URISyntaxException {
String dataArea = getFwProperty(configData, KEY_ECLIPSE_PROV_DATA_AREA);
if (dataArea != null) {
if (dataArea.startsWith(CONFIG_DIR)) {
props.setProperty(KEY_ECLIPSE_PROV_DATA_AREA, dataArea);
return;
}
URI dataAreaURI = new URI(dataArea);
URI relative = URIUtil.makeRelative(dataAreaURI, configArea);
if (dataAreaURI.equals(relative)) {
props.setProperty(KEY_ECLIPSE_PROV_DATA_AREA, FileUtils.toFileURL(dataAreaURI));
return;
}
String result = URIUtil.toUnencodedString(relative);
//We only relativize up to the level where the p2 and config folder are siblings (e.g. foo/p2 and foo/config)
if (result.startsWith("../..")) //$NON-NLS-1$
result = dataArea;
else if (!result.equals(dataArea)) {
props.setProperty(KEY_ECLIPSE_PROV_DATA_AREA, CONFIG_DIR + result);
return;
}
props.setProperty(KEY_ECLIPSE_PROV_DATA_AREA, FileUtils.toFileURL(new URI(result)));
}
}
private void readSimpleConfiguratorURL(Properties props, URI configArea) throws URISyntaxException {
if (props.getProperty(KEY_ORG_ECLIPSE_EQUINOX_SIMPLECONFIGURATOR_CONFIGURL) != null)
props.setProperty(KEY_ORG_ECLIPSE_EQUINOX_SIMPLECONFIGURATOR_CONFIGURL, URIUtil.makeAbsolute(FileUtils.fromFileURL(props.getProperty(KEY_ORG_ECLIPSE_EQUINOX_SIMPLECONFIGURATOR_CONFIGURL)), configArea).toString());
}
private void writeSimpleConfiguratorURL(ConfigData configData, Properties props, URI configArea) throws URISyntaxException {
//FIXME How would someone set such a value.....
String value = getFwProperty(configData, KEY_ORG_ECLIPSE_EQUINOX_SIMPLECONFIGURATOR_CONFIGURL);
if (value != null)
props.setProperty(KEY_ORG_ECLIPSE_EQUINOX_SIMPLECONFIGURATOR_CONFIGURL, FileUtils.toFileURL(URIUtil.makeRelative(URIUtil.fromString(value), configArea)));
}
private String getFwProperty(ConfigData data, String key) {
return data.getProperty(key);
}
public void saveFwConfig(BundleInfo[] bInfos, Manipulator manipulator, boolean backup, boolean relative) throws IOException {//{
ConfigData configData = manipulator.getConfigData();
LauncherData launcherData = manipulator.getLauncherData();
//Get the OSGi jar from the bundle.info
File fwJar = EquinoxBundlesState.getSystemBundleFromBundleInfos(configData);
launcherData.setFwJar(fwJar);
File outputFile = launcherData.getFwConfigLocation();
if (outputFile.exists()) {
if (outputFile.isFile()) {
if (!outputFile.getName().equals(EquinoxConstants.CONFIG_INI))
throw new IllegalStateException(NLS.bind(Messages.exception_fwConfigLocationName, outputFile.getAbsolutePath(), EquinoxConstants.CONFIG_INI));
} else { // Directory
outputFile = new File(outputFile, EquinoxConstants.CONFIG_INI);
}
} else {
if (!outputFile.getName().equals(EquinoxConstants.CONFIG_INI)) {
if (!outputFile.mkdir())
throw new IOException(NLS.bind(Messages.exception_failedToCreateDir, outputFile));
outputFile = new File(outputFile, EquinoxConstants.CONFIG_INI);
}
}
Properties configProps = new Properties();
//URI rootURI = launcherData.getLauncher() != null ? launcherData.getLauncher().getParentFile().toURI() : null;
writeFwJarLocation(configData, launcherData, configProps);
try {
//writeLauncherPath(configData, configProps, rootURI);
URI configArea = manipulator.getLauncherData().getFwConfigLocation().toURI();
writep2DataArea(configData, configProps, configArea);
writeSimpleConfiguratorURL(configData, configProps, configArea);
writeBundlesList(launcherData.getFwJar(), configProps, bInfos);
writeInitialStartLevel(configData, configProps);
writeDefaultStartLevel(configData, configProps);
} catch (URISyntaxException e) {
throw new FrameworkAdminRuntimeException(e, Messages.exception_errorSavingConfigIni);
}
Properties original = configData.getProperties();
original.putAll(configProps);
configProps = original;
//Deal with the fw jar and ensure it is not set.
//TODO This can't be done before because of the previous calls to appendProperties
if (configProps == null || configProps.size() == 0) {
Log.log(LogService.LOG_WARNING, this, "saveFwConfig() ", Messages.log_configProps); //$NON-NLS-1$
return;
}
if (!Utils.createParentDir(outputFile)) {
throw new IllegalStateException(NLS.bind(Messages.exception_failedToCreateDir, outputFile.getParent()));
}
if (DEBUG)
Utils.printoutProperties(System.out, "configProps", configProps); //$NON-NLS-1$
if (backup)
if (outputFile.exists()) {
File dest = Utils.getSimpleDataFormattedFile(outputFile);
if (!outputFile.renameTo(dest))
throw new IOException(NLS.bind(Messages.exception_failedToRename, outputFile, dest));
Log.log(LogService.LOG_INFO, this, "saveFwConfig()", NLS.bind(Messages.log_renameSuccessful, outputFile, dest)); //$NON-NLS-1$
}
filterPropertiesFromSharedArea(configProps, manipulator);
saveProperties(outputFile, configProps);
rememberSharedConfigurationTimestamp(configProps, manipulator, outputFile.getParentFile());
}
private void saveProperties(File outputFile, Properties configProps) throws IOException {
String header = "This configuration file was written by: " + this.getClass().getName(); //$NON-NLS-1$
FileOutputStream out = null;
try {
out = new FileOutputStream(outputFile);
configProps.store(out, header);
Log.log(LogService.LOG_INFO, NLS.bind(Messages.log_propertiesSaved, outputFile));
} finally {
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void filterPropertiesFromSharedArea(Properties configProps, Manipulator manipulator) {
LauncherData launcherData = manipulator.getLauncherData();
//Remove from the config file that we are about to write the properties that are unchanged compared to what is in the base
Properties sharedConfigProperties = getSharedConfiguration(ParserUtils.getOSGiInstallArea(Arrays.asList(launcherData.getProgramArgs()), configProps, launcherData), configProps.getProperty(EquinoxConstants.PROP_SHARED_CONFIGURATION_AREA));
if (sharedConfigProperties == null)
return;
Enumeration<?> keys = configProps.propertyNames();
while (keys.hasMoreElements()) {
String key = (String) keys.nextElement();
String sharedValue = sharedConfigProperties.getProperty(key);
if (sharedValue == null)
continue;
String value = configProps.getProperty(key);
if (equalsIgnoringSeparators(sharedValue, value)) {
configProps.remove(key);
continue;
}
// never write out the osgi.framework property in the user's local config.ini
// See https://bugs.eclipse.org/329583
if (key.equals(EquinoxConstants.PROP_OSGI_FW)) {
configProps.remove(key);
continue;
}
if (key.equals(EquinoxConstants.PROP_BUNDLES) && equalBundleLists(manipulator, value, sharedValue)) {
configProps.remove(key);
continue;
}
if (key.equals(EquinoxConstants.PROP_FW_EXTENSIONS) && equalBundleLists(manipulator, value, sharedValue)) {
configProps.remove(key);
continue;
}
}
}
private boolean equalBundleLists(Manipulator manipulator, String value, String sharedValue) {
BundleInfo[] bundles = parseBundleList(manipulator, value);
BundleInfo[] sharedBundles = parseBundleList(manipulator, sharedValue);
if (bundles == null || sharedBundles == null || bundles.length != sharedBundles.length)
return false;
List<BundleInfo> compareList = new ArrayList<>(Arrays.asList(bundles));
compareList.removeAll(Arrays.asList(sharedBundles));
return compareList.isEmpty();
}
private boolean equalsIgnoringSeparators(String s1, String s2) {
if (s1 == null && s2 == null)
return true;
if (s1 == null || s2 == null)
return false;
StringBuffer sb1 = new StringBuffer(s1);
StringBuffer sb2 = new StringBuffer(s2);
canonicalizePathsForComparison(sb1);
canonicalizePathsForComparison(sb2);
return sb1.toString().equals(sb2.toString());
}
private void canonicalizePathsForComparison(StringBuffer s) {
final String[] tokens = new String[] {"\\\\", "\\", "//", "/"}; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
for (String token : tokens) {
int idx = s.length();
for (int i = s.length(); i != 0 && idx != -1; i--) {
idx = s.toString().lastIndexOf(token, idx);
if (idx != -1) {
s.replace(idx, idx + token.length(), "^"); //$NON-NLS-1$
}
}
}
}
private void rememberSharedConfigurationTimestamp(Properties configProps, Manipulator manipulator, File folder) throws IOException {
LauncherData launcherData = manipulator.getLauncherData();
//Remove from the config file that we are about to write the properties that are unchanged compared to what is in the base
File sharedConfigIni = findSharedConfigIniFile(ParserUtils.getOSGiInstallArea(Arrays.asList(launcherData.getProgramArgs()), configProps, launcherData), configProps.getProperty(EquinoxConstants.PROP_SHARED_CONFIGURATION_AREA));
if (sharedConfigIni == null)
return;
File timestampFile = new File(folder, BASE_TIMESTAMP_FILE_CONFIGINI);
Properties timestamps;
try {
timestamps = loadProperties(timestampFile);
} catch (IOException e) {
timestamps = new Properties();
}
timestamps.setProperty(KEY_CONFIGINI_TIMESTAMP, String.valueOf(sharedConfigIni.lastModified()));
saveProperties(timestampFile, timestamps);
}
private Properties getSharedConfiguration(File baseFile, String sharedConfigurationArea) {
if (sharedConfigurationArea == null)
return null;
File sharedConfigIni = findSharedConfigIniFile(baseFile, sharedConfigurationArea);
if (sharedConfigIni != null && sharedConfigIni.exists()) {
try {
return loadProperties(sharedConfigIni);
} catch (FileNotFoundException e) {
return null;
} catch (IOException e) {
return null;
}
}
return null;
}
}