blob: 9ae44275f963490f914be574be6859239d23444a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2018 IBM Corporation and others. All rights reserved.
* 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
*
* Red Hat, Inc (Krzysztof Daniel) - Bug 421935: Extend simpleconfigurator to
* read .info files from many locations
*
*******************************************************************************/
package org.eclipse.equinox.internal.simpleconfigurator.manipulator;
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.ParserUtils;
import org.eclipse.equinox.internal.frameworkadmin.utils.Utils;
import org.eclipse.equinox.internal.provisional.configuratormanipulator.ConfiguratorManipulator;
import org.eclipse.equinox.internal.provisional.frameworkadmin.*;
import org.eclipse.equinox.internal.simpleconfigurator.SimpleConfiguratorImpl;
import org.eclipse.equinox.internal.simpleconfigurator.utils.EquinoxUtils;
import org.eclipse.equinox.internal.simpleconfigurator.utils.SimpleConfiguratorUtils;
import org.eclipse.equinox.simpleconfigurator.manipulator.SimpleConfiguratorManipulator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
public class SimpleConfiguratorManipulatorImpl implements SimpleConfiguratorManipulator, ConfiguratorManipulator {
class LocationInfo {
URI[] prerequisiteLocations = null;
URI systemBundleLocation = null;
URI[] systemFragmentedBundleLocations = null;
}
private final static boolean DEBUG = false;
private static final BundleInfo[] NULL_BUNDLEINFOS = new BundleInfo[0];
public static final String PROP_KEY_EXCLUSIVE_INSTALLATION = "org.eclipse.equinox.simpleconfigurator.exclusiveInstallation"; //$NON-NLS-1$
public static final String CONFIG_LIST = "bundles.info"; //$NON-NLS-1$
public static final String CONFIG_FOLDER = "configuration"; //$NON-NLS-1$
public static final String CONFIGURATOR_FOLDER = "org.eclipse.equinox.simpleconfigurator"; //$NON-NLS-1$
public static final String PROP_KEY_CONFIGURL = "org.eclipse.equinox.simpleconfigurator.configUrl"; //$NON-NLS-1$
public static final String SHARED_BUNDLES_INFO = CONFIG_FOLDER + File.separatorChar + CONFIGURATOR_FOLDER
+ File.separatorChar + CONFIG_LIST;
private Set<Manipulator> manipulators = new HashSet<>();
/**
* Return the ConfiguratorConfigFile which is determined by the parameters set
* in Manipulator.
*
* @param manipulator
* @return File
*/
private static File getConfigFile(Manipulator manipulator) throws IllegalStateException {
File fwConfigLoc = manipulator.getLauncherData().getFwConfigLocation();
File baseDir = null;
if (fwConfigLoc == null) {
baseDir = manipulator.getLauncherData().getHome();
if (baseDir == null) {
if (manipulator.getLauncherData().getLauncher() != null) {
baseDir = manipulator.getLauncherData().getLauncher().getParentFile();
} else {
throw new IllegalStateException("All of fwConfigFile, home, launcher are not set."); //$NON-NLS-1$
}
}
} else {
if (fwConfigLoc.exists())
if (fwConfigLoc.isDirectory())
baseDir = fwConfigLoc;
else
baseDir = fwConfigLoc.getParentFile();
else {
// TODO We need to decide whether launcher data configLocation is the location
// of a file or a directory
if (fwConfigLoc.getName().endsWith(".ini")) //$NON-NLS-1$
baseDir = fwConfigLoc.getParentFile();
else
baseDir = fwConfigLoc;
}
}
File configuratorFolder = new File(baseDir, SimpleConfiguratorManipulatorImpl.CONFIGURATOR_FOLDER);
File targetFile = new File(configuratorFolder, SimpleConfiguratorManipulatorImpl.CONFIG_LIST);
if (!Utils.createParentDir(targetFile))
return null;
return targetFile;
}
static boolean isPrerequisiteBundles(URI location, LocationInfo info) {
boolean ret = false;
if (info.prerequisiteLocations == null)
return false;
for (URI prerequisiteLocation : info.prerequisiteLocations) {
if (location.equals(prerequisiteLocation)) {
ret = true;
break;
}
}
return ret;
}
static boolean isSystemBundle(URI location, LocationInfo info) {
if (info.systemBundleLocation == null)
return false;
if (location.equals(info.systemBundleLocation))
return true;
return false;
}
static boolean isSystemFragmentBundle(URI location, LocationInfo info) {
boolean ret = false;
if (info.systemFragmentedBundleLocations == null)
return false;
for (URI systemFragmentedBundleLocation : info.systemFragmentedBundleLocations) {
if (location.equals(systemFragmentedBundleLocation)) {
ret = true;
break;
}
}
return ret;
}
private static boolean isTargetConfiguratorBundle(BundleInfo[] bInfos) {
for (BundleInfo bInfo : bInfos) {
if (isTargetConfiguratorBundle(bInfo.getLocation())) {
return true;
// TODO confirm that startlevel of configurator bundle must be no larger than
// beginning start level of fw. However, there is no way to know the start level
// of cached ones.
}
}
return false;
}
private static boolean isTargetConfiguratorBundle(URI location) {
final String symbolic = Utils
.getPathFromClause(Utils.getManifestMainAttributes(location, Constants.BUNDLE_SYMBOLICNAME));
return (SimpleConfiguratorManipulator.SERVICE_PROP_VALUE_CONFIGURATOR_SYMBOLICNAME.equals(symbolic));
}
private void algorithm(int initialSl, SortedMap<Integer, List<BundleInfo>> bslToList, BundleInfo configuratorBInfo,
List<BundleInfo> setToInitialConfig, List<BundleInfo> setToSimpleConfig, LocationInfo info) {
int configuratorSL = configuratorBInfo.getStartLevel();
Integer sL0 = bslToList.keySet().iterator().next();// StartLevel == 0;
List<BundleInfo> list0 = bslToList.get(sL0);
if (sL0.intValue() == 0)
for (BundleInfo bInfo : list0) {
if (isSystemBundle(bInfo.getLocation(), info)) {
setToSimpleConfig.add(bInfo);
break;
}
}
for (Integer sL : bslToList.keySet()) {
List<BundleInfo> list = bslToList.get(sL);
if (sL.intValue() < configuratorSL) {
for (BundleInfo bInfo : list) {
if (!isSystemBundle(bInfo.getLocation(), info))
setToInitialConfig.add(bInfo);
}
} else if (sL.intValue() > configuratorSL) {
for (BundleInfo bInfo : list) {
if (isPrerequisiteBundles(bInfo.getLocation(), info)
|| isSystemFragmentBundle(bInfo.getLocation(), info))
if (!isSystemBundle(bInfo.getLocation(), info))
setToInitialConfig.add(bInfo);
setToSimpleConfig.add(bInfo);
}
} else {
boolean found = false;
for (BundleInfo bInfo : list) {
if (found) {
if (!isSystemBundle(bInfo.getLocation(), info))
if (isPrerequisiteBundles(bInfo.getLocation(), info)
|| isSystemFragmentBundle(bInfo.getLocation(), info))
setToInitialConfig.add(bInfo);
setToSimpleConfig.add(bInfo);
continue;
}
if (isTargetConfiguratorBundle(bInfo.getLocation()))
found = true;
else if (!isSystemBundle(bInfo.getLocation(), info))
setToInitialConfig.add(bInfo);
setToSimpleConfig.add(bInfo);
}
}
}
setToInitialConfig.add(configuratorBInfo);
}
private boolean checkResolve(BundleInfo bInfo, BundlesState state) {// throws ManipulatorException {
if (bInfo == null)
throw new IllegalArgumentException("bInfo is null."); //$NON-NLS-1$
if (!state.isResolved())
state.resolve(false);
if (!state.isResolved(bInfo)) {
printoutUnsatisfiedConstraints(bInfo, state);
return false;
}
return true;
}
private boolean divideBundleInfos(Manipulator manipulator, List<BundleInfo> setToInitialConfig,
List<BundleInfo> setToSimpleConfig, final int initialBSL) {
BundlesState state = manipulator.getBundlesState();
BundleInfo[] targetBundleInfos = null;
if (state.isFullySupported()) {
targetBundleInfos = state.getExpectedState();
} else {
targetBundleInfos = manipulator.getConfigData().getBundles();
}
BundleInfo configuratorBInfo = null;
for (BundleInfo targetBundleInfo : targetBundleInfos) {
if (isTargetConfiguratorBundle(targetBundleInfo.getLocation())) {
if (targetBundleInfo.isMarkedAsStarted()) {
configuratorBInfo = targetBundleInfo;
break;
}
}
}
if (configuratorBInfo == null && !manipulators.contains(manipulator)) {
return false;
} else if (manipulators.contains(manipulator) && targetBundleInfos.length == 0) {
// Resulting state will have no bundles - so is an uninstall, including
// uninstall of the configurator. However, we have seen this manipulator
// before with a target configurator bundle, so allow uninstall to proceed,
// but only get one chance.
manipulators.remove(manipulator);
} else if (!manipulators.contains(manipulator)) {
manipulators.add(manipulator);
}
if (state.isFullySupported()) {
state.resolve(false);
}
LocationInfo info = new LocationInfo();
setSystemBundles(state, info);
if (configuratorBInfo != null) {
setPrerequisiteBundles(configuratorBInfo, state, info);
SortedMap<Integer, List<BundleInfo>> bslToList = getSortedMap(initialBSL, targetBundleInfos);
algorithm(initialBSL, bslToList, configuratorBInfo, setToInitialConfig, setToSimpleConfig, info);
}
return true;
}
private SortedMap<Integer, List<BundleInfo>> getSortedMap(int initialSl, BundleInfo[] bInfos) {
SortedMap<Integer, List<BundleInfo>> bslToList = new TreeMap<>();
for (BundleInfo bInfo : bInfos) {
Integer sL = Integer.valueOf(bInfo.getStartLevel());
if (sL.intValue() == BundleInfo.NO_LEVEL)
sL = Integer.valueOf(initialSl);
List<BundleInfo> list = bslToList.get(sL);
if (list == null) {
list = new LinkedList<>();
bslToList.put(sL, list);
}
list.add(bInfo);
}
return bslToList;
}
private BundleInfo[] orderingInitialConfig(List<BundleInfo> setToInitialConfig) {
List<BundleInfo> notToBeStarted = new LinkedList<>();
List<BundleInfo> toBeStarted = new LinkedList<>();
for (BundleInfo bInfo : setToInitialConfig) {
if (bInfo.isMarkedAsStarted())
toBeStarted.add(bInfo);
else
notToBeStarted.add(bInfo);
}
setToInitialConfig.clear();
setToInitialConfig.addAll(notToBeStarted);
setToInitialConfig.addAll(toBeStarted);
return Utils.getBundleInfosFromList(setToInitialConfig);
}
private void printoutUnsatisfiedConstraints(BundleInfo bInfo, BundlesState state) {
if (DEBUG) {
StringBuffer sb = new StringBuffer();
sb.append("Missing constraints:\n"); //$NON-NLS-1$
String[] missings = state.getUnsatisfiedConstraints(bInfo);
for (String missing : missings) {
sb.append(" " + missing + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
}
System.out.println(sb.toString());
}
}
/**
* Like {@link SimpleConfiguratorImpl#chooseConfigurationURL(URL, URL[])} but it
* doesn't check file timestamps because if the
* {@link SimpleConfiguratorImpl#PROP_IGNORE_USER_CONFIGURATION} property is set
* then we already know that timestamps have been checked and we need to ignore
* the user config.
*/
private URL chooseConfigurationURL(String relativePath, URL[] configURL) throws MalformedURLException {
if (configURL != null) {
File userConfig = new File(configURL[0].getFile(), relativePath);
if (configURL.length == 1) {
return userConfig.exists() ? userConfig.toURI().toURL() : null;
}
File sharedConfig = new File(configURL[1].getFile(), relativePath);
if (!userConfig.exists()) {
return sharedConfig.exists() ? sharedConfig.toURI().toURL() : null;
}
if (!sharedConfig.exists()) {
return userConfig.toURI().toURL();
}
if (Boolean.getBoolean(SimpleConfiguratorImpl.PROP_IGNORE_USER_CONFIGURATION)) {
return sharedConfig.toURI().toURL();
}
return userConfig.toURI().toURL();
}
return null;
}
@Override
public BundleInfo[] loadConfiguration(BundleContext context, String infoPath) throws IOException {
URI installArea = EquinoxUtils.getInstallLocationURI(context);
URL configURL = null;
if (infoPath == null) {
SimpleConfiguratorImpl simpleImpl = new SimpleConfiguratorImpl(context, null);
configURL = simpleImpl.getConfigurationURL();
} else {
// == (not .equals) use the default source info, currently SOURCE_INFO_PATH
boolean defaultSource = (infoPath == SOURCE_INFO);
if (defaultSource)
infoPath = SOURCE_INFO_PATH;
URL[] configURLs = EquinoxUtils.getConfigAreaURL(context);
configURL = chooseConfigurationURL(infoPath, configURLs);
}
// At this point the file specified by configURL should definitely exist or be
// null
if (configURL == null) {
return NULL_BUNDLEINFOS;
}
List<BundleInfo> result = new ArrayList<>();
// Stream will be closed by loadConfiguration
result.addAll(Arrays.asList(loadConfiguration(configURL.openStream(), installArea)));
try {
List<File> infoFiles = SimpleConfiguratorUtils.getInfoFiles();
for (File infoFile : infoFiles) {
// Stream will be closed by loadConfiguration
BundleInfo[] info = loadConfiguration(infoFile.toURL().openStream(), infoFile.getParentFile().toURI());
result.addAll(Arrays.asList(info));
}
} catch (URISyntaxException e) {
// ignore the extended configurations
}
return result.toArray(new BundleInfo[result.size()]);
}
/*
* InputStream must be closed
*/
@Override
public BundleInfo[] loadConfiguration(InputStream stream, URI installArea) throws IOException {
if (stream == null)
return NULL_BUNDLEINFOS;
List<org.eclipse.equinox.internal.simpleconfigurator.utils.BundleInfo> simpleBundles = SimpleConfiguratorUtils
.readConfiguration(stream, installArea);
// convert to FrameworkAdmin BundleInfo Type
BundleInfo[] result = new BundleInfo[simpleBundles.size()];
int i = 0;
for (org.eclipse.equinox.internal.simpleconfigurator.utils.BundleInfo simpleInfo : simpleBundles) {
URI location = simpleInfo.getLocation();
if (!location.isAbsolute() && simpleInfo.getBaseLocation() != null)
location = URIUtil.makeAbsolute(location, simpleInfo.getBaseLocation());
BundleInfo bundleInfo = new BundleInfo(simpleInfo.getSymbolicName(), simpleInfo.getVersion(), location,
simpleInfo.getStartLevel(), simpleInfo.isMarkedAsStarted());
bundleInfo.setBaseLocation(simpleInfo.getBaseLocation());
result[i++] = bundleInfo;
}
return result;
}
@Override
public void saveConfiguration(BundleInfo[] configuration, OutputStream stream, URI installArea) throws IOException {
org.eclipse.equinox.internal.simpleconfigurator.utils.BundleInfo[] simpleInfos = convertBundleInfos(
configuration, installArea);
SimpleConfiguratorManipulatorUtils.writeConfiguration(simpleInfos, stream);
}
@Override
public void saveConfiguration(BundleInfo[] configuration, File outputFile, URI installArea) throws IOException {
saveConfiguration(configuration, outputFile, installArea, false);
}
private void saveConfiguration(BundleInfo[] configuration, File outputFile, URI installArea, boolean backup)
throws IOException {
if (backup && outputFile.exists()) {
File backupFile = Utils.getSimpleDataFormattedFile(outputFile);
if (!outputFile.renameTo(backupFile)) {
throw new IOException("Fail to rename from (" + outputFile + ") to (" + backupFile + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
}
org.eclipse.equinox.internal.simpleconfigurator.utils.BundleInfo[] simpleInfos = convertBundleInfos(
configuration, installArea);
// if empty remove the configuration file
if (simpleInfos == null || simpleInfos.length == 0) {
if (outputFile.exists()) {
outputFile.delete();
}
File parentDir = outputFile.getParentFile();
if (parentDir.exists()) {
parentDir.delete();
}
return;
}
SimpleConfiguratorManipulatorUtils.writeConfiguration(simpleInfos, outputFile);
if (CONFIG_LIST.equals(outputFile.getName()) && installArea != null
&& isSharedInstallSetup(URIUtil.toFile(installArea), outputFile))
rememberSharedBundlesInfoTimestamp(installArea, outputFile.getParentFile());
}
private void rememberSharedBundlesInfoTimestamp(URI installArea, File outputFolder) {
if (installArea == null)
return;
File sharedBundlesInfo = new File(URIUtil.append(installArea, SHARED_BUNDLES_INFO));
if (!sharedBundlesInfo.exists())
return;
Properties timestampToPersist = new Properties();
timestampToPersist.put(SimpleConfiguratorImpl.KEY_BUNDLESINFO_TIMESTAMP,
Long.toString(SimpleConfiguratorUtils.getFileLastModified(sharedBundlesInfo)));
timestampToPersist.put(SimpleConfiguratorImpl.KEY_EXT_TIMESTAMP,
Long.toString(SimpleConfiguratorUtils.getExtendedTimeStamp()));
OutputStream os = null;
try {
try {
File outputFile = new File(outputFolder, SimpleConfiguratorImpl.BASE_TIMESTAMP_FILE_BUNDLESINFO);
os = new BufferedOutputStream(new FileOutputStream(outputFile));
timestampToPersist.store(os, "Written by " + this.getClass()); //$NON-NLS-1$
} finally {
if (os != null)
os.close();
}
} catch (IOException e) {
return;
}
}
private org.eclipse.equinox.internal.simpleconfigurator.utils.BundleInfo[] convertBundleInfos(
BundleInfo[] configuration, URI installArea) {
// convert to SimpleConfigurator BundleInfo Type
org.eclipse.equinox.internal.simpleconfigurator.utils.BundleInfo[] simpleInfos = new org.eclipse.equinox.internal.simpleconfigurator.utils.BundleInfo[configuration.length];
for (int i = 0; i < configuration.length; i++) {
BundleInfo bundleInfo = configuration[i];
URI location = bundleInfo.getLocation();
if (bundleInfo.getSymbolicName() == null || bundleInfo.getVersion() == null || location == null)
throw new IllegalArgumentException("Cannot persist bundleinfo: " + bundleInfo.toString()); //$NON-NLS-1$
// only need to make a new BundleInfo if we are changing it.
if (installArea != null)
location = URIUtil.makeRelative(location, installArea);
simpleInfos[i] = new org.eclipse.equinox.internal.simpleconfigurator.utils.BundleInfo(
bundleInfo.getSymbolicName(), bundleInfo.getVersion(), location, bundleInfo.getStartLevel(),
bundleInfo.isMarkedAsStarted());
simpleInfos[i].setBaseLocation(bundleInfo.getBaseLocation());
}
return simpleInfos;
}
@Override
public BundleInfo[] save(Manipulator manipulator, boolean backup) throws IOException {
List<BundleInfo> setToInitialConfig = new LinkedList<>();
List<BundleInfo> setToSimpleConfig = new LinkedList<>();
ConfigData configData = manipulator.getConfigData();
if (!divideBundleInfos(manipulator, setToInitialConfig, setToSimpleConfig,
configData.getInitialBundleStartLevel()))
return configData.getBundles();
File outputFile = getConfigFile(manipulator);
URI installArea = ParserUtils.getOSGiInstallArea(Arrays.asList(manipulator.getLauncherData().getProgramArgs()),
manipulator.getConfigData().getProperties(), manipulator.getLauncherData()).toURI();
saveConfiguration(setToSimpleConfig.toArray(new BundleInfo[setToSimpleConfig.size()]), outputFile, installArea,
backup);
configData.setProperty(SimpleConfiguratorManipulatorImpl.PROP_KEY_CONFIGURL,
outputFile.toURL().toExternalForm());
return orderingInitialConfig(setToInitialConfig);
}
void setPrerequisiteBundles(BundleInfo configuratorBundleInfo, BundlesState state, LocationInfo info) {
if (state.isFullySupported())
if (!this.checkResolve(configuratorBundleInfo, state)) {
printoutUnsatisfiedConstraints(configuratorBundleInfo, state);
return;
}
BundleInfo[] prerequisites = state.getPrerequisteBundles(configuratorBundleInfo);
info.prerequisiteLocations = new URI[prerequisites.length];
for (int i = 0; i < prerequisites.length; i++)
info.prerequisiteLocations[i] = prerequisites[i].getLocation();
return;
}
void setSystemBundles(BundlesState state, LocationInfo info) {
BundleInfo systemBundleInfo = state.getSystemBundle();
if (systemBundleInfo == null) {
// TODO Log
// throw new IllegalStateException("There is no systemBundle.\n");
return;
}
if (state.isFullySupported())
if (!this.checkResolve(systemBundleInfo, state)) {
printoutUnsatisfiedConstraints(systemBundleInfo, state);
return;
}
info.systemBundleLocation = systemBundleInfo.getLocation();
BundleInfo[] fragments = state.getSystemFragmentedBundles();
info.systemFragmentedBundleLocations = new URI[fragments.length];
for (int i = 0; i < fragments.length; i++)
info.systemFragmentedBundleLocations[i] = fragments[i].getLocation();
}
@Override
public void updateBundles(Manipulator manipulator) throws IOException {
if (DEBUG)
System.out.println("SimpleConfiguratorManipulatorImpl#updateBundles()"); //$NON-NLS-1$
BundlesState bundleState = manipulator.getBundlesState();
if (bundleState == null)
return;
if (bundleState.isFullySupported())
bundleState.resolve(true);
BundleInfo[] currentBInfos = bundleState.getExpectedState();
if (!isTargetConfiguratorBundle(currentBInfos))
return;
Properties properties = new Properties();
String[] jvmArgs = manipulator.getLauncherData().getJvmArgs();
for (String jvmArg : jvmArgs) {
if (jvmArg.startsWith("-D")) {
// $NON-NLS-1$
int index = jvmArg.indexOf("="); //$NON-NLS-1$
if (index > 0 && jvmArg.length() > 2) {
String key = jvmArg.substring(2, index);
String value = jvmArg.substring(index + 1);
properties.setProperty(key, value);
}
}
}
Utils.appendProperties(properties, manipulator.getConfigData().getProperties());
boolean exclusiveInstallation = Boolean.parseBoolean(
properties.getProperty(SimpleConfiguratorManipulatorImpl.PROP_KEY_EXCLUSIVE_INSTALLATION));
File configFile = getConfigFile(manipulator);
File installArea = ParserUtils.getOSGiInstallArea(Arrays.asList(manipulator.getLauncherData().getProgramArgs()),
manipulator.getConfigData().getProperties(), manipulator.getLauncherData());
BundleInfo[] toInstall = new BundleInfo[0];
boolean isShared = isSharedInstallSetup(installArea, configFile);
if (!isShared || (isShared && !hasBaseChanged(installArea.toURI(), configFile.getParentFile()))) {
try {
// input stream will be closed for us
toInstall = loadConfiguration(new FileInputStream(configFile), installArea.toURI());
} catch (FileNotFoundException e) {
// no file, just return an empty list
toInstall = new BundleInfo[0];
}
}
List<BundleInfo> toUninstall = new LinkedList<>();
if (exclusiveInstallation)
for (BundleInfo currentBInfo : currentBInfos) {
boolean install = false;
for (BundleInfo toInstall1 : toInstall) {
if (currentBInfo.getLocation().equals(toInstall1.getLocation())) {
install = true;
break;
}
}
if (!install) {
toUninstall.add(currentBInfo);
}
}
for (BundleInfo toInstall1 : toInstall) {
try {
bundleState.installBundle(toInstall1);
} catch (RuntimeException e) {
// Ignore
}
}
if (exclusiveInstallation)
for (BundleInfo bInfo : toUninstall) {
bundleState.uninstallBundle(bInfo);
}
bundleState.resolve(true);
manipulator.getConfigData().setBundles(bundleState.getExpectedState());
}
@Override
public void cleanup(Manipulator manipulator) {
File outputFile = getConfigFile(manipulator);
outputFile.delete();
if (outputFile.getParentFile().isDirectory())
outputFile.getParentFile().delete();
}
private boolean hasBaseChanged(URI installArea, File outputFolder) {
String rememberedTimestamp;
String extensionTimestsamp;
try {
rememberedTimestamp = (String) loadProperties(
new File(outputFolder, SimpleConfiguratorImpl.BASE_TIMESTAMP_FILE_BUNDLESINFO))
.get(SimpleConfiguratorImpl.KEY_BUNDLESINFO_TIMESTAMP);
extensionTimestsamp = (String) loadProperties(
new File(outputFolder, SimpleConfiguratorImpl.BASE_TIMESTAMP_FILE_BUNDLESINFO))
.get(SimpleConfiguratorImpl.KEY_EXT_TIMESTAMP);
} catch (IOException e) {
return false;
}
if (rememberedTimestamp == null)
return false;
File sharedBundlesInfo = new File(URIUtil.append(installArea, SHARED_BUNDLES_INFO));
if (!sharedBundlesInfo.exists())
return true;
return !(String.valueOf(SimpleConfiguratorUtils.getFileLastModified(sharedBundlesInfo))
.equals(rememberedTimestamp)
&& String.valueOf(SimpleConfiguratorUtils.getExtendedTimeStamp()).equals(extensionTimestsamp));
}
private boolean isSharedInstallSetup(File installArea, File outputFile) {
// An instance is treated as shared if the bundles.info file is not located in
// the install area.
return !new File(installArea, SHARED_BUNDLES_INFO).equals(outputFile);
}
private 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) {
// Do nothing
}
is = null;
}
return props;
}
}