| /******************************************************************************* |
| * Copyright (c) 2000, 2006 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 java.io.*; |
| import java.net.*; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.core.runtime.*; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.update.configuration.*; |
| import org.eclipse.update.configurator.*; |
| import org.eclipse.update.core.*; |
| import org.eclipse.update.core.model.*; |
| import org.eclipse.update.internal.model.*; |
| |
| /** |
| * |
| */ |
| public class ConfigurationPolicy extends ConfigurationPolicyModel { |
| |
| /** |
| * Constructor for ConfigurationPolicyModel. |
| */ |
| public ConfigurationPolicy() { |
| } |
| |
| /** |
| * Copy Constructor for ConfigurationPolicyModel. |
| */ |
| public ConfigurationPolicy(ConfigurationPolicy configPolicy) { |
| super(); |
| setPolicy(configPolicy.getPolicy()); |
| setConfiguredFeatureReferences(configPolicy.getConfiguredFeatures()); |
| setUnconfiguredFeatureReferences(configPolicy.getUnconfiguredFeatures()); |
| setConfiguredSiteModel(configPolicy.getConfiguredSiteModel()); |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| private boolean isUnconfigured(IFeatureReference featureReference) { |
| |
| if (featureReference == null) |
| return false; |
| |
| // returns true if the feature is part of the configured list |
| IFeatureReference[] refs = getUnconfiguredFeatures(); |
| for (int i = 0; i < refs.length; i++) { |
| if (featureReference.equals(refs[i])) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public boolean isConfigured(IFeatureReference featureReference) { |
| |
| if (featureReference == null) |
| return false; |
| |
| // returns true if the feature is part of the configured list |
| IFeatureReference[] refs = getConfiguredFeatures(); |
| for (int i = 0; i < refs.length; i++) { |
| if (featureReference.equals(refs[i])) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * adds the feature to the list of features if the policy is USER_INCLUDE |
| */ |
| public void configure(IFeatureReference featureReference, boolean callInstallHandler, boolean createActivity) throws CoreException { |
| |
| if (isConfigured(featureReference)) // already configured |
| return; |
| |
| if (featureReference == null) { |
| UpdateCore.warn("The feature reference to configure is null"); //$NON-NLS-1$ |
| return; |
| } |
| |
| IFeature feature = null; |
| try { |
| feature = featureReference.getFeature(null); |
| } catch (CoreException e) { |
| if (!UpdateManagerUtils.isOptional(featureReference)) { |
| URL url = featureReference.getURL(); |
| String urlString = (url != null) ? url.toExternalForm() : "<no feature reference url>"; //$NON-NLS-1$ |
| UpdateCore.warn("Error retrieving feature:" + urlString, e); //$NON-NLS-1$ |
| return; |
| } |
| } |
| if (feature == null) { |
| URL url = featureReference.getURL(); |
| String urlString = (url != null) ? url.toExternalForm() : "<no feature reference url>"; //$NON-NLS-1$ |
| UpdateCore.warn("The feature to unconfigure is null: feature reference is:" + urlString); //$NON-NLS-1$ |
| } |
| |
| // Setup optional install handler |
| InstallHandlerProxy handler = null; |
| if (callInstallHandler && feature.getInstallHandlerEntry() != null) |
| handler = new InstallHandlerProxy(IInstallHandler.HANDLER_ACTION_CONFIGURE, feature, feature.getInstallHandlerEntry(), null); |
| boolean success = false; |
| Throwable originalException = null; |
| |
| // do the configure action |
| try { |
| if (handler != null) |
| handler.configureInitiated(); |
| |
| ConfigurationActivity activity = null; |
| if (createActivity) { |
| activity = new ConfigurationActivity(IActivity.ACTION_CONFIGURE); |
| activity.setLabel(feature.getVersionedIdentifier().toString()); |
| activity.setDate(new Date()); |
| } |
| |
| addConfiguredFeatureReference((FeatureReferenceModel) featureReference); |
| |
| // everything done ok |
| if (activity != null) { |
| InstallConfiguration installConfig = (InstallConfiguration) SiteManager.getLocalSite().getCurrentConfiguration(); |
| activity.setStatus(IActivity.STATUS_OK); |
| installConfig.addActivity(activity); |
| } |
| |
| if (handler != null) |
| handler.completeConfigure(); |
| |
| success = true; |
| } catch (Throwable t) { |
| originalException = t; |
| } finally { |
| Throwable newException = null; |
| try { |
| if (handler != null) |
| handler.configureCompleted(success); |
| } catch (Throwable t) { |
| newException = t; |
| } |
| if (originalException != null) // original exception wins |
| throw Utilities.newCoreException(NLS.bind(Messages.InstallHandler_error, (new String[] { feature.getLabel() })), originalException); |
| if (newException != null) |
| throw Utilities.newCoreException(NLS.bind(Messages.InstallHandler_error, (new String[] { feature.getLabel() })), newException); |
| } |
| } |
| |
| /** |
| * check if the plugins to unconfigure are required by other configured feature and |
| * adds the feature to the list of unconfigured features |
| */ |
| public boolean unconfigure(IFeatureReference featureReference, boolean callInstallHandler, boolean createActivity) throws CoreException { |
| |
| if (isUnconfigured(featureReference)) { |
| UpdateCore.warn("Feature already unconfigured"); //$NON-NLS-1$ |
| return true; |
| } |
| |
| if (featureReference == null) { |
| UpdateCore.warn("The feature reference to unconfigure is null"); //$NON-NLS-1$ |
| return false; |
| } |
| |
| IFeature feature = null; |
| try { |
| feature = featureReference.getFeature(null); |
| } catch (CoreException e) { |
| if (!UpdateManagerUtils.isOptional(featureReference)) { |
| URL url = featureReference.getURL(); |
| String urlString = (url != null) ? url.toExternalForm() : "<no feature reference url>"; //$NON-NLS-1$ |
| UpdateCore.warn("Error retrieving feature:" + urlString, e); //$NON-NLS-1$ |
| return false; |
| } |
| } |
| |
| if (feature == null) { |
| URL url = featureReference.getURL(); |
| String urlString = (url != null) ? url.toExternalForm() : "<no feature reference url>"; //$NON-NLS-1$ |
| UpdateCore.warn("The feature to unconfigure is null: feature reference is:" + urlString); //$NON-NLS-1$ |
| return false; |
| } |
| |
| // Setup optional install handler |
| InstallHandlerProxy handler = null; |
| if (callInstallHandler && feature.getInstallHandlerEntry() != null) { |
| handler = new InstallHandlerProxy(IInstallHandler.HANDLER_ACTION_UNCONFIGURE, feature, feature.getInstallHandlerEntry(), null); |
| } |
| |
| boolean success = false; |
| Throwable originalException = null; |
| |
| // do the unconfigure action |
| try { |
| |
| ConfigurationActivity activity = null; |
| if (createActivity) { |
| activity = new ConfigurationActivity(IActivity.ACTION_UNCONFIGURE); |
| activity.setLabel(feature.getVersionedIdentifier().toString()); |
| activity.setDate(new Date()); |
| } |
| |
| InstallConfiguration installConfig = null; |
| |
| // only ask for install config is activity created. |
| // prevents loops during reconciliation |
| if (activity != null) |
| installConfig = ((InstallConfiguration) SiteManager.getLocalSite().getCurrentConfiguration()); |
| |
| // Allow unconfigure if the feature is optional from all the parents |
| // or if the feature is mandatory and non of its parent are configured |
| // removed, not a core issue (so deep down) |
| //if (validateNoConfiguredParents(feature)) { |
| if (handler != null) |
| handler.unconfigureInitiated(); |
| addUnconfiguredFeatureReference((FeatureReferenceModel) featureReference); |
| if (handler != null) |
| handler.completeUnconfigure(); |
| |
| // everything done ok |
| if (activity != null) { |
| activity.setStatus(IActivity.STATUS_OK); |
| installConfig.addActivity(activity); |
| } |
| success = true; |
| //} else { |
| // if (activity != null) { |
| // activity.setStatus(IActivity.STATUS_NOK); |
| // installConfig.addActivityModel((ConfigurationActivityModel) activity); |
| // } |
| //} |
| } catch (Throwable t) { |
| originalException = t; |
| } finally { |
| Throwable newException = null; |
| try { |
| if (handler != null) |
| handler.unconfigureCompleted(success); |
| } catch (Throwable t) { |
| newException = t; |
| } |
| if (originalException != null) // original exception wins |
| throw Utilities.newCoreException(NLS.bind(Messages.InstallHandler_error, (new String[] { feature.getLabel() })), originalException); |
| if (newException != null) |
| throw Utilities.newCoreException(NLS.bind(Messages.InstallHandler_error, (new String[] { feature.getLabel() })), newException); |
| } |
| |
| if (!success) { |
| 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 success; |
| } |
| |
| /** |
| * Calculates the plugin list for the policy. For "INCLUDE" policy, this |
| * corresponds to the plugins for configured features. For "EXCLUDE" |
| * policy, this corresponds to the plugins for unconfigured features that |
| * are not referenced by any configured features. |
| */ |
| public String[] getPluginPath(ISite site) throws CoreException { |
| // TODO we may need to exclude patched plugins here, but this should be good enough for now |
| if (getPolicy() == IPlatformConfiguration.ISitePolicy.MANAGED_ONLY) |
| return new String[0]; |
| |
| String[] pluginPaths; |
| // Note: Since 3.0M7 we leave patched features configured, |
| // and take this into account when computing configured plugins |
| // all unconfigured features. Note that patched features are still |
| // configured |
| IFeatureReference[] unconfiguredFeatures = getUnconfiguredFeatures(); |
| // all configured features, including patches and patched features |
| IFeatureReference[] configuredFeatures = getConfiguredFeatures(); |
| if (!isEnabled()) { |
| if (getPolicy() == IPlatformConfiguration.ISitePolicy.USER_INCLUDE) { |
| // disabled site, INCLUDE policy |
| pluginPaths = new String[0]; |
| } else { |
| // disabled site, EXCLUDE policy |
| pluginPaths = getAllKnownPluginStrings(site, |
| configuredFeatures, unconfiguredFeatures); |
| } |
| } else { |
| // PatchedFeatures (may have no patches) with corresponding patches |
| PatchedFeature[] patchedFeatures = buildPatchedFeatures(configuredFeatures); |
| if (getPolicy() == IPlatformConfiguration.ISitePolicy.USER_INCLUDE) { |
| // enabled site, INCLUDE policy |
| pluginPaths = getConfiguredPluginStrings(site, patchedFeatures); |
| } else { |
| // enabled site, EXCLUDE policy - the usual scenario for local |
| // site. |
| // return all known MINUS configured plugins |
| pluginPaths = subtract(getAllKnownPluginStrings(site, |
| configuredFeatures, unconfiguredFeatures), |
| getConfiguredPluginStrings(site, patchedFeatures)); |
| } |
| } |
| //TRACE |
| if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_RECONCILER) { |
| UpdateCore |
| .debug("GetPluginPath for: " //$NON-NLS-1$ |
| + ((site == null) ? "<No site>" : site.getURL() //$NON-NLS-1$ |
| .toString())); |
| for (int i = 0; i < pluginPaths.length; i++) { |
| UpdateCore.debug("To write:" + pluginPaths[i]); //$NON-NLS-1$ |
| } |
| } |
| return pluginPaths; |
| } |
| |
| /** |
| * Obtains PatchedFeatures - non patch features with corresponding patches if any |
| * |
| * @param features |
| * array of features to operate with |
| * @return Patches |
| */ |
| private PatchedFeature[] buildPatchedFeatures(IFeatureReference[] features) { |
| // PatchedFeatures by VersionedIdentifier |
| Map map = new HashMap(); |
| // Create a map of features (not patches) |
| for (int f = 0; f < features.length; f++) { |
| IFeatureReference featureRef = features[f]; |
| try { |
| if(featureRef.isPatch()){ |
| continue; |
| } |
| VersionedIdentifier vi = featureRef.getVersionedIdentifier(); |
| map.put(vi, new PatchedFeature(features[f])); |
| } catch (CoreException e) { |
| UpdateCore.warn(null, e); |
| } |
| } |
| // attach patches to features |
| for (int f = 0; f < features.length; f++) { |
| IFeatureReference patchCandidate = features[f]; |
| try { |
| IFeature feature = patchCandidate.getFeature(null); |
| IImport[] imports = feature.getImports(); |
| for (int i = 0; i < imports.length; i++) { |
| IImport oneImport = imports[i]; |
| if (!oneImport.isPatch()) |
| continue; |
| // it is a patch for |
| VersionedIdentifier patchedIdentifier = |
| oneImport.getVersionedIdentifier(); |
| PatchedFeature pf=(PatchedFeature) map.get(patchedIdentifier); |
| if (pf!=null) { |
| pf.addPatch(patchCandidate); |
| } else { |
| // patched feature not enabled |
| } |
| } |
| } catch (CoreException e) { |
| UpdateCore.warn(null, e); |
| } |
| } |
| Collection patchedFeatures=map.values(); |
| return (PatchedFeature[])patchedFeatures.toArray(new PatchedFeature[patchedFeatures.size()]); |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public IFeatureReference[] getConfiguredFeatures() { |
| FeatureReferenceModel[] result = getConfiguredFeaturesModel(); |
| if (result.length == 0) |
| return new IFeatureReference[0]; |
| else |
| return (IFeatureReference[]) result; |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public IFeatureReference[] getUnconfiguredFeatures() { |
| FeatureReferenceModel[] result = getUnconfiguredFeaturesModel(); |
| if (result.length == 0) |
| return new IFeatureReference[0]; |
| else |
| return (IFeatureReference[]) result; |
| } |
| |
| /** |
| * Gets the configuredSite. |
| * @return Returns a IConfiguredSite |
| */ |
| public IConfiguredSite getConfiguredSite() { |
| return (IConfiguredSite) getConfiguredSiteModel(); |
| } |
| |
| /** |
| * removes a feature reference |
| */ |
| public void removeFeatureReference(IFeatureReference featureRef) { |
| if (featureRef instanceof FeatureReferenceModel) { |
| removeFeatureReference((FeatureReferenceModel) featureRef); |
| } |
| } |
| |
| /** |
| * @return an array of plugin path for the array of feature reference. For |
| * features that have patches, plugin path will |
| * point to plugin with the same ID provided by the patch if it |
| * exists. Each plugin path only appears once [bug 21750] |
| */ |
| private String[] getConfiguredPluginStrings(ISite site, PatchedFeature[] features) throws CoreException { |
| if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_CONFIGURATION){ |
| UpdateCore.warn("CONFIGURED PLUGINS"); //$NON-NLS-1$ |
| } |
| |
| // Use set to eliminate plugins with same ID and version. |
| // Different versions of plugins with same ID are allowed if coming from different features |
| Set featurePlugins = new HashSet(); |
| for (int i = 0; i < features.length; i++) { |
| FeaturePlugin[] plugins = features[i].getPlugins(); |
| featurePlugins.addAll(Arrays.asList(plugins)); |
| } |
| Set pluginStrings = getPluginStrings(site, (FeaturePlugin[]) featurePlugins.toArray(new FeaturePlugin[featurePlugins.size()])); |
| return (String[]) pluginStrings.toArray(new String[pluginStrings.size()]); |
| } |
| /** |
| * @return an array of plugin path for every plugin in known features |
| */ |
| private String[] getAllKnownPluginStrings(ISite site, IFeatureReference[] configured,IFeatureReference[] unconfigured) throws CoreException { |
| if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_CONFIGURATION){ |
| UpdateCore.warn("ALL PLUGINS"); //$NON-NLS-1$ |
| } |
| // Add features, patched features, or patches |
| IFeatureReference[] all=new IFeatureReference[configured.length+unconfigured.length]; |
| System.arraycopy(configured, 0, all, 0, configured.length); |
| System.arraycopy(unconfigured, 0, all, configured.length, unconfigured.length); |
| // |
| Set patchedPlugins = new HashSet(); |
| for (int i=0; i< all.length; i++) { |
| try { |
| IFeature feature = all[i].getFeature(null); |
| if (feature == null) { |
| UpdateCore.warn("Null Feature", new Exception()); //$NON-NLS-1$ |
| continue; |
| } |
| |
| IPluginEntry[] entries = feature.getPluginEntries(); |
| // add every plugin to the map |
| for (int entr = 0; entr < entries.length; entr++) { |
| patchedPlugins.add(new FeaturePlugin(entries[entr], feature)); |
| } |
| |
| } catch (CoreException e) { |
| UpdateCore.warn(null, e); |
| } |
| } |
| Set pluginStrings = getPluginStrings(site, (FeaturePlugin[])patchedPlugins.toArray(new FeaturePlugin[patchedPlugins.size()])); |
| return (String[]) pluginStrings.toArray(new String[pluginStrings.size()]); |
| } |
| /** |
| * @param site |
| * @param plugins[] |
| * @return valid string pointing to plugins in given features |
| * @throws CoreException |
| */ |
| private Set getPluginStrings(ISite site, FeaturePlugin[] plugins) throws CoreException { |
| Set pluginStrings=new HashSet(); |
| for (int i=0; i< plugins.length; i++) { |
| IPluginEntry entry = plugins[i].getEntry(); |
| IFeature feature=plugins[i].getFeature(); |
| |
| // obtain the path of the plugin directories on the site |
| ContentReference[] featureContentReference = null; |
| try { |
| featureContentReference = feature.getFeatureContentProvider().getPluginEntryArchiveReferences(entry, null /*IProgressMonitor*/ |
| ); |
| } catch (CoreException e) { |
| UpdateCore.warn(null, e); |
| } |
| |
| // transform into a valid String |
| if (featureContentReference != null) { |
| for (int j = 0; j < featureContentReference.length; j++) { |
| URL url = site.getSiteContentProvider().getArchiveReference(featureContentReference[j].getIdentifier()); |
| if (url != null) { |
| // make it relative to the site |
| String path = UpdateManagerUtils.getURLAsString(site.getURL(), url); |
| // add end "/" |
| if(!path.endsWith(".jar")) //$NON-NLS-1$ |
| path += (path.endsWith(File.separator) || path.endsWith("/")) ? "" : "/"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| pluginStrings.add(path); |
| if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_CONFIGURATION) |
| UpdateCore.warn("Add plugin: " + path + " to the list"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| } |
| } |
| return pluginStrings; |
| } |
| |
| /** |
| * Obtains strings existing in the allStrings array, but not in the stringsToRemove |
| */ |
| private String[] subtract(String[] allStrings, String[] stringsToRemove) { |
| HashSet resultList = new HashSet(Arrays.asList(allStrings)); |
| resultList.removeAll(Arrays.asList(stringsToRemove)); |
| return (String[])resultList.toArray(new String[resultList.size()]); |
| } |
| } |