/******************************************************************************* | |
* Copyright (c) 2000, 2004 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.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(Policy.bind("InstallHandler.error", feature.getLabel()), originalException); //$NON-NLS-1$ | |
if (newException != null) | |
throw Utilities.newCoreException(Policy.bind("InstallHandler.error", feature.getLabel()), newException); //$NON-NLS-1$ | |
} | |
} | |
/** | |
* 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(Policy.bind("InstallHandler.error", feature.getLabel()), originalException); //$NON-NLS-1$ | |
if (newException != null) | |
throw Utilities.newCoreException(Policy.bind("InstallHandler.error", feature.getLabel()), newException); //$NON-NLS-1$ | |
} | |
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 { | |
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 "/" | |
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()]); | |
} | |
} |