diff options
author | Pascal Rapicault (Ericsson) | 2013-04-04 20:24:05 +0000 |
---|---|---|
committer | Pascal Rapicault | 2013-04-05 15:46:26 +0000 |
commit | 63e1a9c2064cb40f8d4eaa214c3db45c5dba0f56 (patch) | |
tree | 9f735b6fde8a5a216ceb7a770352eb6a8e3b20ab | |
parent | 368767b358a6613ad497a924681f1333158ffa0e (diff) | |
download | rt.equinox.p2-63e1a9c2064cb40f8d4eaa214c3db45c5dba0f56.tar.gz rt.equinox.p2-63e1a9c2064cb40f8d4eaa214c3db45c5dba0f56.tar.xz rt.equinox.p2-63e1a9c2064cb40f8d4eaa214c3db45c5dba0f56.zip |
Extract migration code into a new class
3 files changed, 199 insertions, 176 deletions
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/sharedinstall/NeedsMigration.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/sharedinstall/NeedsMigration.java index a70b9dfc9..287e7fb95 100644 --- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/sharedinstall/NeedsMigration.java +++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/sharedinstall/NeedsMigration.java @@ -12,7 +12,7 @@ package org.eclipse.equinox.p2.tests.sharedinstall; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import org.eclipse.equinox.internal.p2.ui.sdk.scheduler.AutomaticUpdateScheduler; +import org.eclipse.equinox.internal.p2.ui.sdk.scheduler.migration.MigrationSupport; import org.eclipse.equinox.p2.engine.IEngine; import org.eclipse.equinox.p2.engine.IProfile; import org.eclipse.equinox.p2.metadata.IInstallableUnit; @@ -40,7 +40,7 @@ public class NeedsMigration extends AbstractProvisioningTest { private IPlanner planner; private IEngine engine; - private AutomaticUpdateScheduler scheduler; + private MigrationSupport scheduler; private Method needsMigrationMethod; @Override @@ -48,7 +48,7 @@ public class NeedsMigration extends AbstractProvisioningTest { IULoader.loadIUs(this); planner = createPlanner(); engine = createEngine(); - scheduler = new AutomaticUpdateScheduler(); + scheduler = new MigrationSupport(); createTestMetdataRepository(new IInstallableUnit[] {sdk1, sdk2, egit1, egit2, cdt1, eppPackage}); needsMigrationMethod = scheduler.getClass().getDeclaredMethod("needsMigration", IProfile.class, IProfile.class); needsMigrationMethod.setAccessible(true); diff --git a/bundles/org.eclipse.equinox.p2.ui.sdk.scheduler/src/org/eclipse/equinox/internal/p2/ui/sdk/scheduler/AutomaticUpdateScheduler.java b/bundles/org.eclipse.equinox.p2.ui.sdk.scheduler/src/org/eclipse/equinox/internal/p2/ui/sdk/scheduler/AutomaticUpdateScheduler.java index 1ffa1e25d..65ae0346d 100644 --- a/bundles/org.eclipse.equinox.p2.ui.sdk.scheduler/src/org/eclipse/equinox/internal/p2/ui/sdk/scheduler/AutomaticUpdateScheduler.java +++ b/bundles/org.eclipse.equinox.p2.ui.sdk.scheduler/src/org/eclipse/equinox/internal/p2/ui/sdk/scheduler/AutomaticUpdateScheduler.java @@ -14,33 +14,19 @@ package org.eclipse.equinox.internal.p2.ui.sdk.scheduler; import com.ibm.icu.util.Calendar; import com.ibm.icu.util.ULocale; -import java.io.File; -import java.net.URI; -import java.util.Iterator; -import java.util.Set; import org.eclipse.core.runtime.*; import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper; -import org.eclipse.equinox.internal.p2.engine.EngineActivator; import org.eclipse.equinox.internal.p2.garbagecollector.GarbageCollector; -import org.eclipse.equinox.internal.p2.metadata.query.UpdateQuery; -import org.eclipse.equinox.internal.p2.ui.sdk.scheduler.migration.ImportFromInstallationWizard_c; +import org.eclipse.equinox.internal.p2.ui.sdk.scheduler.migration.MigrationSupport; import org.eclipse.equinox.internal.provisional.p2.updatechecker.*; import org.eclipse.equinox.p2.core.IProvisioningAgent; import org.eclipse.equinox.p2.engine.IProfile; import org.eclipse.equinox.p2.engine.IProfileRegistry; import org.eclipse.equinox.p2.engine.query.IUProfilePropertyQuery; -import org.eclipse.equinox.p2.engine.query.UserVisibleRootQuery; import org.eclipse.equinox.p2.metadata.IInstallableUnit; import org.eclipse.equinox.p2.query.IQuery; -import org.eclipse.equinox.p2.query.QueryUtil; -import org.eclipse.equinox.p2.repository.IRepositoryManager; -import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager; import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.jface.wizard.WizardDialog; -import org.eclipse.osgi.service.datalocation.Location; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.*; +import org.eclipse.ui.IStartup; import org.eclipse.ui.statushandlers.StatusManager; /** @@ -49,9 +35,6 @@ import org.eclipse.ui.statushandlers.StatusManager; * @since 3.5 */ public class AutomaticUpdateScheduler implements IStartup { - - private static final String ECLIPSE_P2_SKIP_MIGRATION_WIZARD = "eclipse.p2.skipMigrationWizard"; //$NON-NLS-1$ - private static final String ECLIPSE_P2_SKIP_MOVED_INSTALL_DETECTION = "eclipse.p2.skipMovedInstallDetection"; //$NON-NLS-1$ public static final String MIGRATION_DIALOG_SHOWN = "migrationDialogShown"; //$NON-NLS-1$ // values are to be picked up from the arrays DAYS and HOURS @@ -103,166 +86,13 @@ public class AutomaticUpdateScheduler implements IStartup { IProvisioningAgent agent = (IProvisioningAgent) ServiceHelper.getService(AutomaticUpdatePlugin.getContext(), IProvisioningAgent.SERVICE_NAME); IProfileRegistry registry = (IProfileRegistry) agent.getService(IProfileRegistry.SERVICE_NAME); IProfile currentProfile = registry.getProfile(profileId); - if (currentProfile != null && performMigration(agent, registry, currentProfile)) + if (currentProfile != null && new MigrationSupport().performMigration(agent, registry, currentProfile)) return; garbageCollect(); scheduleUpdate(); } - //The return value indicates if the migration dialog has been shown or not. It does not indicate whether the migration has completed. - private boolean performMigration(IProvisioningAgent agent, IProfileRegistry registry, IProfile currentProfile) { - boolean skipWizard = Boolean.TRUE.toString().equalsIgnoreCase(System.getProperty(ECLIPSE_P2_SKIP_MIGRATION_WIZARD)); - if (skipWizard) - return false; - - IProfile previousProfile = null; - URI[] reposToMigrate = null; - if (!skipFirstTimeMigration() && !configurationSpecifiedManually() && isFirstTimeRunningThisSharedInstance(agent, registry, currentProfile)) { - File searchRoot = getSearchLocation(); - if (searchRoot == null) - return false; - - IProvisioningAgent otherConfigAgent = new PreviousConfigurationFinder(getConfigurationLocation().getParentFile()).findPreviousInstalls(searchRoot, getInstallFolder()); - if (otherConfigAgent == null) { - return false; - } - previousProfile = ((IProfileRegistry) otherConfigAgent.getService(IProfileRegistry.SERVICE_NAME)).getProfile(IProfileRegistry.SELF); - if (previousProfile == null) - return false; - - reposToMigrate = ((IMetadataRepositoryManager) otherConfigAgent.getService(IMetadataRepositoryManager.SERVICE_NAME)).getKnownRepositories(IRepositoryManager.REPOSITORIES_NON_SYSTEM); - } - - if (previousProfile == null && baseChangedSinceLastPresentationOfWizard(agent, registry, currentProfile)) - previousProfile = findMostRecentReset(registry, currentProfile); - - if (previousProfile == null) - return false; - - if (needsMigration(previousProfile, currentProfile)) { - openMigrationWizard(previousProfile, reposToMigrate); - } else { - //There is nothing to migrate, so we mark the migration complete - AutomaticUpdatePlugin.getDefault().rememberMigrationCompleted(currentProfile.getProfileId()); - } - return true; - } - - private File getInstallFolder() { - Location configurationLocation = (Location) ServiceHelper.getService(EngineActivator.getContext(), Location.class.getName(), Location.INSTALL_FILTER); - return new File(configurationLocation.getURL().getPath()); - - } - - //The search location is two level up from the configuration location. - private File getSearchLocation() { - File parent = getConfigurationLocation().getParentFile(); - if (parent == null) - return null; - return parent.getParentFile(); - } - - private File getConfigurationLocation() { - Location configurationLocation = (Location) ServiceHelper.getService(EngineActivator.getContext(), Location.class.getName(), Location.CONFIGURATION_FILTER); - File configurationFolder = new File(configurationLocation.getURL().getPath()); - return configurationFolder; - } - - //Check if the user has explicitly specified -configuration on the command line - private boolean configurationSpecifiedManually() { - String commandLine = System.getProperty("eclipse.commands"); //$NON-NLS-1$ - if (commandLine == null) - return false; - return commandLine.contains("-configuration\n"); //$NON-NLS-1$ - } - - private boolean skipFirstTimeMigration() { - return Boolean.TRUE.toString().equalsIgnoreCase(System.getProperty(ECLIPSE_P2_SKIP_MOVED_INSTALL_DETECTION)); - } - - private boolean isFirstTimeRunningThisSharedInstance(IProvisioningAgent agent, IProfileRegistry registry, IProfile currentProfile) { - long[] history = registry.listProfileTimestamps(currentProfile.getProfileId()); - boolean isInitial = !IProfile.STATE_SHARED_INSTALL_VALUE_INITIAL.equals(registry.getProfileStateProperties(currentProfile.getProfileId(), history[0]).get(IProfile.STATE_PROP_SHARED_INSTALL)); - if (isInitial) { - if (AutomaticUpdatePlugin.getDefault().getLastMigration() >= history[0]) - return false; - return true; - } - return false; - } - - /** - * @param previousProfile is the profile used previous to the current one - * @param currentProfile is the current profile used by eclipse. - * @return true if set difference between previousProfile units and currentProfile units not empty, otherwise false - */ - private boolean needsMigration(IProfile previousProfile, IProfile currentProfile) { - //First, try the case of inclusion - Set<IInstallableUnit> previousProfileUnits = previousProfile.query(new UserVisibleRootQuery(), null).toSet(); - Set<IInstallableUnit> currentProfileUnits = currentProfile.available(new UserVisibleRootQuery(), null).toSet(); - previousProfileUnits.removeAll(currentProfileUnits); - - //For the IUs left in the previous profile, look for those that could be in the base but not as roots - Iterator<IInstallableUnit> previousProfileIterator = previousProfileUnits.iterator(); - while (previousProfileIterator.hasNext()) { - if (!currentProfile.available(QueryUtil.createIUQuery(previousProfileIterator.next()), null).isEmpty()) - previousProfileIterator.remove(); - } - - //For the IUs left in the previous profile, look for those that could be available in the root but as higher versions (they could be root or not) - previousProfileIterator = previousProfileUnits.iterator(); - while (previousProfileIterator.hasNext()) { - if (!currentProfile.available(new UpdateQuery(previousProfileIterator.next()), null).isEmpty()) - previousProfileIterator.remove(); - } - - return !previousProfileUnits.isEmpty(); - } - - private void openMigrationWizard(final IProfile inputProfile, final URI[] reposToMigrate) { - Display d = Display.getDefault(); - d.asyncExec(new Runnable() { - public void run() { - WizardDialog migrateWizard = new WizardDialog(getWorkbenchWindowShell(), new ImportFromInstallationWizard_c(inputProfile, reposToMigrate)); - migrateWizard.create(); - migrateWizard.open(); - } - }); - } - - Shell getWorkbenchWindowShell() { - IWorkbenchWindow activeWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); - return activeWindow != null ? activeWindow.getShell() : null; - - } - - private boolean baseChangedSinceLastPresentationOfWizard(IProvisioningAgent agent, IProfileRegistry registry, IProfile profile) { - long lastProfileMigrated = AutomaticUpdatePlugin.getDefault().getLastMigration(); - long lastResetTimestamp = findMostRecentResetTimestamp(registry, profile); - return lastProfileMigrated <= lastResetTimestamp; - } - - //The timestamp from which we migrated or -1 - private long findMostRecentResetTimestamp(IProfileRegistry registry, IProfile profile) { - long[] history = registry.listProfileTimestamps(profile.getProfileId()); - int index = history.length - 1; - boolean found = false; - while (!(found = IProfile.STATE_SHARED_INSTALL_VALUE_BEFOREFLUSH.equals(registry.getProfileStateProperties(profile.getProfileId(), history[index]).get(IProfile.STATE_PROP_SHARED_INSTALL))) && index > 0) { - index--; - } - if (!found) - return -1; - return history[index]; - } - - private IProfile findMostRecentReset(IProfileRegistry registry, IProfile profile) { - long ts = findMostRecentResetTimestamp(registry, profile); - if (ts == -1) - return null; - return registry.getProfile(profile.getProfileId(), ts); - } - /** * Invokes the garbage collector to discard unused plugins, if specified by a * corresponding preference. diff --git a/bundles/org.eclipse.equinox.p2.ui.sdk.scheduler/src/org/eclipse/equinox/internal/p2/ui/sdk/scheduler/migration/MigrationSupport.java b/bundles/org.eclipse.equinox.p2.ui.sdk.scheduler/src/org/eclipse/equinox/internal/p2/ui/sdk/scheduler/migration/MigrationSupport.java new file mode 100644 index 000000000..ecce7afef --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.ui.sdk.scheduler/src/org/eclipse/equinox/internal/p2/ui/sdk/scheduler/migration/MigrationSupport.java @@ -0,0 +1,193 @@ +/******************************************************************************* + * Copyright (c) 2013 Ericsson AB 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: + * Ericsson AB - initial API and implementation + ******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.sdk.scheduler.migration; + +import java.io.File; +import java.net.URI; +import java.util.Iterator; +import java.util.Set; +import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper; +import org.eclipse.equinox.internal.p2.engine.EngineActivator; +import org.eclipse.equinox.internal.p2.metadata.query.UpdateQuery; +import org.eclipse.equinox.internal.p2.ui.sdk.scheduler.AutomaticUpdatePlugin; +import org.eclipse.equinox.internal.p2.ui.sdk.scheduler.PreviousConfigurationFinder; +import org.eclipse.equinox.p2.core.IProvisioningAgent; +import org.eclipse.equinox.p2.engine.IProfile; +import org.eclipse.equinox.p2.engine.IProfileRegistry; +import org.eclipse.equinox.p2.engine.query.UserVisibleRootQuery; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.query.QueryUtil; +import org.eclipse.equinox.p2.repository.IRepositoryManager; +import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.osgi.service.datalocation.Location; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; + +public class MigrationSupport { + private static final String ECLIPSE_P2_SKIP_MIGRATION_WIZARD = "eclipse.p2.skipMigrationWizard"; //$NON-NLS-1$ + private static final String ECLIPSE_P2_SKIP_MOVED_INSTALL_DETECTION = "eclipse.p2.skipMovedInstallDetection"; //$NON-NLS-1$ + + //The return value indicates if the migration dialog has been shown or not. It does not indicate whether the migration has completed. + public boolean performMigration(IProvisioningAgent agent, IProfileRegistry registry, IProfile currentProfile) { + boolean skipWizard = Boolean.TRUE.toString().equalsIgnoreCase(System.getProperty(ECLIPSE_P2_SKIP_MIGRATION_WIZARD)); + if (skipWizard) + return false; + + IProfile previousProfile = null; + URI[] reposToMigrate = null; + if (!skipFirstTimeMigration() && !configurationSpecifiedManually() && isFirstTimeRunningThisSharedInstance(agent, registry, currentProfile)) { + File searchRoot = getSearchLocation(); + if (searchRoot == null) + return false; + + IProvisioningAgent otherConfigAgent = new PreviousConfigurationFinder(getConfigurationLocation().getParentFile()).findPreviousInstalls(searchRoot, getInstallFolder()); + if (otherConfigAgent == null) { + return false; + } + previousProfile = ((IProfileRegistry) otherConfigAgent.getService(IProfileRegistry.SERVICE_NAME)).getProfile(IProfileRegistry.SELF); + if (previousProfile == null) + return false; + + reposToMigrate = ((IMetadataRepositoryManager) otherConfigAgent.getService(IMetadataRepositoryManager.SERVICE_NAME)).getKnownRepositories(IRepositoryManager.REPOSITORIES_NON_SYSTEM); + } + + if (previousProfile == null && baseChangedSinceLastPresentationOfWizard(agent, registry, currentProfile)) + previousProfile = findMostRecentReset(registry, currentProfile); + + if (previousProfile == null) + return false; + + if (needsMigration(previousProfile, currentProfile)) { + openMigrationWizard(previousProfile, reposToMigrate); + } else { + //There is nothing to migrate, so we mark the migration complete + AutomaticUpdatePlugin.getDefault().rememberMigrationCompleted(currentProfile.getProfileId()); + } + return true; + } + + private File getInstallFolder() { + Location configurationLocation = (Location) ServiceHelper.getService(EngineActivator.getContext(), Location.class.getName(), Location.INSTALL_FILTER); + return new File(configurationLocation.getURL().getPath()); + + } + + //The search location is two level up from the configuration location. + private File getSearchLocation() { + File parent = getConfigurationLocation().getParentFile(); + if (parent == null) + return null; + return parent.getParentFile(); + } + + private File getConfigurationLocation() { + Location configurationLocation = (Location) ServiceHelper.getService(EngineActivator.getContext(), Location.class.getName(), Location.CONFIGURATION_FILTER); + File configurationFolder = new File(configurationLocation.getURL().getPath()); + return configurationFolder; + } + + //Check if the user has explicitly specified -configuration on the command line + private boolean configurationSpecifiedManually() { + String commandLine = System.getProperty("eclipse.commands"); //$NON-NLS-1$ + if (commandLine == null) + return false; + return commandLine.contains("-configuration\n"); //$NON-NLS-1$ + } + + private boolean skipFirstTimeMigration() { + return Boolean.TRUE.toString().equalsIgnoreCase(System.getProperty(ECLIPSE_P2_SKIP_MOVED_INSTALL_DETECTION)); + } + + private boolean isFirstTimeRunningThisSharedInstance(IProvisioningAgent agent, IProfileRegistry registry, IProfile currentProfile) { + long[] history = registry.listProfileTimestamps(currentProfile.getProfileId()); + boolean isInitial = !IProfile.STATE_SHARED_INSTALL_VALUE_INITIAL.equals(registry.getProfileStateProperties(currentProfile.getProfileId(), history[0]).get(IProfile.STATE_PROP_SHARED_INSTALL)); + if (isInitial) { + if (AutomaticUpdatePlugin.getDefault().getLastMigration() >= history[0]) + return false; + return true; + } + return false; + } + + /** + * @param previousProfile is the profile used previous to the current one + * @param currentProfile is the current profile used by eclipse. + * @return true if set difference between previousProfile units and currentProfile units not empty, otherwise false + */ + private boolean needsMigration(IProfile previousProfile, IProfile currentProfile) { + //First, try the case of inclusion + Set<IInstallableUnit> previousProfileUnits = previousProfile.query(new UserVisibleRootQuery(), null).toSet(); + Set<IInstallableUnit> currentProfileUnits = currentProfile.available(new UserVisibleRootQuery(), null).toSet(); + previousProfileUnits.removeAll(currentProfileUnits); + + //For the IUs left in the previous profile, look for those that could be in the base but not as roots + Iterator<IInstallableUnit> previousProfileIterator = previousProfileUnits.iterator(); + while (previousProfileIterator.hasNext()) { + if (!currentProfile.available(QueryUtil.createIUQuery(previousProfileIterator.next()), null).isEmpty()) + previousProfileIterator.remove(); + } + + //For the IUs left in the previous profile, look for those that could be available in the root but as higher versions (they could be root or not) + previousProfileIterator = previousProfileUnits.iterator(); + while (previousProfileIterator.hasNext()) { + if (!currentProfile.available(new UpdateQuery(previousProfileIterator.next()), null).isEmpty()) + previousProfileIterator.remove(); + } + + return !previousProfileUnits.isEmpty(); + } + + private void openMigrationWizard(final IProfile inputProfile, final URI[] reposToMigrate) { + Display d = Display.getDefault(); + d.asyncExec(new Runnable() { + public void run() { + WizardDialog migrateWizard = new WizardDialog(getWorkbenchWindowShell(), new ImportFromInstallationWizard_c(inputProfile, reposToMigrate)); + migrateWizard.create(); + migrateWizard.open(); + } + }); + } + + private boolean baseChangedSinceLastPresentationOfWizard(IProvisioningAgent agent, IProfileRegistry registry, IProfile profile) { + long lastProfileMigrated = AutomaticUpdatePlugin.getDefault().getLastMigration(); + long lastResetTimestamp = findMostRecentResetTimestamp(registry, profile); + return lastProfileMigrated <= lastResetTimestamp; + } + + //The timestamp from which we migrated or -1 + private long findMostRecentResetTimestamp(IProfileRegistry registry, IProfile profile) { + long[] history = registry.listProfileTimestamps(profile.getProfileId()); + int index = history.length - 1; + boolean found = false; + while (!(found = IProfile.STATE_SHARED_INSTALL_VALUE_BEFOREFLUSH.equals(registry.getProfileStateProperties(profile.getProfileId(), history[index]).get(IProfile.STATE_PROP_SHARED_INSTALL))) && index > 0) { + index--; + } + if (!found) + return -1; + return history[index]; + } + + private IProfile findMostRecentReset(IProfileRegistry registry, IProfile profile) { + long ts = findMostRecentResetTimestamp(registry, profile); + if (ts == -1) + return null; + return registry.getProfile(profile.getProfileId(), ts); + } + + Shell getWorkbenchWindowShell() { + IWorkbenchWindow activeWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + return activeWindow != null ? activeWindow.getShell() : null; + + } + +} |