| /******************************************************************************* |
| * Copyright (c) 2000, 2003 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Common Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.update.internal.core; |
| |
| |
| import java.io.*; |
| import java.net.*; |
| import java.util.*; |
| |
| import org.eclipse.core.runtime.*; |
| import org.eclipse.update.configuration.*; |
| import org.eclipse.update.core.*; |
| import org.eclipse.update.core.model.*; |
| import org.eclipse.update.internal.model.*; |
| import org.eclipse.update.internal.operations.*; |
| import org.eclipse.update.configurator.*; |
| |
| /** |
| * A Configured site manages the Configured and unconfigured features of a Site |
| */ |
| public class ConfiguredSite extends ConfiguredSiteModel implements IConfiguredSite { |
| |
| private static final String PRODUCT_SITE_MARKER = ".eclipseproduct"; //$NON-NLS-1$ |
| private static final String EXTENSION_SITE_MARKER = ".eclipseextension"; //$NON-NLS-1$ |
| |
| // listeners |
| private ListenersList listeners = new ListenersList(); |
| |
| // verification status |
| private IStatus verifyStatus; |
| |
| // transient: true if the site was just created so we can remove it |
| private transient boolean justCreated = false; |
| |
| /* |
| * Default Constructor |
| */ |
| public ConfiguredSite() { |
| } |
| |
| /* |
| * Copy Constructor |
| * As of now, configSite can only be of type ConfiguredSite |
| */ |
| public ConfiguredSite(IConfiguredSite configSite) { |
| ConfiguredSite cSite = (ConfiguredSite) configSite; |
| setSiteModel(cSite.getSiteModel()); |
| setConfigurationPolicyModel(new ConfigurationPolicy(cSite.getConfigurationPolicy())); |
| setUpdatable(cSite.isUpdatable()); |
| setEnabled(cSite.isEnabled()); |
| setPreviousPluginPath(cSite.getPreviousPluginPath()); |
| setPlatformURLString(cSite.getPlatformURLString()); |
| } |
| |
| /* |
| * Adds a listener |
| */ |
| public void addConfiguredSiteChangedListener(IConfiguredSiteChangedListener listener) { |
| synchronized (listeners) { |
| listeners.add(listener); |
| } |
| } |
| |
| /* |
| * Removes a listener |
| */ |
| public void removeConfiguredSiteChangedListener(IConfiguredSiteChangedListener listener) { |
| synchronized (listeners) { |
| listeners.remove(listener); |
| } |
| } |
| |
| /* |
| * @see IConfiguredSite#install(IFeature,IVerificationListener, IProgressMonitor) |
| */ |
| public IFeatureReference install(IFeature feature, IVerificationListener verificationListener, IProgressMonitor monitor) throws InstallAbortedException, CoreException { |
| return install(feature, null, verificationListener, monitor); |
| } |
| |
| /* |
| * @see IConfiguredSite#install(IFeature, IFeatureReference, IVerificationListener, IProgressMonitor) |
| */ |
| public IFeatureReference install(IFeature feature, IFeatureReference[] optionalFeatures, IVerificationListener verificationListener, IProgressMonitor monitor) throws InstallAbortedException, CoreException { |
| |
| // change the status if justCreated |
| if (justCreated) justCreated=false; |
| |
| // ConfigSite is read only |
| if (!isUpdatable()) { |
| String errorMessage = Policy.bind("ConfiguredSite.NonInstallableSite", getSite().getURL().toExternalForm()); //$NON-NLS-1$ |
| IStatus status = verifyUpdatableStatus(); |
| if (status != null) |
| errorMessage += " " + status.getMessage(); //$NON-NLS-1$ |
| throw Utilities.newCoreException(errorMessage, null); |
| } |
| |
| // feature is null |
| if (feature == null) { |
| String errorMessage = Policy.bind("ConfiguredSite.NullFeatureToInstall"); //$NON-NLS-1$ |
| throw Utilities.newCoreException(errorMessage, null); |
| } |
| |
| // feature reference to return |
| IFeatureReference installedFeatureRef; |
| IFeature installedFeature = null; |
| |
| // create the Activity (INSTALL) |
| ConfigurationActivity activity = new ConfigurationActivity(IActivity.ACTION_FEATURE_INSTALL); |
| activity.setLabel(feature.getVersionedIdentifier().toString()); |
| activity.setDate(new Date()); |
| |
| try { |
| installedFeatureRef = getSite().install(feature, optionalFeatures, verificationListener, monitor); |
| |
| if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_INSTALL) { |
| UpdateCore.debug("Sucessfully installed: " + installedFeatureRef.getURL().toExternalForm()); //$NON-NLS-1$ |
| } |
| |
| if (installedFeatureRef != null) { |
| try { |
| installedFeature = installedFeatureRef.getFeature(null); |
| } catch (CoreException e) { |
| UpdateCore.warn(null, e); |
| } |
| } |
| |
| // everything done ok |
| activity.setStatus(IActivity.STATUS_OK); |
| |
| // notify listeners |
| Object[] siteListeners = listeners.getListeners(); |
| for (int i = 0; i < siteListeners.length; i++) { |
| if (installedFeature != null) { |
| IConfiguredSiteChangedListener listener = ((IConfiguredSiteChangedListener) siteListeners[i]); |
| listener.featureInstalled(installedFeature); |
| } |
| } |
| } catch (CoreException e) { |
| // not ok, set Activity status |
| activity.setStatus(IActivity.STATUS_NOK); |
| throw e; |
| } finally { |
| IInstallConfiguration current = SiteManager.getLocalSite().getCurrentConfiguration(); |
| ((InstallConfiguration) current).addActivity(activity); |
| } |
| // call the configure task |
| if (installedFeature != null) |
| configure(installedFeature, optionalFeatures, false); |
| /*callInstallHandler*/ |
| |
| return installedFeatureRef; |
| } |
| |
| /* |
| * @see IConfiguredSite#remove(IFeature, IProgressMonitor) |
| */ |
| public void remove(IFeature feature, IProgressMonitor monitor) throws CoreException { |
| |
| // ConfigSite is read only |
| if (!isUpdatable()) { |
| String errorMessage = Policy.bind("ConfiguredSite.NonUninstallableSite", getSite().getURL().toExternalForm()); //$NON-NLS-1$ |
| throw Utilities.newCoreException(errorMessage, null); |
| } |
| |
| // create the Activity |
| ConfigurationActivity activity = new ConfigurationActivity(IActivity.ACTION_FEATURE_REMOVE); |
| activity.setLabel(feature.getVersionedIdentifier().toString()); |
| activity.setDate(new Date()); |
| |
| try { |
| IFeatureReference referenceToRemove = null; |
| ISiteFeatureReference[] featureRef = getSite().getFeatureReferences(); |
| ISiteFeatureReference ref = getSite().getFeatureReference(feature); |
| for (int i = 0; i < featureRef.length; i++) { |
| if (featureRef[i].equals(ref)) { |
| referenceToRemove = featureRef[i]; |
| break; |
| } |
| } |
| |
| // we found a feature reference on the site matching the feature |
| if (referenceToRemove != null) { |
| // Check if feature is unconfigured before we remove it |
| // our UI will check. |
| // For non-UI application, throw error is feature is configured |
| if (getConfigurationPolicy().isConfigured(referenceToRemove)) { |
| IFeature featureToRemove = ((IFeatureReference) referenceToRemove).getFeature(null); |
| String featureLabel = (featureToRemove == null) ? null : featureToRemove.getLabel(); |
| throw Utilities.newCoreException(Policy.bind("ConfiguredSite.UnableToRemoveConfiguredFeature" //$NON-NLS-1$ |
| , featureLabel), null); |
| } |
| } else { |
| throw Utilities.newCoreException(Policy.bind("ConfiguredSite.UnableToFindFeature", feature.getURL().toString()), //$NON-NLS-1$ |
| null); |
| } |
| |
| // remove the feature |
| getSite().remove(feature, monitor); |
| getConfigurationPolicy().removeFeatureReference(referenceToRemove); |
| // everything done ok |
| activity.setStatus(IActivity.STATUS_OK); |
| // notify listeners |
| Object[] siteListeners = listeners.getListeners(); |
| for (int i = 0; i < siteListeners.length; i++) { |
| ((IConfiguredSiteChangedListener) siteListeners[i]).featureRemoved(feature); |
| } |
| } catch (CoreException e) { |
| activity.setStatus(IActivity.STATUS_NOK); |
| throw e; |
| } finally { |
| IInstallConfiguration current = SiteManager.getLocalSite().getCurrentConfiguration(); |
| ((InstallConfiguration) current).addActivity(activity); |
| } |
| } |
| |
| /* |
| * @see IConfiguredSite#configure(IFeature) |
| */ |
| public void configure(IFeature feature) throws CoreException { |
| configure(feature, null, true /*callInstallHandler*/ |
| ); |
| } |
| |
| /* |
| * |
| */ |
| private void configure(IFeature feature, IFeatureReference[] optionalFeatures, boolean callInstallHandler) throws CoreException { |
| |
| if (feature == null) { |
| UpdateCore.warn("Attempting to configure a null feature in site:" + getSite().getURL().toExternalForm()); //$NON-NLS-1$ |
| return; |
| } |
| |
| ConfigurationPolicy configPolicy = getConfigurationPolicy(); |
| if (configPolicy == null) |
| return; |
| |
| // bottom up approach, same configuredSite |
| IIncludedFeatureReference[] childrenRef = feature.getIncludedFeatureReferences(); |
| if (optionalFeatures != null) { |
| childrenRef = childrenToConfigure(childrenRef, optionalFeatures); |
| } |
| |
| for (int i = 0; i < childrenRef.length; i++) { |
| try { |
| IFeature child = childrenRef[i].getFeature(null); |
| configure(child, optionalFeatures, callInstallHandler); |
| } catch (CoreException e) { |
| // will skip any bad children |
| if (!childrenRef[i].isOptional()) |
| UpdateCore.warn("Unable to configure child feature: " + childrenRef[i] + " " + e); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| |
| // configure root feature |
| IFeatureReference featureReference = getSite().getFeatureReference(feature); |
| configPolicy.configure(featureReference, callInstallHandler, true); |
| |
| // notify listeners |
| Object[] siteListeners = listeners.getListeners(); |
| for (int i = 0; i < siteListeners.length; i++) { |
| ((IConfiguredSiteChangedListener) siteListeners[i]).featureConfigured(feature); |
| } |
| } |
| |
| /* |
| * Return the optional children to configure |
| * |
| * @param children all the nested features |
| * @param optionalfeatures optional features to install |
| * @return IFeatureReference[] |
| */ |
| private IIncludedFeatureReference[] childrenToConfigure(IIncludedFeatureReference[] children, IFeatureReference[] optionalfeatures) { |
| |
| List childrenToInstall = new ArrayList(); |
| for (int i = 0; i < children.length; i++) { |
| IIncludedFeatureReference optionalFeatureToConfigure = children[i]; |
| if (!optionalFeatureToConfigure.isOptional()) { |
| childrenToInstall.add(optionalFeatureToConfigure); |
| } else { |
| for (int j = 0; j < optionalfeatures.length; j++) { |
| // must compare feature as optionalFeatures are from the install site |
| // where children are on the local site |
| try { |
| IFeature installedChildren = optionalfeatures[j].getFeature(null); |
| if (installedChildren.equals(optionalFeatureToConfigure.getFeature(null))) { |
| childrenToInstall.add(optionalFeatureToConfigure); |
| break; |
| } |
| } catch (CoreException e) { |
| UpdateCore.warn("", e); //$NON-NLS-1$ |
| } |
| } |
| } |
| } |
| |
| IIncludedFeatureReference[] result = new IIncludedFeatureReference[childrenToInstall.size()]; |
| if (childrenToInstall.size() > 0) { |
| childrenToInstall.toArray(result); |
| } |
| |
| return result; |
| } |
| |
| /* |
| * @see IConfiguredSite#unconfigure(IFeature) |
| */ |
| public boolean unconfigure(IFeature feature) throws CoreException { |
| // the first call sould disable without checking for enable parent |
| return unconfigure(feature, true, false); |
| } |
| |
| private boolean unconfigure(IFeature feature, boolean includePatches, boolean verifyEnableParent) throws CoreException { |
| IFeatureReference featureReference = getSite().getFeatureReference(feature); |
| |
| if (featureReference == null) { |
| UpdateCore.warn("Unable to retrieve Feature Reference for feature" + feature); //$NON-NLS-1$ |
| return false; |
| } |
| |
| ConfigurationPolicy configPolicy = getConfigurationPolicy(); |
| if (configPolicy == null) |
| return false; |
| |
| // verify no enable parent |
| if (verifyEnableParent && !validateNoConfiguredParents(feature)) { |
| UpdateCore.warn("The feature " + feature.getVersionedIdentifier() + " to disable is needed by another enable feature"); //$NON-NLS-1$ //$NON-NLS-2$ |
| return false; |
| } |
| |
| boolean sucessfullyUnconfigured = false; |
| try { |
| sucessfullyUnconfigured = configPolicy.unconfigure(featureReference, true, true); |
| } catch (CoreException e) { |
| URL url = featureReference.getURL(); |
| String urlString = (url != null) ? url.toExternalForm() : "<no feature reference url>"; //$NON-NLS-1$ |
| UpdateCore.warn("Unable to unconfigure" + urlString, e); //$NON-NLS-1$ |
| throw e; |
| } |
| if (sucessfullyUnconfigured) { |
| // 2.0.2: unconfigure patches that reference this feature. |
| // A patch is a feature that contains an import |
| // statement with patch="true" and an id/version |
| // that matches an already installed and configured |
| // feature. When patched feature is unconfigured, |
| // all the patches that reference it must be |
| // unconfigured as well |
| // (in contrast, patched features can be |
| // configured without the patches). |
| if (includePatches) |
| unconfigurePatches(feature); |
| |
| // top down approach, same configuredSite |
| IIncludedFeatureReference[] childrenRef = feature.getIncludedFeatureReferences(); |
| for (int i = 0; i < childrenRef.length; i++) { |
| try { |
| IFeature child = childrenRef[i].getFeature(null); // disable the exact feature |
| unconfigure(child, includePatches, true); // check for parent as we should be the only parent. |
| } catch (CoreException e) { |
| // skip any bad children |
| UpdateCore.warn("Unable to unconfigure child feature: " + childrenRef[i] + " " + e); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| |
| // notify listeners |
| Object[] siteListeners = listeners.getListeners(); |
| for (int i = 0; i < siteListeners.length; i++) { |
| IConfiguredSiteChangedListener listener = ((IConfiguredSiteChangedListener) siteListeners[i]); |
| listener.featureUnconfigured(feature); |
| } |
| |
| return true; |
| } else { |
| URL url = featureReference.getURL(); |
| String urlString = (url != null) ? url.toExternalForm() : "<no feature reference url>"; //$NON-NLS-1$ |
| UpdateCore.warn("Unable to unconfigure:" + urlString); //$NON-NLS-1$ |
| return false; |
| } |
| } |
| |
| /* |
| * Look for features that have an import reference |
| * that points to this feature and where patch=true. |
| * Unconfigure all the matching patches, but |
| * do not do the same lookup for them |
| * because patches cannot have patches themselves. |
| */ |
| |
| private void unconfigurePatches(IFeature feature) { |
| IFeatureReference[] frefs = getConfiguredFeatures(); |
| for (int i = 0; i < frefs.length; i++) { |
| IFeatureReference fref = frefs[i]; |
| try { |
| IFeature candidate = fref.getFeature(null); |
| if (candidate.equals(feature)) |
| continue; |
| |
| if (UpdateUtils.isPatch(feature, candidate)) |
| unconfigure(candidate, false, false); |
| } catch (CoreException e) { |
| UpdateCore.warn("", e); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| /* |
| * @see IConfiguredSite#getConfiguredFeatures() |
| */ |
| public IFeatureReference[] getConfiguredFeatures() { |
| if (isEnabled()) |
| return getRawConfiguredFeatures(); |
| else |
| return new ISiteFeatureReference[0]; |
| } |
| |
| /* |
| * @see IConfiguredSite#getConfiguredFeatures() |
| */ |
| private IFeatureReference[] getRawConfiguredFeatures() { |
| ConfigurationPolicy configPolicy = getConfigurationPolicy(); |
| if (configPolicy == null) |
| return new ISiteFeatureReference[0]; |
| |
| return configPolicy.getConfiguredFeatures(); |
| } |
| |
| /* |
| * adds configured and unconfigured feature references |
| */ |
| public IFeatureReference[] getFeatureReferences() { |
| |
| ConfigurationPolicy configPolicy = getConfigurationPolicy(); |
| if (configPolicy == null) |
| return new ISiteFeatureReference[0]; |
| |
| IFeatureReference[] configuredFeatures = getConfiguredFeatures(); |
| int confLen = configuredFeatures.length; |
| IFeatureReference[] unconfiguredFeatures = configPolicy.getUnconfiguredFeatures(); |
| int unconfLen = unconfiguredFeatures.length; |
| |
| IFeatureReference[] result = new IFeatureReference[confLen + unconfLen]; |
| if (confLen > 0) { |
| System.arraycopy(configuredFeatures, 0, result, 0, confLen); |
| } |
| if (unconfLen > 0) { |
| System.arraycopy(unconfiguredFeatures, 0, result, confLen, unconfLen); |
| } |
| |
| return result; |
| } |
| |
| /* |
| * Configure and unconfigure appropriate feature to |
| * become 'like' currentConfiguration which is the configuration |
| * the user wants to revert to. |
| * |
| * All features from currentConfiguration should be configured |
| */ |
| public void revertTo(IConfiguredSite oldConfiguration, IProgressMonitor monitor, IProblemHandler handler) throws CoreException, InterruptedException { |
| |
| ConfiguredSite oldConfiguredSite = (ConfiguredSite) oldConfiguration; |
| |
| // retrieve the feature that were configured |
| IFeatureReference[] configuredFeatures = oldConfiguredSite.validConfiguredFeatures(handler); |
| |
| for (int i = 0; i < configuredFeatures.length; i++) { |
| getConfigurationPolicy().configure(configuredFeatures[i], true, true); |
| } |
| |
| // calculate all the features we have to unconfigure from the current state to this state |
| // in the history. |
| List featureToUnconfigure = oldConfiguredSite.calculateUnconfiguredFeatures(configuredFeatures); |
| |
| // for each unconfigured feature check if it still exists |
| // if so add as unconfigured |
| Iterator iter = featureToUnconfigure.iterator(); |
| while (iter.hasNext()) { |
| IFeatureReference element = (IFeatureReference) iter.next(); |
| try { |
| // do not log activity |
| getConfigurationPolicy().unconfigure(element, true, true); |
| } catch (CoreException e) { |
| // log no feature to unconfigure |
| String url = element.getURL().toString(); |
| ISite site = element.getSite(); |
| String siteString = (site != null) ? site.getURL().toExternalForm() : Policy.bind("ConfiguredSite.NoSite"); //$NON-NLS-1$ |
| UpdateCore.warn(Policy.bind("ConfiguredSite.CannotFindFeatureToUnconfigure", url, siteString), e); //$NON-NLS-1$ |
| } |
| } |
| //} // end USER_EXCLUDE |
| } |
| |
| /* |
| * We have to keep our configured feature |
| * check if they are all valid |
| * Return the valid configured features |
| */ |
| private IFeatureReference[] validConfiguredFeatures(IProblemHandler handler) throws InterruptedException { |
| |
| IFeatureReference[] configuredFeatures = getConfiguredFeatures(); |
| if (configuredFeatures != null) { |
| for (int i = 0; i < configuredFeatures.length; i++) { |
| IFeature feature = null; |
| |
| // attempt to access the feature |
| try { |
| feature = configuredFeatures[i].getFeature(null); |
| } catch (CoreException e) { |
| // notify we cannot find the feature |
| UpdateCore.warn(null, e); |
| String featureString = configuredFeatures[i].getURL().toExternalForm(); |
| if (!handler.reportProblem(Policy.bind("ConfiguredSite.CannotFindFeatureToConfigure", featureString))) { //$NON-NLS-1$ |
| throw new InterruptedException(); |
| } |
| } |
| |
| // verify all the plugins still exist |
| if (feature != null) { |
| // get plugin identifier |
| List sitePluginIdentifiers = new ArrayList(); |
| ISite site = feature.getSite(); |
| IPluginEntry[] sitePluginEntries = null; |
| |
| if (site != null) { |
| sitePluginEntries = site.getPluginEntries(); |
| for (int index = 0; index < sitePluginEntries.length; index++) { |
| IPluginEntry entry = sitePluginEntries[index]; |
| sitePluginIdentifiers.add(entry.getVersionedIdentifier()); |
| } |
| } |
| |
| if (sitePluginEntries.length > 0) { |
| IPluginEntry[] featurePluginEntries = feature.getPluginEntries(); |
| for (int index = 0; index < featurePluginEntries.length; index++) { |
| IPluginEntry currentFeaturePluginEntry = featurePluginEntries[index]; |
| if (!contains(currentFeaturePluginEntry.getVersionedIdentifier(), sitePluginIdentifiers)) { |
| // the plugin defined by the feature |
| // doesn't seem to exist on the site |
| String msg = "Error verifying existence of plugin:" + currentFeaturePluginEntry.getVersionedIdentifier().toString(); //$NON-NLS-1$ |
| UpdateCore.log(msg, new Exception()); |
| |
| String siteString = (site != null) ? site.getURL().toExternalForm() : Policy.bind("ConfiguredSite.NoSite"); //$NON-NLS-1$ |
| String errorLabel = Policy.bind("ConfiguredSite.CannotFindPluginEntry", currentFeaturePluginEntry.getVersionedIdentifier().toString(), siteString); //$NON-NLS-1$ //$NON-NLS-2$ |
| if (handler == null) { |
| throw new InterruptedException(errorLabel); |
| } |
| if (!handler.reportProblem(Policy.bind(errorLabel))) { |
| throw new InterruptedException(); |
| } |
| } // end if not found in site |
| } // end for |
| } |
| } |
| } // end for configured feature |
| } |
| return configuredFeatures; |
| } |
| |
| /* |
| * We are in the process of calculating the delta between what was configured in the current |
| * configuration that is not configured now |
| * |
| * we have to figure out what feature have been unconfigured for the whole |
| * history between current and us... |
| * |
| * is it as simple as get all configured, and unconfigured, |
| * the do the delta with what should be configured |
| * |
| */ |
| private List calculateUnconfiguredFeatures(IFeatureReference[] configuredFeatures) throws CoreException { |
| |
| Set featureToUnconfigureSet = new HashSet(); |
| |
| // loop for all history |
| // try to see if the configured site existed |
| // if it does, get the unconfigured features |
| // and the configured one |
| IInstallConfiguration[] history = SiteManager.getLocalSite().getConfigurationHistory(); |
| |
| for (int i = 0; i < history.length; i++) { |
| IInstallConfiguration element = history[i]; |
| IConfiguredSite[] configSites = element.getConfiguredSites(); |
| for (int j = 0; j < configSites.length; j++) { |
| ConfiguredSite configSite = (ConfiguredSite) configSites[j]; |
| if (configSite.getSite().equals(getSite())) { |
| featureToUnconfigureSet.addAll(Arrays.asList(configSite.getConfigurationPolicy().getUnconfiguredFeatures())); |
| featureToUnconfigureSet.addAll(Arrays.asList(configSite.getConfigurationPolicy().getConfiguredFeatures())); |
| } |
| } |
| } |
| |
| // remove the unconfigured feature we found that are now to be configured |
| // (they may have been unconfigured in the past, but the revert makes them configured) |
| List featureToUnconfigureList = remove(configuredFeatures, featureToUnconfigureSet); |
| |
| return featureToUnconfigureList; |
| } |
| |
| /* |
| * Utilities: Remove an array of feature references |
| * from a list |
| */ |
| private List remove(IFeatureReference[] featureRefs, Set set) { |
| List result = new ArrayList(); |
| |
| if (set == null) |
| return result; |
| |
| // if an element of the list is NOT found in the array, |
| // add it to the result list |
| Iterator iter = set.iterator(); |
| while (iter.hasNext()) { |
| IFeatureReference element = (IFeatureReference) iter.next(); |
| boolean found = false; |
| for (int i = 0; i < featureRefs.length; i++) { |
| if (element.equals(featureRefs[i])) { |
| found = true; |
| } |
| } |
| |
| if (!found) |
| result.add(element); |
| } |
| return result; |
| } |
| |
| /* |
| * I have issues when running list.contain(versionedIdentifier) |
| * The code runs the Object.equals instead of the VersionedIdentifier.equals |
| */ |
| private boolean contains(VersionedIdentifier id, List list) { |
| boolean found = false; |
| if (list != null && !list.isEmpty()) { |
| Iterator iter = list.iterator(); |
| while (iter.hasNext() && !found) { |
| VersionedIdentifier element = (VersionedIdentifier) iter.next(); |
| if (element.equals(id)) { |
| found = true; |
| } |
| } |
| } |
| return found; |
| } |
| |
| /* |
| * |
| */ |
| public ConfigurationPolicy getConfigurationPolicy() { |
| return (ConfigurationPolicy) getConfigurationPolicyModel(); |
| } |
| |
| /* |
| * |
| */ |
| public ISite getSite() { |
| return (ISite) getSiteModel(); |
| } |
| |
| /* |
| * |
| */ |
| public IInstallConfiguration getInstallConfiguration() { |
| return (IInstallConfiguration) getInstallConfigurationModel(); |
| } |
| |
| /* |
| * |
| */ |
| public IStatus getBrokenStatus(IFeature feature) { |
| |
| IStatus featureStatus = createStatus(IStatus.OK, IFeature.STATUS_HAPPY, "", null); //$NON-NLS-1$ |
| |
| // check the Plugins of all the features |
| // every plugin of the feature must be on the site |
| IPluginEntry[] siteEntries = getSite().getPluginEntries(); |
| IPluginEntry[] featuresEntries = feature.getPluginEntries(); |
| IPluginEntry[] result = UpdateManagerUtils.diff(featuresEntries, siteEntries); |
| if (result != null && (result.length != 0)) { |
| String msg = Policy.bind("SiteLocal.FeatureUnHappy"); //$NON-NLS-1$ |
| MultiStatus multi = new MultiStatus(featureStatus.getPlugin(), IFeature.STATUS_UNHAPPY, msg, null); |
| |
| for (int k = 0; k < result.length; k++) { |
| VersionedIdentifier id = result[k].getVersionedIdentifier(); |
| Object[] values = new String[] { "", "" }; //$NON-NLS-1$ //$NON-NLS-2$ |
| if (id != null) { |
| values = new Object[] { id.getIdentifier(), id.getVersion()}; |
| } |
| String msg1 = Policy.bind("ConfiguredSite.MissingPluginsBrokenFeature", values); //$NON-NLS-1$ |
| UpdateCore.warn(msg1); |
| IStatus status = createStatus(IStatus.ERROR, IFeature.STATUS_UNHAPPY, msg1, null); |
| multi.add(status); |
| } |
| return multi; |
| } |
| |
| // check os, arch, and ws |
| |
| String msg = Policy.bind("SiteLocal.FeatureHappy"); //$NON-NLS-1$ |
| return createStatus(IStatus.OK, IFeature.STATUS_HAPPY, msg, null); |
| } |
| |
| /* |
| * |
| */ |
| public boolean isConfigured(IFeature feature) { |
| if (!isEnabled()) |
| return false; |
| |
| if (getConfigurationPolicy() == null) |
| return false; |
| IFeatureReference featureReference = getSite().getFeatureReference(feature); |
| if (featureReference == null) { |
| if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_WARNINGS) |
| UpdateCore.warn("Unable to retrieve featureReference for feature:" + feature); //$NON-NLS-1$ |
| return false; |
| } |
| return getConfigurationPolicy().isConfigured(featureReference); |
| } |
| |
| /** |
| * @see Object#toString() |
| */ |
| public String toString() { |
| if (getSite() == null) |
| return "No Site"; //$NON-NLS-1$ |
| if (getSite().getURL() == null) |
| return "No URL"; //$NON-NLS-1$ |
| return getSite().getURL().toExternalForm(); |
| } |
| |
| /** |
| * @see IConfiguredSite#verifyUpdatableStatus() |
| */ |
| public IStatus verifyUpdatableStatus() { |
| |
| if (verifyStatus != null) |
| return verifyStatus; |
| |
| URL siteURL = getSite().getURL(); |
| if (siteURL == null) { |
| verifyStatus = createStatus(IStatus.ERROR, Policy.bind("ConfiguredSite.SiteURLNull"), null); //$NON-NLS-1$ |
| return verifyStatus; |
| } |
| |
| if (!"file".equalsIgnoreCase(siteURL.getProtocol())) { //$NON-NLS-1$ |
| verifyStatus = createStatus(IStatus.ERROR, Policy.bind("ConfiguredSite.NonLocalSite"), null); //$NON-NLS-1$ |
| return verifyStatus; |
| } |
| |
| String siteLocation = siteURL.getFile(); |
| File file = new File(siteLocation); |
| |
| // get the product name of the private marker |
| // if there is no private marker, check if the site is contained in another site |
| // if there is a marker and this is a different product, return false |
| // otherwise don't check if we are contained in another site |
| String productName = getProductName(file); |
| if (productName != null) { |
| if (!productName.equals(getProductIdentifier("id", getProductFile()))) { //$NON-NLS-1$ |
| verifyStatus = createStatus(IStatus.ERROR, Policy.bind("ConfiguredSite.NotSameProductId", productName), null); //$NON-NLS-1$ |
| return verifyStatus; |
| } |
| } else { |
| File container = getSiteContaining(file); |
| if (container != null) { |
| verifyStatus = createStatus(IStatus.ERROR, Policy.bind("ConfiguredSite.ContainedInAnotherSite", container.getAbsolutePath()), null); //$NON-NLS-1$ |
| return verifyStatus; |
| } |
| } |
| |
| if (!canWrite(file)) { |
| verifyStatus = createStatus(IStatus.ERROR, Policy.bind("ConfiguredSite.ReadOnlySite"), null); //$NON-NLS-1$ |
| return verifyStatus; |
| } |
| |
| verifyStatus = createStatus(IStatus.OK, "", null); //$NON-NLS-1$ |
| setUpdatable(true); |
| return verifyStatus; |
| } |
| |
| /* |
| * Verify we can write on the file system |
| */ |
| private static boolean canWrite(File file) { |
| if (!file.isDirectory() && file.getParentFile() != null) { |
| file = file.getParentFile(); |
| } |
| |
| File tryFile = null; |
| FileOutputStream out = null; |
| try { |
| tryFile = new File(file, "toDelete"); //$NON-NLS-1$ |
| out = new FileOutputStream(tryFile); |
| out.write(0); |
| } catch (IOException e) { |
| return false; |
| } finally { |
| try { |
| if (out != null) |
| out.close(); |
| } catch (IOException e) { |
| } |
| if (tryFile != null) |
| tryFile.delete(); |
| } |
| return true; |
| } |
| |
| /* |
| * Check if the directory contains a marker |
| * if not ask all directory children to check |
| * if one validates the condition, returns the marker |
| */ |
| private static File getSiteContaining(File file) { |
| |
| if (file == null) |
| return null; |
| |
| UpdateCore.warn("IsContained: Checking for markers at:" + file); //$NON-NLS-1$ |
| if (file.exists() && file.isDirectory()) { |
| File productFile = new File(file, PRODUCT_SITE_MARKER); |
| File extensionFile = new File(file, EXTENSION_SITE_MARKER); |
| if (productFile.exists() || extensionFile.exists()) |
| return file; |
| // // do not check if a marker exists in the current but start from the parent |
| // // the current is analyze by getProductname() |
| // if (file.getParentFile() != null) { |
| // File privateFile = new File(file.getParentFile(), PRIVATE_SITE_MARKER); |
| // if (privateFile.exists()) |
| // return file.getParentFile(); |
| // } |
| } |
| return getSiteContaining(file.getParentFile()); |
| } |
| |
| /* |
| * Returns the name of the product if the identifier of the private Site markup is not |
| * the same as the identifier of the product the workbench was started with. |
| * If the product is the same, return null. |
| */ |
| private static String getProductName(File file) { |
| |
| if (file == null) |
| return null; |
| |
| File markerFile = new File(file, EXTENSION_SITE_MARKER ); |
| if (!markerFile.exists()) { |
| return null; |
| } |
| |
| File productFile = getProductFile(); |
| String productId = null; |
| String privateId = null; |
| if (productFile != null) { |
| productId = getProductIdentifier("id", productFile); //$NON-NLS-1$ |
| privateId = getProductIdentifier("id", markerFile); //$NON-NLS-1$ |
| if (productId == null) { |
| UpdateCore.warn("Product ID is null at:" + productFile); //$NON-NLS-1$ |
| return null; |
| } |
| if (!productId.equalsIgnoreCase(privateId)) { |
| UpdateCore.warn("Product id at" + productFile + " Different than:" + markerFile); //$NON-NLS-1$ //$NON-NLS-2$ |
| String name = getProductIdentifier("name", markerFile); //$NON-NLS-1$ |
| String version = getProductIdentifier("version", markerFile); //$NON-NLS-1$ |
| String markerID = (name == null) ? version : name + ":" + version; //$NON-NLS-1$ |
| if (markerID == null) |
| markerID = ""; //$NON-NLS-1$ |
| return markerID; |
| } else { |
| return privateId; |
| } |
| } else { |
| UpdateCore.warn("Product Marker doesn't exist:" + productFile); //$NON-NLS-1$ |
| } |
| |
| return null; |
| } |
| |
| /* |
| * Returns the identifier of the product from the property file |
| */ |
| private static String getProductIdentifier(String identifier, File propertyFile) { |
| String result = null; |
| if (identifier == null) |
| return result; |
| InputStream in = null; |
| try { |
| in = new FileInputStream(propertyFile); |
| PropertyResourceBundle bundle = new PropertyResourceBundle(in); |
| result = bundle.getString(identifier); |
| } catch (IOException e) { |
| if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_INSTALL) |
| UpdateCore.debug("Exception reading property file:" + propertyFile); //$NON-NLS-1$ |
| } catch (MissingResourceException e) { |
| if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_INSTALL) |
| UpdateCore.debug("Exception reading '" + identifier + "' from property file:" + propertyFile); //$NON-NLS-1$ //$NON-NLS-2$ |
| } finally { |
| if (in == null) |
| try { |
| in.close(); |
| } catch (IOException e1) { |
| } |
| } |
| return result; |
| } |
| |
| /* |
| * Returns the identifier of the product from the property file |
| */ |
| private static File getProductFile() { |
| |
| String productInstallDirectory = ConfiguratorUtils.getInstallURL().getFile(); |
| if (productInstallDirectory != null) { |
| File productFile = new File(productInstallDirectory, PRODUCT_SITE_MARKER); |
| if (productFile.exists()) { |
| return productFile; |
| } else { |
| UpdateCore.warn("Product marker doesn't exist:" + productFile); //$NON-NLS-1$ |
| } |
| } else { |
| UpdateCore.warn("Cannot retrieve install URL from BootLoader"); //$NON-NLS-1$ |
| } |
| return null; |
| } |
| |
| /* |
| * |
| */ |
| /*package*/ |
| boolean createPrivateSiteMarker() { |
| URL siteURL = getSite().getURL(); |
| if (siteURL == null) { |
| UpdateCore.warn("Unable to create marker. The Site url is null."); //$NON-NLS-1$ |
| return false; |
| } |
| |
| if (!"file".equalsIgnoreCase(siteURL.getProtocol())) { //$NON-NLS-1$ |
| UpdateCore.warn("Unable to create private marker. The Site is not on the local file system."); //$NON-NLS-1$ |
| return false; |
| } |
| |
| String siteLocation = siteURL.getFile(); |
| File productFile = getProductFile(); |
| boolean success = false; |
| if (productFile != null) { |
| String productId = getProductIdentifier("id", productFile); //$NON-NLS-1$ |
| String productName = getProductIdentifier("name", productFile); //$NON-NLS-1$ |
| String productVer = getProductIdentifier("version", productFile); //$NON-NLS-1$ |
| if (productId != null) { |
| File file = new File(siteLocation, EXTENSION_SITE_MARKER); |
| if (!file.exists()) { |
| OutputStream out = null; |
| OutputStreamWriter outWriter = null; |
| try { |
| out = new FileOutputStream(file); |
| outWriter = new OutputStreamWriter(out, "UTF8"); //$NON-NLS-1$ |
| outWriter.write("id=" + productId+"\n"); //$NON-NLS-1$ //$NON-NLS-2$ |
| if (productName != null) |
| outWriter.write("name=" + productName+"\n"); //$NON-NLS-1$ //$NON-NLS-2$ |
| if (productVer != null) |
| outWriter.write("version=" + productVer+"\n"); //$NON-NLS-1$ //$NON-NLS-2$ |
| success = true; |
| justCreated = true; |
| } catch (Exception e) { |
| UpdateCore.warn("Unable to create private Marker at:" + file, e); //$NON-NLS-1$ |
| } finally { |
| try { |
| if (outWriter != null) |
| outWriter.close(); |
| } catch (IOException e1) { |
| } |
| try { |
| if (out != null) |
| out.close(); |
| } catch (IOException e2) { |
| } |
| } |
| } |
| } |
| } |
| return success; |
| } |
| |
| |
| /* |
| * Returns true if the directory of the Site contains |
| * .eclipseextension |
| */ |
| public boolean isExtensionSite() { |
| return containsMarker(EXTENSION_SITE_MARKER); |
| } |
| |
| /* |
| * Returns true if the directory of the Site contains |
| * .eclipseextension |
| */ |
| public boolean isProductSite() { |
| return containsMarker(PRODUCT_SITE_MARKER); |
| } |
| |
| /* |
| * Returns true if the directory of the Site contains |
| * .eclipseextension |
| */ |
| public boolean isPrivateSite() { |
| return isExtensionSite(); |
| } |
| |
| /* |
| * |
| */ |
| private boolean containsMarker(String marker) { |
| ISite site = getSite(); |
| if (site == null) { |
| UpdateCore.warn("Contains Markers:The site is null"); //$NON-NLS-1$ |
| return false; |
| } |
| |
| URL url = site.getURL(); |
| if (url == null) { |
| UpdateCore.warn("Contains Markers:Site URL is null"); //$NON-NLS-1$ |
| return false; |
| } |
| if (!"file".equalsIgnoreCase(url.getProtocol())) { //$NON-NLS-1$ |
| UpdateCore.warn("Contains Markers:Non file protocol"); //$NON-NLS-1$ |
| return false; |
| } |
| File file = new File(url.getFile()); |
| if (!file.exists()) { |
| UpdateCore.warn("Contains Markers:The site doesn't exist:" + file); //$NON-NLS-1$ |
| return false; |
| } |
| File extension = new File(file, marker); |
| if (!extension.exists()) { |
| UpdateCore.warn("Contains Markers:The extensionfile does not exist:" + extension); //$NON-NLS-1$ |
| return false; |
| } |
| return true; |
| } |
| |
| /* |
| * Returns true if the Site is already natively linked |
| */ |
| public boolean isNativelyLinked() throws CoreException { |
| String platformString = getPlatformURLString(); |
| if (platformString == null) { |
| UpdateCore.warn("Unable to retrieve platformString"); //$NON-NLS-1$ |
| return false; |
| } |
| |
| URL siteURL = null; |
| try { |
| // check if the site exists and is updatable |
| // update configSite |
| URL urlToCheck = new URL(platformString); |
| IPlatformConfiguration runtimeConfig = ConfiguratorUtils.getCurrentPlatformConfiguration(); |
| IPlatformConfiguration.ISiteEntry entry = runtimeConfig.findConfiguredSite(urlToCheck); |
| if (entry != null) { |
| return entry.isNativelyLinked(); |
| } else { |
| UpdateCore.warn("Unable to retrieve site:" + platformString + " from platform."); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| // check by comparing URLs |
| IPlatformConfiguration.ISiteEntry[] sites = runtimeConfig.getConfiguredSites(); |
| for (int i = 0; i < sites.length; i++) { |
| siteURL = sites[i].getURL(); |
| URL resolvedURL = Platform.resolve(siteURL); |
| if (UpdateManagerUtils.sameURL(resolvedURL, urlToCheck)) |
| return true; |
| } |
| } catch (MalformedURLException e) { |
| String msg = Policy.bind("ConfiguredSite.UnableResolveURL", platformString); //$NON-NLS-1$ |
| throw Utilities.newCoreException(msg, e); |
| } catch (IOException e) { |
| String msg = Policy.bind("ConfiguredSite.UnableToAccessSite", new Object[] { siteURL }); //$NON-NLS-1$ |
| throw Utilities.newCoreException(msg, e); |
| } |
| |
| return false; |
| } |
| |
| /* |
| * we have to check that no configured/enable parent include this feature |
| */ |
| private boolean validateNoConfiguredParents(IFeature feature) throws CoreException { |
| if (feature == null) { |
| UpdateCore.warn("ConfigurationPolicy: validate Feature is null"); //$NON-NLS-1$ |
| return true; |
| } |
| |
| IFeatureReference[] parents = UpdateManagerUtils.getParentFeatures(feature, getConfiguredFeatures(), false); |
| return (parents.length == 0); |
| } |
| |
| } |