Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEd Merks2016-05-17 12:21:21 -0400
committerEd Merks2016-05-17 12:21:21 -0400
commit2d874b3247457318ae4af3381eb5c8d4314cff12 (patch)
treede5e7f30e2745f48505efdc9c677b6ce1bbbf0e3
parent595cd198ec6874f4babfbb30da59940c5dcb51a0 (diff)
downloadorg.eclipse.oomph-2d874b3247457318ae4af3381eb5c8d4314cff12.tar.gz
org.eclipse.oomph-2d874b3247457318ae4af3381eb5c8d4314cff12.tar.xz
org.eclipse.oomph-2d874b3247457318ae4af3381eb5c8d4314cff12.zip
[485476] Eclipse OOpmh Installed Eclipse.App fails when moved
https://bugs.eclipse.org/bugs/show_bug.cgi?id=485476
-rw-r--r--plugins/org.eclipse.oomph.p2.core/META-INF/MANIFEST.MF1
-rw-r--r--plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/core/Profile.java2
-rw-r--r--plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/AgentImpl.java470
-rw-r--r--plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/BundlePoolImpl.java13
-rw-r--r--plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/LazyProfile.java16
-rw-r--r--plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/PersistentMap.java14
-rw-r--r--plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/ProfileImpl.java14
-rw-r--r--plugins/org.eclipse.oomph.setup.core/src/org/eclipse/oomph/setup/internal/core/SetupTaskPerformer.java22
-rw-r--r--plugins/org.eclipse.oomph.setup.p2/src/org/eclipse/oomph/setup/p2/impl/P2TaskImpl.java116
-rw-r--r--plugins/org.eclipse.oomph.setup.ui/src/org/eclipse/oomph/setup/ui/SetupUIPlugin.java23
-rw-r--r--setups/OomphInstaller.setup12
11 files changed, 565 insertions, 138 deletions
diff --git a/plugins/org.eclipse.oomph.p2.core/META-INF/MANIFEST.MF b/plugins/org.eclipse.oomph.p2.core/META-INF/MANIFEST.MF
index 2aa02fd0c..967dd8857 100644
--- a/plugins/org.eclipse.oomph.p2.core/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.oomph.p2.core/META-INF/MANIFEST.MF
@@ -24,6 +24,7 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)",
org.eclipse.equinox.p2.director;bundle-version="[2.0.0,3.0.0)",
org.eclipse.equinox.p2.operations;bundle-version="[2.0.0,3.0.0)",
org.eclipse.equinox.p2.touchpoint.natives;bundle-version="[1.0.0,2.0.0)",
+ org.eclipse.equinox.p2.touchpoint.eclipse;bundle-version="[2.0.0,3.0.0)",
org.eclipse.oomph.p2;bundle-version="[1.4.0,2.0.0)";visibility:=reexport
Bundle-ActivationPolicy: lazy
Service-Component: META-INF/lazyProfileRegistry.xml, META-INF/lazyProfileRegistry_bug390470.xml
diff --git a/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/core/Profile.java b/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/core/Profile.java
index 081d443bd..c59f904ba 100644
--- a/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/core/Profile.java
+++ b/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/core/Profile.java
@@ -27,6 +27,8 @@ public interface Profile extends IProfile, AgentElement
public static final String PROP_PROFILE_REFERENCER = "org.eclipse.oomph.p2.profile.referencer"; //$NON-NLS-1$
+ public static final String PROP_PROFILE_SHARED_POOL = "org.eclipse.oomph.p2.profile.shared.pool"; //$NON-NLS-1$
+
public static final String PROP_IU_COMPATIBILITY = "org.eclipse.oomph.p2.iu.compatibility"; //$NON-NLS-1$
public static final String TYPE_INSTALLATION = "Installation";
diff --git a/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/AgentImpl.java b/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/AgentImpl.java
index 58f5500ee..2cb5674b2 100644
--- a/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/AgentImpl.java
+++ b/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/AgentImpl.java
@@ -14,14 +14,26 @@ import org.eclipse.oomph.p2.P2Exception;
import org.eclipse.oomph.p2.core.Agent;
import org.eclipse.oomph.p2.core.AgentManager;
import org.eclipse.oomph.p2.core.BundlePool;
+import org.eclipse.oomph.p2.core.P2Util;
import org.eclipse.oomph.p2.core.Profile;
import org.eclipse.oomph.p2.core.ProfileCreator;
+import org.eclipse.oomph.util.IOUtil;
import org.eclipse.oomph.util.PropertiesUtil;
import org.eclipse.oomph.util.StringUtil;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.URIConverter;
+
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Platform;
+import org.eclipse.equinox.internal.p2.engine.CommitOperationEvent;
import org.eclipse.equinox.internal.p2.repository.Transport;
+import org.eclipse.equinox.internal.p2.touchpoint.eclipse.EclipseTouchpoint;
+import org.eclipse.equinox.internal.p2.touchpoint.eclipse.Util;
+import org.eclipse.equinox.internal.p2.update.Configuration;
+import org.eclipse.equinox.internal.p2.update.Site;
+import org.eclipse.equinox.internal.provisional.p2.core.eventbus.IProvisioningEventBus;
+import org.eclipse.equinox.internal.provisional.p2.core.eventbus.SynchronousProvisioningListener;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.core.IProvisioningAgentProvider;
import org.eclipse.equinox.p2.core.ProvisionException;
@@ -29,7 +41,10 @@ import org.eclipse.equinox.p2.core.spi.IAgentService;
import org.eclipse.equinox.p2.engine.IEngine;
import org.eclipse.equinox.p2.engine.IProfile;
import org.eclipse.equinox.p2.engine.IProfileRegistry;
+import org.eclipse.equinox.p2.metadata.IArtifactKey;
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.planner.IPlanner;
+import org.eclipse.equinox.p2.query.QueryUtil;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
@@ -40,10 +55,15 @@ import org.osgi.framework.ServiceReference;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.EventObject;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* @author Eike Stepper
@@ -53,6 +73,9 @@ public class AgentImpl extends AgentManagerElementImpl implements Agent
{
public static final String ENGINE_PATH = "org.eclipse.equinox.p2.engine";
+ private static final Pattern ECLIPSE_INI_SECTION_PATTERN = Pattern.compile("^(-vmargs)([\n\r]+.*)\\z|^(-[^\\n\\r]*[\\n\\r]*)((?:^[^-][^\\n\\r]*)*[\\n\\r]*)",
+ Pattern.MULTILINE | Pattern.DOTALL);
+
private final AgentManagerImpl agentManager;
private final File location;
@@ -93,6 +116,13 @@ public class AgentImpl extends AgentManagerElementImpl implements Agent
}
@Override
+ protected BundlePool loadElement(String key, String extraInfo)
+ {
+ // TODO
+ return super.loadElement(key, extraInfo);
+ }
+
+ @Override
protected void initializeFirstTime()
{
IProfileRegistry profileRegistry = getProfileRegistry();
@@ -129,6 +159,13 @@ public class AgentImpl extends AgentManagerElementImpl implements Agent
}
@Override
+ protected Profile loadElement(String key, String extraInfo)
+ {
+ // TODO
+ return super.loadElement(key, extraInfo);
+ }
+
+ @Override
protected void initializeFirstTime()
{
fillProfileMap(this);
@@ -467,7 +504,60 @@ public class AgentImpl extends AgentManagerElementImpl implements Agent
provisioningAgent.registerService(IArtifactRepositoryManager.SERVICE_NAME, artifactRepositoryManager);
}
+ IProvisioningEventBus eventBus = (IProvisioningEventBus)provisioningAgent.getService(IProvisioningEventBus.SERVICE_NAME);
+ if (eventBus != null)
+ {
+ eventBus.addListener(new SynchronousProvisioningListener()
+ {
+ public void notify(EventObject event)
+ {
+ if (event instanceof CommitOperationEvent)
+ {
+ CommitOperationEvent commitOperationEvent = (CommitOperationEvent)event;
+ IProfile profile = commitOperationEvent.getProfile();
+ if (Profile.TYPE_INSTALLATION.equals(profile.getProperty(Profile.PROP_PROFILE_TYPE)))
+ {
+ // If this is a commit of an Oomph-created installation profile, then adjust the installation details.
+ adjustInstallation(profile);
+ }
+ }
+ }
+ });
+ }
+
this.provisioningAgent = provisioningAgent;
+
+ Profile currentProfile = getCurrentProfile();
+ if (currentProfile instanceof ProfileImpl)
+ {
+ File cachedInstallFolder = currentProfile.getInstallFolder();
+ if (cachedInstallFolder != null)
+ {
+ String actualInstallFolderLocation = currentProfile.getProperty(IProfile.PROP_INSTALL_FOLDER);
+ if (actualInstallFolderLocation != null)
+ {
+ File actualInstallFolder = new File(actualInstallFolderLocation);
+ if (!actualInstallFolder.equals(cachedInstallFolder))
+ {
+ ((ProfileImpl)currentProfile).setInstallFolder(actualInstallFolder);
+
+ BundlePool bundlePool = currentProfile.getBundlePool();
+ if (bundlePool instanceof BundlePoolImpl)
+ {
+ File bundlePoolLocation = bundlePool.getLocation();
+ if (bundlePoolLocation.equals(cachedInstallFolder))
+ {
+ ((BundlePoolImpl)bundlePool).setLocation(actualInstallFolder);
+ bundlePoolMap.remap(cachedInstallFolder.toString(), actualInstallFolderLocation);
+ }
+ }
+
+ String profileID = currentProfile.getProfileId();
+ profileMap.save(profileID, profileID);
+ }
+ }
+ }
+ }
}
}
@@ -661,4 +751,384 @@ public class AgentImpl extends AgentManagerElementImpl implements Agent
return provisioningAgent;
}
+
+ private void adjustInstallation(IProfile profile)
+ {
+ // This property should always be in a well-formed profile.
+ String bundlePoolLocation = profile.getProperty(IProfile.PROP_CACHE);
+ if (bundlePoolLocation != null)
+ {
+ // There should always be a bundle pool for this location.
+ BundlePool bundlePool = getBundlePool(new File(bundlePoolLocation));
+ if (bundlePool != null)
+ {
+ // And there should always be an install folder in a well-formed profile.
+ // On the Mac, this should point at the Contents/Eclipse subfolder.
+ String installFolderLocation = profile.getProperty(IProfile.PROP_INSTALL_FOLDER);
+ if (installFolderLocation != null)
+ {
+ // The configuration folder should be nested in this install folder.
+ File installFolder = new File(installFolderLocation);
+ File configurationFolder = new File(installFolder, "configuration");
+
+ // If this is an installation based on a shared pool...
+ if ("true".equals(profile.getProperty(Profile.PROP_PROFILE_SHARED_POOL)))
+ {
+ try
+ {
+ adjustConfigIni(profile, bundlePool, configurationFolder);
+ }
+ catch (Exception ex)
+ {
+ // Ignore.
+ }
+
+ try
+ {
+ adjustLauncherIni(profile, installFolder, true);
+ }
+ catch (Exception ex)
+ {
+ // Ignore.
+ }
+
+ try
+ {
+ adjustBundlesInfo(configurationFolder);
+ }
+ catch (Exception ex)
+ {
+ // Ignore.
+ }
+
+ try
+ {
+ adjustPlatformXML(bundlePoolLocation, configurationFolder);
+ }
+ catch (Exception ex)
+ {
+ // Ignore.
+ }
+ }
+ else
+ {
+ try
+ {
+ adjustLauncherIni(profile, installFolder, false);
+ }
+ catch (Exception ex)
+ {
+ // Ignore.
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void adjustConfigIni(IProfile profile, BundlePool bundlePool, File configurationFolder)
+ {
+ // It should have a config.ini file to set various system properties.
+ // If it doesn't exist, it's not a well-formed installation so an exception will be thrown loading it and we'll exit this method as a result.
+ File configIniFile = new File(configurationFolder, "config.ini");
+ Map<String, String> configProperties = PropertiesUtil.loadProperties(configIniFile);
+
+ // The OSGi slash path might be specified using platform:/base/<bundle-id>
+ // but that doesn't work for a shared installation because the referenced bundle doesn't physically exist in the installation.
+ boolean changed = false;
+ String splashPath = configProperties.get("osgi.splashPath");
+ if (splashPath != null)
+ {
+ // If there is a splash path with a URI of this form...
+ org.eclipse.emf.common.util.URI uri = org.eclipse.emf.common.util.URI.createURI(splashPath);
+ if ("platform".equals(uri.scheme()) && uri.segmentCount() >= 2 && "base".equals(uri.segment(0)))
+ {
+ // Determine which IU resolves for bundle-id...
+ LOOP: for (IInstallableUnit installableUnit : P2Util.asIterable(profile.query(QueryUtil.createIUQuery(uri.lastSegment()), null)))
+ {
+ // Look at all that IU's artifacts.
+ for (IArtifactKey artifactKey : installableUnit.getArtifacts())
+ {
+ // If the file slash.bmp exists in that artifact jar or folder...
+ File artifactFile = bundlePool.getFileArtifactRepository().getArtifactFile(artifactKey);
+ if (artifactFile.isDirectory() ? new File(artifactFile, "splash.bmp").exists()
+ : URIConverter.INSTANCE.exists(URI.createURI("archive:" + URI.createFileURI(artifactFile.getAbsolutePath() + "!/splash.bmp")), null))
+ {
+ // Replace the value with the absolute URI of the artifact in the shared bundle pool.
+ // The launcher and p2 have a bad habit of using URL.getPath which does not decode encoded character, e.g., %20 is not decode to the space
+ // character.
+ // So better we not produce an encoded URI.
+ configProperties.put("osgi.splashPath", createFileURI(artifactFile));
+ changed = true;
+ break LOOP;
+ }
+ }
+ }
+ }
+ }
+
+ // The OSGi framework property might be a relative path, e.g., file:../<path-to-shared-pool>.
+ String osgiFramework = configProperties.get("osgi.framework");
+ if (osgiFramework != null)
+ {
+ // If file: is not followed by a '/', the URI won't be considered hierarchical even though it has file scheme.
+ URI uri = URI.createURI(osgiFramework);
+ if (uri.hasOpaquePart() && "file".equals(uri.scheme()))
+ {
+ // Resolve the relative path in the URI against the configuration folder's URI.
+ // If that file exists, as expected will be the case.
+ URI configurationFolderURI = URI.createFileURI(configurationFolder.toString());
+ URI absoluteOSGiFrameworkLocation = URI.createURI(uri.opaquePart()).resolve(configurationFolderURI);
+ if (new File(absoluteOSGiFrameworkLocation.toFileString()).exists())
+ {
+ // Replace the value with the absolute URI of the OSGi framework bundle.
+ // The launcher and p2 have a bad habit of using URL.getPath which does not decode encoded character, e.g., %20 is not decode to the space character.
+ // So better we not produce an encoded URI.
+ configProperties.put("osgi.framework", createFileURI(absoluteOSGiFrameworkLocation.toFileString()));
+ changed = true;
+ }
+ }
+ }
+
+ // If there were changes made, save the configuration.
+ if (changed)
+ {
+ PropertiesUtil.saveProperties(configIniFile, configProperties, false, true, "This configuration file was written by: " + AgentImpl.class.getName());
+ }
+ }
+
+ private void adjustLauncherIni(IProfile profile, File installFolder, boolean sharedPool)
+ {
+ // We need to modify the eclipse.ini.
+ // For generality we'll check the launcher name property to compute the name of the launcher ini.
+ String launcherName = profile.getProperty(EclipseTouchpoint.PROFILE_PROP_LAUNCHER_NAME);
+ File iniFile = new File(installFolder, launcherName == null ? "eclipse.ini" : launcherName + ".ini");
+ String contents = new String(IOUtil.readFile(iniFile));
+
+ // We will process all the sections, keeping them in a map from which we'll compute the modified contents.
+ Map<String, String> map = new LinkedHashMap<String, String>();
+ for (Matcher matcher = ECLIPSE_INI_SECTION_PATTERN.matcher(contents); matcher.find();)
+ {
+ // Depending on which part of the pattern matched, we'll need to select the argument and extension from the constituent parts.
+ String argument = matcher.group(3);
+ String extension;
+ if (argument == null)
+ {
+ // If there is no third group, then the first part of the pattern matched, i.e., the -vmargs and the associated args.
+ argument = matcher.group(1);
+ extension = matcher.group(2);
+ }
+ else
+ {
+ // Otherwise the fourth group is the value part of the argument; it could be an empty string.
+ extension = matcher.group(4);
+ }
+
+ // This will remove duplicates as well.
+ if (!argument.startsWith("--launcher.XXMaxPermSize") && !argument.startsWith("-startup") || !map.containsKey(argument))
+ {
+ map.put(argument, extension);
+ }
+ }
+
+ // If there are relative paths, that needs to be made absolute, this is used as the base URI against which to resolve them.
+ // We will build the new contents from the entries in the map.
+ // And will preserve the existing line feed convention if we need to add new lines.
+ URI baseURI = URI.createFileURI(installFolder.toString()).appendSegment("");
+ StringBuilder newContents = new StringBuilder();
+ String nl = null;
+ for (Map.Entry<String, String> entry : map.entrySet())
+ {
+ // The keys will generally include the line feed character, so we trim that off when inspecting the key.
+ String key = entry.getKey();
+ String trimmedKey = key.trim();
+ String value = entry.getValue();
+ if (sharedPool)
+ {
+ if ("-startup".equals(trimmedKey))
+ {
+ // For the -startup value, check if it's a relative path.
+ if (value.startsWith("../"))
+ {
+ // Resolve it against the base URI and check that this file actually exists.
+ URI absoluteBundleLocation = URI.createURI(value.trim()).resolve(baseURI);
+ if (new File(absoluteBundleLocation.toFileString()).exists())
+ {
+ // We'll copy this to the installation folder.
+ // We do this because the Equinox launcher org.eclipse.equinox.launcher.Main.getInstallLocation()
+ // computes the installation location from the location of this bundle.
+ // If we leave it as a relative path that references something outside the installation,
+ // the installation can't roam.
+ File localStartBundle = new File(new File(installFolder, "plugins"), absoluteBundleLocation.lastSegment());
+ IOUtil.copyFile(new File(absoluteBundleLocation.toFileString()), localStartBundle);
+
+ // Remember the line feed convention used for this section.
+ nl = key.substring(trimmedKey.length());
+
+ // The value is therefore the relative path to this copied target.
+ value = (Platform.OS_MACOSX.equals(Util.getOSFromProfile(profile)) ? "../Eclipse/plugins/" : "plugins/") + absoluteBundleLocation.lastSegment()
+ + nl;
+ }
+ }
+ }
+ else if ("--launcher.library".equals(trimmedKey))
+ {
+ // If the launcher library, where the companion shared library is located, is a relative path.
+ if (value.startsWith("../"))
+ {
+ // Resolve it against against the base to determine the absolute location, checking that actually exists.
+ URI absoluteBundleLocation = URI.createURI(value.trim()).resolve(baseURI);
+ if (new File(absoluteBundleLocation.toFileString()).exists())
+ {
+ // Replace the value with this absolute path, preserving the existing line feed convention.
+ nl = key.substring(trimmedKey.length());
+ value = absoluteBundleLocation.toFileString() + nl;
+ }
+ }
+ }
+ else if ("-install".equals(trimmedKey))
+ {
+ // Omit the install argument.
+ // This is generally an absolute path that effectively points at the folder in which the launcher ini is located.
+ // This breaks the ability for this installation to roam.
+ // Instead of this argument, we've copied the startup bundle into the installation, eliminating the need for this value.
+ continue;
+ }
+ }
+
+ newContents.append(key);
+ newContents.append(value);
+ }
+
+ if (!contents.contentEquals(newContents))
+ {
+ IOUtil.writeFile(iniFile, newContents.toString().getBytes());
+ }
+ }
+
+ private void adjustBundlesInfo(File configurationFolder)
+ {
+ // For an installation with a shared bundle pool, this will be a relative path that navigates outside of the installation.
+ // In that case, we want to make those references be absolute.
+ File bundlesInfoFile = new File(configurationFolder, "org.eclipse.equinox.simpleconfigurator/bundles.info");
+
+ // Read all the lines as UTF-8 as documented in a comment in that file.
+ List<String> lines = IOUtil.readLines(bundlesInfoFile, "UTF-8");
+ List<String> result = new ArrayList<String>();
+ boolean changed = false;
+ URI configurationFolderURI = URI.createFileURI(configurationFolder.toString());
+
+ for (String line : lines)
+ {
+ // Ignore the comment lines.
+ if (!line.startsWith("#"))
+ {
+ // Lines of of this form:
+ // <bundle-id>,<version>,<location-URI>,<start-level>,<true|false>
+ // As such, we can split the lines on ',' and generally expect 5 elements in the list.
+ List<String> elements = StringUtil.explode(line, ",");
+ if (elements.size() > 2)
+ {
+ // If the third element that needs to be modified it it's a relative path.
+ String bundleReference = elements.get(2);
+ if (bundleReference.startsWith("../"))
+ {
+ // Resolve it against the location of the configuration folder, and if that bundle exists, as expected...
+ URI absoluteBundleLocation = URI.createURI(bundleReference).resolve(configurationFolderURI);
+ if (new File(absoluteBundleLocation.toFileString()).exists())
+ {
+ // Replace the element, with that absolute URI,
+ // add that replacement to the result,
+ // and continue with the next line.
+ elements.set(2, createFileURI(absoluteBundleLocation.toFileString()));
+ result.add(StringUtil.implode(elements, ',', (char)0));
+ changed = true;
+ continue;
+ }
+ }
+ }
+ }
+
+ // Otherwise add the line as-is to the result.
+ result.add(line);
+ }
+
+ // If there are any changes...
+ if (changed)
+ {
+ // Write the modified result back out to the bundles.info file.
+ IOUtil.writeLines(bundlesInfoFile, "UTF-8", result);
+ }
+ }
+
+ private void adjustPlatformXML(String bundlePoolLocation, File configurationFolder) throws ProvisionException
+ {
+ // The platform.xml, initially will have the wrong site policy.
+ // Also, regular p2 updates will mangle the site URL to be an poorly-formed relative file URI,
+ // which again breaks the ability for the installation to roam.
+ File platformXML = new File(configurationFolder, "org.eclipse.update/platform.xml");
+ if (platformXML.isFile())
+ {
+ URI configurationFolderURI = URI.createFileURI(configurationFolder.toString());
+ Configuration configuration = Configuration.load(platformXML, null);
+ boolean changed = true;
+ for (Site site : configuration.getSites())
+ {
+ // If the site URI is of the form file:../<path> then we need to make it absolute.
+ URI siteURI = URI.createURI(site.getUrl());
+ if (siteURI.hasOpaquePart() && "file".equals(siteURI.scheme()))
+ {
+ // Resolve it against the location of the configuration folder, checking if the folder really exists.
+ URI absoluteSiteURI = URI.createURI(siteURI.opaquePart()).resolve(configurationFolderURI);
+ if (new File(absoluteSiteURI.toFileString()).exists())
+ {
+ // If so, we use this absolute URI instead and change the configuration to specify it.
+ siteURI = absoluteSiteURI;
+ site.setUrl(absoluteSiteURI.toFileString());
+ changed = true;
+ }
+ }
+
+ // If the policy isn't managed all the bundles in the pool will be visible, which is very bad.
+ if (!Site.POLICY_MANAGED_ONLY.equals(site.getPolicy()))
+ {
+ // If this site refers to the shared bundle pool, change the policy to be managed.
+ File siteLocation = new File(siteURI.toFileString());
+ if (siteLocation.equals(new File(bundlePoolLocation)))
+ {
+ site.setPolicy(Site.POLICY_MANAGED_ONLY);
+ changed = true;
+ break;
+ }
+ }
+ }
+
+ // If something has changed, save the configuration.
+ if (changed)
+ {
+ configuration.save(platformXML, null);
+ }
+ }
+ }
+
+ private static String createFileURI(String path)
+ {
+ return createFileURI(new File(path));
+ }
+
+ private static String createFileURI(File file)
+ {
+ String path = file.getPath();
+ if (File.separatorChar != '/')
+ {
+ path = path.replace(File.separatorChar, '/');
+ }
+
+ if (file.isAbsolute() && !path.startsWith(File.separator))
+ {
+ return "file:/" + path;
+ }
+
+ return "file:" + path;
+ }
}
diff --git a/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/BundlePoolImpl.java b/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/BundlePoolImpl.java
index eeb1c4861..539e1968d 100644
--- a/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/BundlePoolImpl.java
+++ b/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/BundlePoolImpl.java
@@ -34,17 +34,16 @@ public class BundlePoolImpl extends AgentManagerElementImpl implements BundlePoo
{
private final Agent agent;
- private final File location;
+ private File location;
- private final String path;
+ private String path;
private IFileArtifactRepository fileArtifactRepository;
public BundlePoolImpl(AgentImpl agent, File location)
{
this.agent = agent;
- this.location = location;
- path = location.getAbsolutePath();
+ setLocation(location);
}
@Override
@@ -68,6 +67,12 @@ public class BundlePoolImpl extends AgentManagerElementImpl implements BundlePoo
return location;
}
+ public void setLocation(File location)
+ {
+ this.location = location;
+ path = location.getAbsolutePath();
+ }
+
public Set<String> getClients()
{
return ((AgentManagerImpl)agent.getAgentManager()).getClientsFor(path);
diff --git a/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/LazyProfile.java b/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/LazyProfile.java
index 3141b5c27..36641c27c 100644
--- a/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/LazyProfile.java
+++ b/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/LazyProfile.java
@@ -14,6 +14,7 @@ import org.eclipse.oomph.p2.P2Exception;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.equinox.internal.p2.engine.ISurrogateProfileHandler;
+import org.eclipse.equinox.internal.p2.engine.Profile;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.engine.IProfile;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
@@ -152,7 +153,20 @@ public final class LazyProfile extends org.eclipse.equinox.internal.p2.engine.Pr
@Override
public void setProperty(String key, String value)
{
- getDelegate().setProperty(key, value);
+ Profile delegate = getDelegate();
+ if (IProfile.PROP_CACHE.equals(key))
+ {
+ // If we're setting the cache property,
+ // and this is a profile for an Oomph installation with a shared bundle pool for which the cache property has already been set,
+ // we don't want org.eclipse.equinox.internal.p2.engine.SimpleProfileRegistry.updateRoamingProfile(Profile)
+ // to change the cache location to point to the installation.
+ if ("true".equals(delegate.getProperty(org.eclipse.oomph.p2.core.Profile.PROP_PROFILE_SHARED_POOL)) && delegate.getProperty(IProfile.PROP_CACHE) != null)
+ {
+ return;
+ }
+ }
+
+ delegate.setProperty(key, value);
}
@Override
diff --git a/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/PersistentMap.java b/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/PersistentMap.java
index b037e2cc6..e73a0cb08 100644
--- a/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/PersistentMap.java
+++ b/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/PersistentMap.java
@@ -159,6 +159,18 @@ public abstract class PersistentMap<E>
return element;
}
+ public final synchronized E remap(String oldKey, String newKey)
+ {
+ E element = elements.remove(oldKey);
+ if (element != null)
+ {
+ elements.put(newKey, element);
+ save(newKey, oldKey);
+ }
+
+ return element;
+ }
+
public final synchronized void removeElement(String key)
{
E element = elements.remove(key);
@@ -248,7 +260,7 @@ public abstract class PersistentMap<E>
}
}
- private void save(String addedKey, final String removedKey)
+ public void save(String addedKey, final String removedKey)
{
if (file != null)
{
diff --git a/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/ProfileImpl.java b/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/ProfileImpl.java
index 6b7749332..64be977f4 100644
--- a/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/ProfileImpl.java
+++ b/plugins/org.eclipse.oomph.p2.core/src/org/eclipse/oomph/p2/internal/core/ProfileImpl.java
@@ -132,9 +132,9 @@ public class ProfileImpl extends AgentManagerElementImpl implements Profile, Per
private final String type;
- private final File installFolder;
+ private File installFolder;
- private final File referencer;
+ private File referencer;
private IProfile delegate;
@@ -198,11 +198,21 @@ public class ProfileImpl extends AgentManagerElementImpl implements Profile, Per
return installFolder;
}
+ public void setInstallFolder(File installFolder)
+ {
+ this.installFolder = installFolder;
+ }
+
public File getReferencer()
{
return referencer;
}
+ public void setReferencer(File referencer)
+ {
+ this.referencer = referencer;
+ }
+
public String getExtraInfo()
{
List<String> tokens = new ArrayList<String>();
diff --git a/plugins/org.eclipse.oomph.setup.core/src/org/eclipse/oomph/setup/internal/core/SetupTaskPerformer.java b/plugins/org.eclipse.oomph.setup.core/src/org/eclipse/oomph/setup/internal/core/SetupTaskPerformer.java
index 863a23121..aa14a96e7 100644
--- a/plugins/org.eclipse.oomph.setup.core/src/org/eclipse/oomph/setup/internal/core/SetupTaskPerformer.java
+++ b/plugins/org.eclipse.oomph.setup.core/src/org/eclipse/oomph/setup/internal/core/SetupTaskPerformer.java
@@ -123,8 +123,6 @@ import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.equinox.internal.p2.update.Configuration;
-import org.eclipse.equinox.internal.p2.update.Site;
import org.eclipse.equinox.p2.metadata.VersionRange;
import org.osgi.framework.Bundle;
@@ -2890,26 +2888,6 @@ public class SetupTaskPerformer extends AbstractSetupTaskContext
File bundlePool = profile.getBundlePool().getLocation();
if (!installFolder.equals(bundlePool))
{
- File platformXML = new File(productConfigurationLocation, "org.eclipse.update/platform.xml");
- if (platformXML.isFile())
- {
- Configuration configuration = Configuration.load(platformXML, null);
- for (Site site : configuration.getSites())
- {
- if (!Site.POLICY_MANAGED_ONLY.equals(site.getPolicy()))
- {
- File siteLocation = new File(URI.createURI(site.getUrl()).toFileString());
- if (siteLocation.equals(bundlePool))
- {
- log("Changing " + platformXML + " (policy=" + Site.POLICY_MANAGED_ONLY + ")", false, Severity.OK);
- site.setPolicy(Site.POLICY_MANAGED_ONLY);
- configuration.save(platformXML, null);
- break;
- }
- }
- }
- }
-
File garbageCollectorPreferences = new File(productConfigurationLocation, ".settings/org.eclipse.equinox.p2.garbagecollector.prefs");
IOUtil.writeLines(garbageCollectorPreferences, "8859_1", Arrays.asList(new String[] { "eclipse.preferences.version=1", "gc_enabled=false" }));
}
diff --git a/plugins/org.eclipse.oomph.setup.p2/src/org/eclipse/oomph/setup/p2/impl/P2TaskImpl.java b/plugins/org.eclipse.oomph.setup.p2/src/org/eclipse/oomph/setup/p2/impl/P2TaskImpl.java
index 56626843c..8bb1036c5 100644
--- a/plugins/org.eclipse.oomph.setup.p2/src/org/eclipse/oomph/setup/p2/impl/P2TaskImpl.java
+++ b/plugins/org.eclipse.oomph.setup.p2/src/org/eclipse/oomph/setup/p2/impl/P2TaskImpl.java
@@ -30,10 +30,8 @@ import org.eclipse.oomph.setup.impl.SetupTaskImpl;
import org.eclipse.oomph.setup.internal.p2.SetupP2Plugin;
import org.eclipse.oomph.setup.p2.P2Task;
import org.eclipse.oomph.setup.p2.SetupP2Package;
-import org.eclipse.oomph.setup.util.DownloadUtil;
import org.eclipse.oomph.util.Confirmer;
import org.eclipse.oomph.util.Confirmer.Confirmation;
-import org.eclipse.oomph.util.IORuntimeException;
import org.eclipse.oomph.util.IOUtil;
import org.eclipse.oomph.util.OS;
import org.eclipse.oomph.util.Pair;
@@ -60,7 +58,6 @@ import org.eclipse.equinox.p2.core.UIServices;
import org.eclipse.equinox.p2.engine.IProfile;
import org.eclipse.equinox.p2.engine.IProfileRegistry;
import org.eclipse.equinox.p2.engine.IProvisioningPlan;
-import org.eclipse.equinox.p2.metadata.IArtifactKey;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.ILicense;
import org.eclipse.equinox.p2.metadata.VersionRange;
@@ -72,7 +69,6 @@ import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
import java.io.File;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.security.cert.Certificate;
@@ -81,12 +77,9 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
-import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
/**
* <!-- begin-user-doc -->
@@ -638,8 +631,6 @@ public class P2TaskImpl extends SetupTaskImpl implements P2Task
public void perform(final SetupTaskContext context) throws Exception
{
File eclipseDir = context.getProductLocation();
- File eclipseIni = new File(eclipseDir, "eclipse.ini");
- boolean eclipseIniExisted = eclipseIni.exists();
boolean offline = context.isOffline();
context.log("Offline = " + offline);
@@ -754,53 +745,6 @@ public class P2TaskImpl extends SetupTaskImpl implements P2Task
}
}
}
-
- if (eclipseIniExisted)
- {
- checkEclipseIniForDuplicates(context, eclipseIni);
- }
-
- updateSplash(context, profile);
- }
-
- private void updateSplash(final SetupTaskContext context, Profile profile)
- {
- BundlePool bundlePool = profile.getBundlePool();
- if (bundlePool != null)
- {
- File productConfigurationLocation = context.getProductConfigurationLocation();
- try
- {
- File configIniFile = new File(productConfigurationLocation, "config.ini");
- Map<String, String> properties = PropertiesUtil.loadProperties(configIniFile);
- String splashPath = properties.get("osgi.splashPath");
- if (splashPath != null)
- {
- org.eclipse.emf.common.util.URI uri = org.eclipse.emf.common.util.URI.createURI(splashPath);
- if ("platform".equals(uri.scheme()) && uri.segmentCount() >= 2 && "base".equals(uri.segment(0)))
- {
- for (IInstallableUnit installableUnit : P2Util.asIterable(profile.query(QueryUtil.createIUQuery(uri.lastSegment()), null)))
- {
- for (IArtifactKey artifactKey : installableUnit.getArtifacts())
- {
- File artifactFile = bundlePool.getFileArtifactRepository().getArtifactFile(artifactKey);
- if (new File(artifactFile, "splash.bmp").exists())
- {
- properties.put("osgi.splashPath", org.eclipse.emf.common.util.URI.createFileURI(artifactFile.toString()).toString());
- saveConfigIni(configIniFile, properties, P2TaskImpl.class);
-
- return;
- }
- }
- }
- }
- }
- }
- catch (IORuntimeException ex)
- {
- // Ignore.
- }
- }
}
private Profile getProfile(final SetupTaskContext context, String profileID) throws Exception
@@ -811,8 +755,10 @@ public class P2TaskImpl extends SetupTaskImpl implements P2Task
BundlePool bundlePool;
String bundlePoolLocation = (String)context.get(AgentManager.PROP_BUNDLE_POOL_LOCATION);
+ boolean sharedPool;
if (bundlePoolLocation != null)
{
+ sharedPool = true;
bundlePool = P2Util.getAgentManager().getBundlePool(new File(bundlePoolLocation));
// TODO Remove the following two lines after bug 485018 has been fixed.
@@ -821,6 +767,7 @@ public class P2TaskImpl extends SetupTaskImpl implements P2Task
}
else
{
+ sharedPool = false;
File agentLocation = new File(context.getProductLocation(), "p2");
Agent agent = P2Util.createAgent(agentLocation);
bundlePool = agent.addBundlePool(agentLocation.getParentFile());
@@ -846,6 +793,13 @@ public class P2TaskImpl extends SetupTaskImpl implements P2Task
profileCreator.addOS(os.getOsgiOS());
profileCreator.addWS(os.getOsgiWS());
profileCreator.addArch(os.getOsgiArch());
+ profileCreator.setRoaming(true);
+
+ // This property is used in org.eclipse.oomph.p2.internal.core.LazyProfile.setProperty(String, String)
+ // to ensure that when org.eclipse.equinox.internal.p2.engine.SimpleProfileRegistry.updateRoamingProfile(Profile)
+ // updates the profile's install location, it doesn't also replace the shared pool location with a local pool.
+ // Of course if this is an installation with a local pool, it should be replace during a roaming update.
+ profileCreator.set(Profile.PROP_PROFILE_SHARED_POOL, sharedPool);
profile = profileCreator.create();
}
@@ -974,56 +928,6 @@ public class P2TaskImpl extends SetupTaskImpl implements P2Task
}
}
- private static void checkEclipseIniForDuplicates(final SetupTaskContext context, File iniFile)
- {
- FileOutputStream out = null;
-
- try
- {
- org.eclipse.emf.common.util.URI uri = org.eclipse.emf.common.util.URI.createFileURI(iniFile.toString());
- String contents = DownloadUtil.load(context.getURIConverter(), uri, null);
- Pattern section = Pattern.compile("^(-vmargs)([\n\r]+.*)\\z|^(-[^\\n\\r]*[\\n\\r]*)((?:^[^-][^\\n\\r]*)*[\\n\\r]*)", Pattern.MULTILINE | Pattern.DOTALL);
- Map<String, String> map = new LinkedHashMap<String, String>();
- for (Matcher matcher = section.matcher(contents); matcher.find();)
- {
- String argument = matcher.group(3);
- String extension;
- if (argument == null)
- {
- argument = matcher.group(1);
- extension = matcher.group(2);
- }
- else
- {
- extension = matcher.group(4);
- }
-
- if (!argument.startsWith("--launcher.XXMaxPermSize") || !map.containsKey(argument))
- {
- map.put(argument, extension);
- }
- }
-
- StringBuilder newContents = new StringBuilder();
- for (Map.Entry<String, String> entry : map.entrySet())
- {
- newContents.append(entry.getKey());
- newContents.append(entry.getValue());
- }
-
- out = new FileOutputStream(iniFile);
- out.write(newContents.toString().getBytes());
- }
- catch (IOException ex)
- {
- // Ignore.
- }
- finally
- {
- IOUtil.close(out);
- }
- }
-
private static Set<IInstallableUnit> getInstalledUnits(Agent agent)
{
Set<IInstallableUnit> result = new HashSet<IInstallableUnit>();
diff --git a/plugins/org.eclipse.oomph.setup.ui/src/org/eclipse/oomph/setup/ui/SetupUIPlugin.java b/plugins/org.eclipse.oomph.setup.ui/src/org/eclipse/oomph/setup/ui/SetupUIPlugin.java
index 800e33e86..0514449ad 100644
--- a/plugins/org.eclipse.oomph.setup.ui/src/org/eclipse/oomph/setup/ui/SetupUIPlugin.java
+++ b/plugins/org.eclipse.oomph.setup.ui/src/org/eclipse/oomph/setup/ui/SetupUIPlugin.java
@@ -70,6 +70,7 @@ import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.equinox.p2.engine.IProfile;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.PreferenceManager;
import org.eclipse.swt.widgets.Display;
@@ -362,12 +363,30 @@ public final class SetupUIPlugin extends OomphUIPlugin
File bundlePoolLocation = bundlePool.getLocation();
if (bundlePoolLocation != null)
{
- File eclipseExtensionFeaturesFolder = new File(bundlePoolLocation, ".eclipseextension/features");
- eclipseExtensionFeaturesFolder.mkdirs();
+ String installFolderLocation = currentProfile.getProperty(IProfile.PROP_INSTALL_FOLDER);
+ if (installFolderLocation != null && !bundlePoolLocation.equals(new File(installFolderLocation)))
+ {
+ File eclipseExtensionFeaturesFolder = new File(bundlePoolLocation, ".eclipseextension/features");
+ eclipseExtensionFeaturesFolder.mkdirs();
+ }
}
}
}
}
+
+ Profile currentProfile = P2Util.getAgentManager().getCurrentAgent().getCurrentProfile();
+ String installFolderLocation = currentProfile.getProperty(IProfile.PROP_INSTALL_FOLDER);
+ if (installFolderLocation != null)
+ {
+ BundlePool bundlePool = currentProfile.getBundlePool();
+ File bundlePoolLocation = bundlePool.getLocation();
+
+ if (!bundlePoolLocation.equals(new File(installFolderLocation)))
+ {
+ File eclipseExtensionFeaturesFolder = new File(bundlePoolLocation, ".eclipseextension/features");
+ eclipseExtensionFeaturesFolder.mkdirs();
+ }
+ }
}
catch (Throwable throwable)
{
diff --git a/setups/OomphInstaller.setup b/setups/OomphInstaller.setup
index 94665fd3d..939d45a47 100644
--- a/setups/OomphInstaller.setup
+++ b/setups/OomphInstaller.setup
@@ -22,6 +22,18 @@
<value>Eclipse Installer</value>
</detail>
</annotation>
+ <version name="local"
+ label="Local"
+ requiredJavaVersion="1.7">
+ <setupTask
+ xsi:type="setup.p2:P2Task"
+ label="Eclipse Installer">
+ <requirement
+ name="org.eclipse.oomph.setup.installer.product"/>
+ <repository
+ url="${oomph.product.update.url}"/>
+ </setupTask>
+ </version>
<version name="mars"
label="Mars"
requiredJavaVersion="1.7">

Back to the top