/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.update.internal.core; import org.eclipse.update.internal.model.SiteLocalModel; import org.eclipse.core.runtime.ListenerList; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.osgi.util.NLS; import org.eclipse.update.configuration.IActivity; import org.eclipse.update.configuration.IConfiguredSite; import org.eclipse.update.configuration.IInstallConfiguration; import org.eclipse.update.configuration.IInstallConfigurationChangedListener; import org.eclipse.update.configuration.IProblemHandler; import org.eclipse.update.configurator.ConfiguratorUtils; import org.eclipse.update.configurator.IPlatformConfiguration; import org.eclipse.update.core.FeatureContentProvider; import org.eclipse.update.core.IFeature; import org.eclipse.update.core.IFeatureReference; import org.eclipse.update.core.IPluginEntry; import org.eclipse.update.core.ISite; import org.eclipse.update.core.ISiteContentProvider; import org.eclipse.update.core.ISiteFeatureReference; import org.eclipse.update.core.Site; import org.eclipse.update.core.SiteManager; import org.eclipse.update.core.Utilities; import org.eclipse.update.core.VersionedIdentifier; import org.eclipse.update.core.model.SiteModel; import org.eclipse.update.internal.configurator.ConfigurationActivator; import org.eclipse.update.internal.configurator.FeatureEntry; import org.eclipse.update.internal.configurator.PlatformConfiguration; import org.eclipse.update.internal.configurator.PluginEntry; import org.eclipse.update.internal.configurator.SiteEntry; import org.eclipse.update.internal.model.ConfigurationActivityModel; import org.eclipse.update.internal.model.ConfiguredSiteModel; import org.eclipse.update.internal.model.InstallConfigurationModel; import org.osgi.framework.Bundle; /** * Manages ConfiguredSites * */ public class InstallConfiguration extends InstallConfigurationModel implements IInstallConfiguration { private static boolean isWindows = System.getProperty("os.name").startsWith("Win"); //$NON-NLS-1$ //$NON-NLS-2$ private ListenerList listeners = new ListenerList(ListenerList.IDENTITY); /* * default constructor. */ public InstallConfiguration() { } /* * Copy constructor * @since 3.0 */ public InstallConfiguration(IInstallConfiguration config) throws MalformedURLException, CoreException { this(config, null, null); } /* * copy constructor */ public InstallConfiguration(IInstallConfiguration config, URL newLocation, String label) throws CoreException, MalformedURLException { // set current date and timeline as caller can call setDate if the // date on the URL string has to be the same Date now = new Date(); setCreationDate(now); setCurrent(false); if (newLocation == null) { String newFileName = UpdateManagerUtils.getLocalRandomIdentifier(SiteLocalModel.CONFIG_FILE, now); newLocation = UpdateManagerUtils.getURL(((LocalSite)SiteManager.getLocalSite()).getLocationURL(), newFileName, null); } setLocationURLString(newLocation.toExternalForm()); if (label == null) label = Utilities.format(now); setLabel(label); // do not copy list of listeners nor activities // make a copy of the siteConfiguration object if (config != null) { IConfiguredSite[] csites = config.getConfiguredSites(); if (csites != null) { for (int i = 0; i < csites.length; i++) { ConfiguredSite configSite = new ConfiguredSite(csites[i]); addConfigurationSiteModel(configSite); } } } resolve(newLocation, null); // no need to parse file, all data are initialized initialized = true; } /* * Returns the list of configured sites or an empty array */ public IConfiguredSite[] getConfiguredSites() { ConfiguredSiteModel[] result = getConfigurationSitesModel(); if (result.length == 0) return new IConfiguredSite[0]; else return (IConfiguredSite[]) result; } /* * Returns the default site policy */ private int getDefaultPolicy() { return PlatformConfiguration.getDefaultPolicy(); } /** * Creates a Configuration Site and a new Site * The policy is from <code> org.eclipse.core.boot.IPlatformConfiguration</code> */ public IConfiguredSite createConfiguredSite(File file) throws CoreException { if (!file.getName().equals("eclipse")) { //$NON-NLS-1$ file = new File(file, "eclipse"); //$NON-NLS-1$ file.mkdirs(); } if (isDuplicateSite(file)) throw Utilities.newCoreException(NLS.bind(Messages.InstallConfiguration_location_exists, (new String[] { file.getPath() })),null); ISite site = InternalSiteManager.createSite(file); //create a config site around the site // even if the site == null BaseSiteLocalFactory factory = new BaseSiteLocalFactory(); ConfiguredSite configSite = (ConfiguredSite) factory.createConfigurationSiteModel((SiteModel) site, getDefaultPolicy()); if (configSite.isNativelyLinked()) { throw Utilities.newCoreException(Messages.InstallConfiguration_AlreadyNativelyLinked, null); } if (configSite.isProductSite()) { throw Utilities.newCoreException(Messages.InstallConfiguration_AlreadyProductSite, null); } if (site != null) { configSite.setPlatformURLString(site.getURL().toExternalForm()); // obtain the list of plugins IPlatformConfiguration runtimeConfiguration = ConfiguratorUtils.getCurrentPlatformConfiguration(); ConfigurationPolicy configurationPolicy = configSite.getConfigurationPolicy(); String[] pluginPath = new String[0]; if (configurationPolicy.getPolicy() == IPlatformConfiguration.ISitePolicy.USER_INCLUDE) pluginPath = configurationPolicy.getPluginPath(site); // create new Site in configuration IPlatformConfiguration.ISitePolicy sitePolicy = runtimeConfiguration.createSitePolicy(configurationPolicy.getPolicy(), pluginPath); // change runtime IPlatformConfiguration.ISiteEntry siteEntry = runtimeConfiguration.createSiteEntry(site.getURL(), sitePolicy); runtimeConfiguration.configureSite(siteEntry); // if the privatre marker doesn't already exist create it configSite.createPrivateSiteMarker(); ((SiteModel)site).setConfiguredSiteModel(configSite); } // configure all features as enable configure(configSite); return configSite; } /** * Creates a Configuration Site and a new Site as a private link site * The policy is from <code> org.eclipse.core.boot.IPlatformConfiguration</code> */ public IConfiguredSite createLinkedConfiguredSite(File file) throws CoreException { return createConfiguredSite(file); // if (isDuplicateSite(file)) // throw Utilities.newCoreException(UpdateUtils.getFormattedMessage("InstallConfiguration.location.exists", file.getPath()),null); // // ISite site = InternalSiteManager.createSite(file); // // //create a config site around the site // // even if the site == null // BaseSiteLocalFactory factory = new BaseSiteLocalFactory(); // ConfiguredSite configSite = (ConfiguredSite) factory.createConfigurationSiteModel((SiteModel) site, getDefaultPolicy()); // // if (!configSite.isExtensionSite()) { // String msg = Policy.bind("InstallConfiguration.NotAnExtensionSite"); // throw Utilities.newCoreException(msg, null); // } // // if (configSite.isNativelyLinked()) { // throw Utilities.newCoreException("InstallConfiguration.AlreadyNativelyLinked", null); // } // // if (site != null) { // configSite.setPlatformURLString(site.getURL().toExternalForm()); // // // obtain the list of plugins // IPlatformConfiguration runtimeConfiguration = ConfiguratorUtils.getCurrentPlatformConfiguration(); // ConfigurationPolicy configurationPolicy = configSite.getConfigurationPolicy(); // String[] pluginPath = new String[0]; // if (configurationPolicy.getPolicy() == IPlatformConfiguration.ISitePolicy.USER_INCLUDE) // pluginPath = configurationPolicy.getPluginPath(site); // // // create new Site in configuration // IPlatformConfiguration.ISitePolicy sitePolicy = runtimeConfiguration.createSitePolicy(configurationPolicy.getPolicy(), pluginPath); // // // change runtime // IPlatformConfiguration.ISiteEntry siteEntry = runtimeConfiguration.createSiteEntry(site.getURL(), sitePolicy); // runtimeConfiguration.configureSite(siteEntry); // // } // // // configure all features as enable // configure(configSite); // // return configSite; } /* *Configure all features as Enable Check we only enable highest version */ private void configure(ConfiguredSite linkedSite) throws CoreException { ISite site = linkedSite.getSite(); ISiteFeatureReference[] newFeaturesRef = site.getFeatureReferences(); for (int i = 0; i < newFeaturesRef.length; i++) { // TRACE if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_RECONCILER) { String reconciliationType = "enable (optimistic)"; //$NON-NLS-1$ UpdateCore.debug("New Linked Site:New Feature: " + newFeaturesRef[i].getURL() + " as " + reconciliationType); //$NON-NLS-1$ //$NON-NLS-2$ } ConfigurationPolicy policy = linkedSite.getConfigurationPolicy(); policy.configure(newFeaturesRef[i], true, false); } SiteReconciler.checkConfiguredFeatures(linkedSite); } /* * */ public void addConfiguredSite(IConfiguredSite site) { if (!isCurrent() && isReadOnly()) return; ConfigurationActivity activity = new ConfigurationActivity(IActivity.ACTION_SITE_INSTALL); activity.setLabel(site.getSite().getURL().toExternalForm()); activity.setDate(new Date()); ConfiguredSiteModel configSiteModel = (ConfiguredSiteModel) site; addConfigurationSiteModel(configSiteModel); configSiteModel.setInstallConfigurationModel(this); // notify listeners Object[] configurationListeners = listeners.getListeners(); for (int i = 0; i < configurationListeners.length; i++) { IInstallConfigurationChangedListener listener = ((IInstallConfigurationChangedListener) configurationListeners[i]); listener.installSiteAdded(site); } // everything done ok activity.setStatus(IActivity.STATUS_OK); this.addActivity(activity); } /** * Method addActivity. * @param activity */ public void addActivity(IActivity activity) { addActivityModel((ConfigurationActivityModel)activity); } /* * */ public void removeConfiguredSite(IConfiguredSite site) { if (!isCurrent() && isReadOnly()) return; if (removeConfigurationSiteModel((ConfiguredSiteModel) site)) { // notify listeners Object[] configurationListeners = listeners.getListeners(); for (int i = 0; i < configurationListeners.length; i++) { IInstallConfigurationChangedListener listener = ((IInstallConfigurationChangedListener) configurationListeners[i]); listener.installSiteRemoved(site); } //activity ConfigurationActivity activity = new ConfigurationActivity(IActivity.ACTION_SITE_REMOVE); activity.setLabel(site.getSite().getURL().toExternalForm()); activity.setDate(new Date()); activity.setStatus(IActivity.STATUS_OK); this.addActivity(activity); } } /* * @see IInstallConfiguration#addInstallConfigurationChangedListener(IInstallConfigurationChangedListener) */ public void addInstallConfigurationChangedListener(IInstallConfigurationChangedListener listener) { listeners.add(listener); } /* * @see IInstallConfiguration#removeInstallConfigurationChangedListener(IInstallConfigurationChangedListener) */ public void removeInstallConfigurationChangedListener(IInstallConfigurationChangedListener listener) { listeners.remove(listener); } /* * Deletes the configuration from its URL/location */ public void remove() { // save the configuration if ("file".equalsIgnoreCase(getURL().getProtocol())) { //$NON-NLS-1$ // the location points to a file File file = new File(getURL().getFile()); UpdateManagerUtils.removeFromFileSystem(file); } } /** * Saves the configuration into its URL/location * and changes the platform configuration. * The runtime site entries from platform.xml are updated as required * (cannot recreate these because must preserve other runtime state) [18520] * @return true if restart is needed */ public boolean save() throws CoreException { // Write info into platform for the next runtime IPlatformConfiguration runtimeConfiguration = ConfiguratorUtils.getCurrentPlatformConfiguration(); ConfiguredSiteModel[] configurationSites = getConfigurationSitesModel(); // clean configured Entries from platform runtime IPlatformConfiguration.IFeatureEntry[] configuredFeatureEntries = runtimeConfiguration.getConfiguredFeatureEntries(); for (int i = 0; i < configuredFeatureEntries.length; i++) { runtimeConfiguration.unconfigureFeatureEntry(configuredFeatureEntries[i]); } // [19958] remember sites currently configured by runtime (use // temp configuration object rather than a straight list to ensure // correct lookup) IPlatformConfiguration tempConfig = null; try { tempConfig = ConfiguratorUtils.getPlatformConfiguration(null); IPlatformConfiguration.ISiteEntry[] tmpSites = runtimeConfiguration.getConfiguredSites(); for (int i = 0; i < tmpSites.length; i++) { tempConfig.configureSite(tmpSites[i]); } } catch (IOException e) { // assume no currently configured sites } //check sites checkSites(configurationSites, runtimeConfiguration); // Save the plugin path, primary feature and platform for (int i = 0; i < configurationSites.length; i++) { ConfiguredSite cSite = ((ConfiguredSite) configurationSites[i]); ConfigurationPolicy configurationPolicy = cSite.getConfigurationPolicy(); savePluginPath(cSite, runtimeConfiguration, tempConfig); // IF primary feature URL or platform feature URL that we need to pass to runtime config // is part of platform:base:, write it as platform:base: URL IFeatureReference[] configuredFeaturesRef = configurationPolicy.getConfiguredFeatures(); for (int j = 0; j < configuredFeaturesRef.length; j++) { IFeature feature = null; try { feature = configuredFeaturesRef[j].getFeature(null); } catch (CoreException e) { UpdateCore.warn(null, e); } saveFeatureEntry(cSite, feature, runtimeConfiguration); } } // [19958] remove any extra site entries from runtime configuration // (site entries that no longer exist in this configuration) if (tempConfig != null) { IPlatformConfiguration.ISiteEntry[] tmpSites = tempConfig.getConfiguredSites(); for (int i = 0; i < tmpSites.length; i++) { runtimeConfiguration.unconfigureSite(tmpSites[i]); } } try { runtimeConfiguration.save(); // log configuration and activities this.date = new Date(runtimeConfiguration.getChangeStamp()); if ("file".equalsIgnoreCase(getURL().getProtocol())) //$NON-NLS-1$ UpdateCore.log(this); resetActivities(); return isRestartNeeded(runtimeConfiguration); } catch (IOException e) { CoreException exc = Utilities.newCoreException(NLS.bind(Messages.InstallConfiguration_UnableToSavePlatformConfiguration, (new String[] { runtimeConfiguration.getConfigurationLocation().toExternalForm() })), e); UpdateCore.warn("",exc); //$NON-NLS-1$ } return true; } /* * Write the plugin path for each site * Do not check if the site already existed before [16696]. * Reuse any runtime site objects in platform.cfg (to preserve state) [18520]. */ private void savePluginPath(ConfiguredSite cSite, IPlatformConfiguration runtimeConfiguration, IPlatformConfiguration tempConfig) // [19958] throws CoreException { ConfigurationPolicy configurationPolicy = cSite.getConfigurationPolicy(); // create a ISitePolicy (policy, pluginPath) // for the site String[] pluginPath = configurationPolicy.getPluginPath(cSite.getSite()); IPlatformConfiguration.ISitePolicy sitePolicy = runtimeConfiguration.createSitePolicy(configurationPolicy.getPolicy(), pluginPath); // get the URL of the site that matches the one platform.cfg gave us URL urlToCheck = null; try { urlToCheck = new URL(cSite.getPlatformURLString()); } catch (MalformedURLException e) { throw Utilities.newCoreException(NLS.bind(Messages.InstallConfiguration_UnableToCreateURL, (new String[] { cSite.getPlatformURLString() })), e); } catch (ClassCastException e) { throw Utilities.newCoreException(Messages.InstallConfiguration_UnableToCast, e); } // update runtime configuration [18520] // Note: we must not blindly replace the site entries because they // contain additional runtime state that needs to be preserved. IPlatformConfiguration.ISiteEntry siteEntry = runtimeConfiguration.findConfiguredSite(urlToCheck); if (siteEntry == null) siteEntry = runtimeConfiguration.createSiteEntry(urlToCheck, sitePolicy); else { siteEntry.setSitePolicy(sitePolicy); ((SiteEntry)siteEntry).refreshPlugins(); if (tempConfig != null) // [19958] remove reused entries from list tempConfig.unconfigureSite(siteEntry); } ((SiteEntry)siteEntry).setEnabled(cSite.isEnabled()); runtimeConfiguration.configureSite(siteEntry, true /*replace if exists*/); } /* * Save the Feature entry * The feature can be a primary feature and/or a platform feature */ private void saveFeatureEntry(ConfiguredSite cSite, IFeature feature, IPlatformConfiguration runtimeConfiguration) throws CoreException { if (feature == null) return; // get the URL of the plugin that corresponds to the feature (pluginid = featureid) String id = feature.getVersionedIdentifier().getIdentifier(); IPluginEntry[] entries = feature.getPluginEntries(); URL url = null; IPluginEntry featurePlugin = null; for (int k = 0; k < entries.length; k++) { if (id.equalsIgnoreCase(entries[k].getVersionedIdentifier().getIdentifier())) { url = getRuntimeConfigurationURL(entries[k], cSite); featurePlugin = entries[k]; break; } } String pluginVersion = null; if (featurePlugin != null) pluginVersion = featurePlugin.getVersionedIdentifier().getVersion().toString(); // Find the site SiteEntry siteEntry = null; try { URL featureUrl = new URL(cSite.getPlatformURLString()); siteEntry = (SiteEntry)runtimeConfiguration.findConfiguredSite(featureUrl); } catch (MalformedURLException e) { throw Utilities.newCoreException(NLS.bind(Messages.InstallConfiguration_UnableToCreateURL, (new String[] { cSite.getPlatformURLString() })), e); } catch (ClassCastException e) { throw Utilities.newCoreException(Messages.InstallConfiguration_UnableToCast, e); } // if the URL doesn't exist throw a CoreException if (siteEntry == null) { throw new CoreException( new Status(IStatus.ERROR, UpdateCore.getPlugin().getBundle().getSymbolicName(), NLS.bind(Messages.InstallConfiguration_unableToFindSite, (new String[] { cSite.getSite().getURL().toExternalForm(), runtimeConfiguration.getConfigurationLocation().toExternalForm() })))); } // write the primary features if (feature.isPrimary()) { // get any fragments for the feature plugin ArrayList list = new ArrayList(); if (url != null) list.add(url); if (featurePlugin != null) { URL[] fragments = getRuntimeFragmentURLs(featurePlugin); list.addAll(Arrays.asList(fragments)); } URL[] roots = (URL[]) list.toArray(new URL[0]); String pluginIdentifier = feature.getPrimaryPluginID(); // save information in runtime platform state String version = feature.getVersionedIdentifier().getVersion().toString(); String application = feature.getApplication(); FeatureEntry featureEntry = (FeatureEntry)runtimeConfiguration.createFeatureEntry(id, version, pluginIdentifier, pluginVersion, true, application, roots); featureEntry.setURL(getFeatureRelativeURL(feature)); siteEntry.addFeatureEntry(featureEntry); } else { // write non-primary feature entries String version = feature.getVersionedIdentifier().getVersion().toString(); String pluginIdentifier = feature.getPrimaryPluginID(); FeatureEntry featureEntry = (FeatureEntry)runtimeConfiguration.createFeatureEntry(id, version, pluginIdentifier, pluginVersion, false, null, null); featureEntry.setURL(getFeatureRelativeURL(feature)); siteEntry.addFeatureEntry(featureEntry); } // write the platform features (features that contain special platform plugins) IPluginEntry[] platformPlugins = getPlatformPlugins(feature, runtimeConfiguration); for (int k = 0; k < platformPlugins.length; k++) { id = platformPlugins[k].getVersionedIdentifier().getIdentifier(); url = getRuntimeConfigurationURL(platformPlugins[k], cSite); if (url != null) { runtimeConfiguration.setBootstrapPluginLocation(id, url); } } } /* * Log if we are about to create a site that didn't exist before * in platform.cfg [16696]. */ private void checkSites(ConfiguredSiteModel[] configurationSites, IPlatformConfiguration runtimeConfiguration) throws CoreException { // check all the sites we are about to write already existed // they should have existed either because they were created by // updateManager or because we read them from platform.cfg for (int i = 0; i < configurationSites.length; i++) { // get the URL of the site that matches the one platform.cfg gave us URL urlToCheck = null; try { urlToCheck = new URL(configurationSites[i].getPlatformURLString()); } catch (MalformedURLException e) { UpdateCore.warn(NLS.bind(Messages.InstallConfiguration_UnableToCreateURL, (new String[] { configurationSites[i].getPlatformURLString() })), e); } catch (ClassCastException e) { UpdateCore.warn(Messages.InstallConfiguration_UnableToCast, e); } // if the URL doesn't exits log it IPlatformConfiguration.ISiteEntry siteEntry = runtimeConfiguration.findConfiguredSite(urlToCheck); if (siteEntry == null) { UpdateCore.warn(NLS.bind(Messages.InstallConfiguration_unableToFindSite, (new String[] { urlToCheck.toExternalForm(), runtimeConfiguration.getConfigurationLocation().toExternalForm() }))); } } } /* * reverts this configuration to the match the new one * * Compare the oldSites with the currentOne. the old state is the state we want to revert to. * * If a site was in old state, but not in the currentOne, keep it in the hash. * If a site is in the currentOne but was not in the old state, unconfigure all features and add it in the hash * If a site was in baoth state, calculate the 'delta' and re-set it in the hash map * * At the end, set the configured site from the new sites hash map * */ public void revertTo(IInstallConfiguration configuration, IProgressMonitor monitor, IProblemHandler handler) throws CoreException, InterruptedException { IConfiguredSite[] oldConfigSites = configuration.getConfiguredSites(); IConfiguredSite[] nowConfigSites = this.getConfiguredSites(); // create a hashtable of the *old* and *new* sites Map oldSitesMap = new Hashtable(0); Map newSitesMap = new Hashtable(0); for (int i = 0; i < oldConfigSites.length; i++) { IConfiguredSite element = oldConfigSites[i]; oldSitesMap.put(element.getSite().getURL().toExternalForm(), element); newSitesMap.put(element.getSite().getURL().toExternalForm(), element); } // create list of all the sites that map the *old* sites // we want the intersection between the old sites and the current sites if (nowConfigSites != null) { String key = null; for (int i = 0; i < nowConfigSites.length; i++) { key = nowConfigSites[i].getSite().getURL().toExternalForm(); IConfiguredSite oldSite = (IConfiguredSite) oldSitesMap.get(key); if (oldSite != null) { // the Site existed before, calculate the delta between its current state and the // state we are reverting to and put it back into the map ((ConfiguredSite) nowConfigSites[i]).revertTo(oldSite, monitor, handler); } else { // the site didn't exist in the InstallConfiguration we are reverting to // unconfigure everything from this site so it is still present ISiteFeatureReference[] featuresToUnconfigure = nowConfigSites[i].getSite().getFeatureReferences(); for (int j = 0; j < featuresToUnconfigure.length; j++) { IFeature featureToUnconfigure = null; try { featureToUnconfigure = featuresToUnconfigure[j].getFeature(null); } catch (CoreException e) { UpdateCore.warn(null, e); } if (featureToUnconfigure != null) nowConfigSites[i].unconfigure(featureToUnconfigure); } } newSitesMap.put(key,nowConfigSites[i]); } // the new configuration has the exact same sites as the old configuration // the old configuration in the Map are either as-is because they don't exist // in the current one, or they are the delta from the current one to the old one Collection sites = newSitesMap.values(); if (sites != null && !sites.isEmpty()) { ConfiguredSiteModel[] sitesModel = new ConfiguredSiteModel[sites.size()]; sites.toArray(sitesModel); setConfigurationSiteModel(sitesModel); } } } /* * @see IInstallConfiguration#getActivities() */ public IActivity[] getActivities() { if (getActivityModel().length == 0) return new IActivity[0]; return (IActivity[]) getActivityModel(); } /* * returns the list of platform plugins of the feature or an empty list * if the feature doesn't contain any platform plugins */ private IPluginEntry[] getPlatformPlugins(IFeature feature, IPlatformConfiguration runtimeConfiguration) { Map featurePlatformPlugins = new HashMap(); String[] platformPluginID = runtimeConfiguration.getBootstrapPluginIdentifiers(); IPluginEntry[] featurePlugins = feature.getPluginEntries(); for (int i = 0; i < platformPluginID.length; i++) { String featurePluginId = null; for (int j = 0; j < featurePlugins.length; j++) { featurePluginId = featurePlugins[j].getVersionedIdentifier().getIdentifier(); if (platformPluginID[i].equals(featurePluginId)) { featurePlatformPlugins.put(platformPluginID[i], featurePlugins[j]); } } } Collection values = featurePlatformPlugins.values(); if (values == null || values.size() == 0) return new IPluginEntry[0]; IPluginEntry[] result = new IPluginEntry[values.size()]; Iterator iter = values.iterator(); int index = 0; while (iter.hasNext()) { result[index] = ((IPluginEntry) iter.next()); index++; } return result; } /* * returns the URL of the pluginEntry on the site * Transform the URL to use platform: protocol if needed * return null if the URL to write is not valid */ private URL getRuntimeConfigurationURL(IPluginEntry entry, ConfiguredSite cSite) throws CoreException { String rootString = cSite.getPlatformURLString(); String pluginPathID = getPathID(entry); try { ISiteContentProvider siteContentProvider = cSite.getSite().getSiteContentProvider(); URL pluginEntryfullURL = siteContentProvider.getArchiveReference(pluginPathID); // if (!rootString.startsWith("platform")) { //$NON-NLS-1$ // DEBUG: if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_CONFIGURATION) UpdateCore.debug("getRuntimeConfiguration Plugin Entry Full URL:" + pluginEntryfullURL + " Platform String:" + rootString + " [NON PLATFORM URL]."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ return pluginEntryfullURL; } //URL pluginEntryRootURL = Platform.resolve(new URL(rootString)); // Do not resolve [16507], just use platform:base/ as a root // rootString = platform:base // pluginRoot = /home/a // pluginFull = /home/a/c/boot.jar // relative = platform:/base/c/boot.jar URL pluginEntryRootURL = cSite.getSite().getURL(); String relativeString = UpdateManagerUtils.getURLAsString(pluginEntryRootURL, pluginEntryfullURL); URL result = new URL(new URL(rootString), relativeString); // DEBUG: if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_CONFIGURATION) UpdateCore.debug("getRuntimeConfiguration plugin Entry Full URL:" + pluginEntryfullURL + " Platform String:" + rootString + " Site URL:" + pluginEntryRootURL + " Relative:" + relativeString); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ // verify we are about to write a valid file URL // check with fullURL as it is not resolved to platform:base/ if (pluginEntryfullURL != null) { if ("file".equals(pluginEntryfullURL.getProtocol())) { //$NON-NLS-1$ String fileString = pluginEntryfullURL.getFile(); if (!new File(fileString).exists()) { UpdateCore.warn("The URL:" + result + " doesn't point to a valid platform plugin.The URL will not be written in the platform configuration", new Exception()); //$NON-NLS-1$ //$NON-NLS-2$ return null; } } } return result; } catch (IOException e) { throw Utilities.newCoreException(NLS.bind(Messages.InstallConfiguration_UnableToCreateURL, (new String[] { rootString })), e); } } /* * Return URLs for any fragments that are associated with the specified plugin entry */ private URL[] getRuntimeFragmentURLs(IPluginEntry entry) throws CoreException { // get the identifier associated with the entry VersionedIdentifier vid = entry.getVersionedIdentifier(); // get the plugin descriptor from the registry Bundle bundle = Platform.getBundle(vid.getIdentifier()); ArrayList list = new ArrayList(); if (bundle != null && bundle.getState() != Bundle.UNINSTALLED && bundle.getState() != Bundle.INSTALLED) { FragmentEntry[] fragments = UpdateManagerUtils.getFragments(bundle); for (int i = 0; fragments != null && i < fragments.length; i++) { String location = fragments[i].getLocation(); try { URL locationURL = new URL(location); locationURL = FileLocator.toFileURL(FileLocator.resolve(locationURL)); list.add(asInstallRelativeURL(locationURL)); } catch (IOException e) { // skip bad fragments } } } return (URL[]) list.toArray(new URL[0]); } /** * Returns the path identifier for a plugin entry. * <code>plugins/<pluginId>_<pluginVersion>.jar</code> * @return the path identifier */ private String getPathID(IPluginEntry entry) { return Site.DEFAULT_PLUGIN_PATH + entry.getVersionedIdentifier().toString() + FeatureContentProvider.JAR_EXTENSION; } /** * Try to recast URL as platform:/base/ */ private URL asInstallRelativeURL(URL url) { // get location of install URL install = ConfiguratorUtils.getInstallURL(); // try to determine if supplied URL can be recast as install-relative if (install.getProtocol().equals(url.getProtocol())) { if (install.getProtocol().equals("file")) { //$NON-NLS-1$ String installS = new File(install.getFile()).getAbsolutePath().replace(File.separatorChar, '/'); if (!installS.endsWith("/")) //$NON-NLS-1$ installS += "/"; //$NON-NLS-1$ String urlS = new File(url.getFile()).getAbsolutePath().replace(File.separatorChar, '/'); if (!urlS.endsWith("/")) //$NON-NLS-1$ urlS += "/"; //$NON-NLS-1$ int ix = installS.lastIndexOf("/"); //$NON-NLS-1$ if (ix != -1) { installS = installS.substring(0, ix + 1); if (urlS.startsWith(installS)) { try { return new URL("platform:/base/" + urlS.substring(installS.length())); //$NON-NLS-1$ } catch (MalformedURLException e) { } } } } } return url; } private boolean isDuplicateSite(File siteDirectory) { IConfiguredSite[] sites = getConfiguredSites(); URL fileURL; try { fileURL = siteDirectory.toURL(); } catch (MalformedURLException e) { return false; } for (int i = 0; i < sites.length; i++) { URL url = sites[i].getSite().getURL(); if (UpdateManagerUtils.sameURL(fileURL, url)) return true; } return false; } /* * Returns the feature url relative to the site. */ private String getFeatureRelativeURL(IFeature feature) { String url = feature.getURL().toExternalForm(); String siteURL = feature.getSite().getURL().toExternalForm(); // TODO fix this. toURL() returns file:/d:/eclipse/etc... wheareas the // platform.asLocalURL() returns file:d:/eclipse/etc... (no leading / ) // if (url.startsWith("file:/") && Platform.getOS().equals("win32")) // url = "file:" + url.substring(6); if (url.startsWith(siteURL)) return url.substring(siteURL.length()); else return url; } /** * @return true if restart is needed */ private boolean isRestartNeeded(IPlatformConfiguration runtimeConfig) { // First, create a map for faster lookups Set newPluginsSet = null; if (runtimeConfig instanceof PlatformConfiguration) { newPluginsSet = ((PlatformConfiguration)runtimeConfig).getPluginPaths(); // On windows, we will be doing case insensitive search as well, so lower it now if (isWindows) { String[] newPluginsSetArray = (String[])newPluginsSet.toArray( new String[newPluginsSet.size()]); for (int i = 0; i < newPluginsSetArray.length; i++) { newPluginsSet.add(newPluginsSetArray[i].toLowerCase()); } } } else { URL[] newBundlePaths = runtimeConfig.getPluginPath(); newPluginsSet = new HashSet(newBundlePaths.length); for (int i=0; i<newBundlePaths.length; i++) { String pluginLocation = newBundlePaths[i].getFile(); newPluginsSet.add(pluginLocation); // On windows, we will be doing case insensitive search as well, so lower it now if (isWindows) newPluginsSet.add(pluginLocation.toLowerCase()); } } Bundle[] oldBundles = UpdateCore.getPlugin().getBundleContext().getBundles(); int offset = ConfigurationActivator.UPDATE_PREFIX.length(); for (int i=0; i<oldBundles.length; i++) { if (oldBundles[i].getBundleId() == 0) continue; // skip the system bundle String oldBundleLocation = oldBundles[i].getLocation(); // Don't worry about bundles we did not install if (!oldBundleLocation.startsWith(ConfigurationActivator.UPDATE_PREFIX)) continue; oldBundleLocation = oldBundleLocation.substring(offset); if (newPluginsSet.contains(oldBundleLocation)) continue; if (isWindows && newPluginsSet.contains(oldBundleLocation.toLowerCase())) continue; if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_CONFIGURATION) UpdateCore.debug("Bundle " + oldBundleLocation + " has been removed"); //$NON-NLS-1$ //$NON-NLS-2$ return true; } if (runtimeConfig instanceof PlatformConfiguration) { return areThereNewVersionOfOldPlugins( ((PlatformConfiguration)runtimeConfig).getPlugins(), oldBundles); } return false; } /** * The method should only be called if all old plug-ins exist in the new * configuration. Determines if a new version was added to any plugin ID, so * more versions are enabled for any given plug-in id then in old * configuration. * * @param newConfigurationPlugins * @param oldConfigurationBundles * @return */ private boolean areThereNewVersionOfOldPlugins(PluginEntry[] newConfigurationPlugins, Bundle[] oldConfigurationBundles) { for ( int i = 0; i < oldConfigurationBundles.length; i++) { if (oldConfigurationBundles[i].getBundleId() == 0) continue; // skip the system bundle if ( getNumberOfPlugins(oldConfigurationBundles[i].getSymbolicName(), oldConfigurationBundles) != getNumberOfPlugins(oldConfigurationBundles[i].getSymbolicName(), newConfigurationPlugins)) { return true; } } return false; } private int getNumberOfPlugins(String symbolicName, PluginEntry[] newConfigurationPlugins) { int numberOfPlugins = 0; for ( int i = 0; i < newConfigurationPlugins.length; i++) { if ( symbolicName.equals(newConfigurationPlugins[i].getPluginIdentifier())) { numberOfPlugins++; } } return numberOfPlugins; } private int getNumberOfPlugins(String symbolicName, Bundle[] oldConfigurationBundles) { int numberOfPlugins = 0; for ( int i = 0; i < oldConfigurationBundles.length; i++) { if ( symbolicName.equals(oldConfigurationBundles[i].getSymbolicName())) { numberOfPlugins++; } } return numberOfPlugins; } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof InstallConfiguration)) return false; InstallConfiguration config = (InstallConfiguration)obj; return getCreationDate().equals(config.getCreationDate()) && getLabel().equals(config.getLabel()) && getLocationURLString().equals(config.getLocationURLString()); } }