| /******************************************************************************* |
| * Copyright (c) 2000, 2005 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.IOException; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.List; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.update.core.ContentReference; |
| import org.eclipse.update.core.IFeature; |
| import org.eclipse.update.core.IFeatureContentConsumer; |
| import org.eclipse.update.core.IFeatureFactory; |
| import org.eclipse.update.core.IFeatureReference; |
| import org.eclipse.update.core.IInstallHandler; |
| import org.eclipse.update.core.INonPluginEntry; |
| import org.eclipse.update.core.IPluginEntry; |
| import org.eclipse.update.core.ISite; |
| import org.eclipse.update.core.ISiteFeatureReference; |
| import org.eclipse.update.core.IVerificationListener; |
| import org.eclipse.update.core.IVerifier; |
| import org.eclipse.update.core.InstallMonitor; |
| import org.eclipse.update.core.Site; |
| import org.eclipse.update.core.Utilities; |
| import org.eclipse.update.core.model.ContentEntryModel; |
| import org.eclipse.update.core.model.FeatureModel; |
| import org.eclipse.update.core.model.FeatureReferenceModel; |
| import org.eclipse.update.core.model.InstallAbortedException; |
| import org.eclipse.update.internal.operations.UpdateUtils; |
| |
| |
| /** |
| * Site on the File System |
| */ |
| public class SiteFile extends Site { |
| |
| /** |
| * plugin entries |
| */ |
| private List pluginEntries = new ArrayList(0); |
| |
| /** |
| * |
| */ |
| public ISiteContentConsumer createSiteContentConsumer(IFeature targetFeature) throws CoreException { |
| SiteFileContentConsumer consumer = new SiteFileContentConsumer(targetFeature); |
| consumer.setSite(this); |
| return consumer; |
| } |
| |
| /** |
| */ |
| public String getDefaultPackagedFeatureType() { |
| return DEFAULT_INSTALLED_FEATURE_TYPE; |
| } |
| |
| /* |
| * @see ISite#install(IFeature, IVerifier, IProgressMonitor) |
| */ |
| public IFeatureReference install(IFeature sourceFeature, IVerificationListener verificationListener, IProgressMonitor progress) throws CoreException { |
| return install(sourceFeature,null,verificationListener,progress); |
| } |
| |
| /* |
| * @see ISite#install(IFeature, IVerifier, IProgressMonitor) |
| */ |
| public IFeatureReference install(IFeature sourceFeature, IFeatureReference[] optionalfeatures, IVerificationListener verificationListener, IProgressMonitor progress) throws CoreException { |
| |
| if (sourceFeature == null) |
| return null; |
| |
| // make sure we have an InstallMonitor |
| InstallMonitor monitor; |
| if (progress == null) |
| monitor = null; |
| else if (progress instanceof InstallMonitor) |
| monitor = (InstallMonitor) progress; |
| else |
| monitor = new InstallMonitor(progress); |
| |
| // create new executable feature and install source content into it |
| IFeature localFeature = createExecutableFeature(sourceFeature); |
| |
| IFeatureReference localFeatureReference = null; |
| localFeatureReference = sourceFeature.install(localFeature, optionalfeatures, verificationListener, monitor); |
| |
| return localFeatureReference; |
| } |
| |
| /* |
| * @see ISite#install(IFeature,IFeatureContentConsumer, IVerifier,IVerificationLIstener, IProgressMonitor) |
| */ |
| public IFeatureReference install(IFeature sourceFeature, IFeatureReference[] optionalfeatures, IFeatureContentConsumer parentContentConsumer, IVerifier parentVerifier, IVerificationListener verificationListener, IProgressMonitor progress) |
| throws InstallAbortedException, CoreException { |
| |
| if (sourceFeature == null) |
| return null; |
| |
| // make sure we have an InstallMonitor |
| InstallMonitor monitor; |
| if (progress == null) |
| monitor = null; |
| else if (progress instanceof InstallMonitor) |
| monitor = (InstallMonitor) progress; |
| else |
| monitor = new InstallMonitor(progress); |
| |
| // create new executable feature and install source content into it |
| IFeature localFeature = createExecutableFeature(sourceFeature); |
| parentContentConsumer.addChild(localFeature); |
| |
| // set the verifier |
| IVerifier vr = sourceFeature.getFeatureContentProvider().getVerifier(); |
| if (vr != null) |
| vr.setParent(parentVerifier); |
| |
| IFeatureReference localFeatureReference = null; |
| localFeatureReference = sourceFeature.install(localFeature, optionalfeatures, verificationListener, monitor); |
| |
| return localFeatureReference; |
| } |
| |
| /* |
| * @see ISite#remove(IFeature, IProgressMonitor) |
| */ |
| public void remove(IFeature feature, IProgressMonitor progress) throws CoreException { |
| |
| if (feature == null) { |
| UpdateCore.warn("Feature to remove is null"); //$NON-NLS-1$ |
| return; |
| } |
| |
| ErrorRecoveryLog recoveryLog = ErrorRecoveryLog.getLog(); |
| |
| // make sure we have an InstallMonitor |
| InstallMonitor monitor; |
| if (progress == null) |
| monitor = null; |
| else if (progress instanceof InstallMonitor) |
| monitor = (InstallMonitor) progress; |
| else |
| monitor = new InstallMonitor(progress); |
| |
| // Setup optional install handler |
| InstallHandlerProxy handler = new InstallHandlerProxy(IInstallHandler.HANDLER_ACTION_UNINSTALL, feature, feature.getInstallHandlerEntry(), monitor); |
| boolean success = false; |
| Throwable originalException = null; |
| |
| try { |
| |
| // start log |
| recoveryLog.open(ErrorRecoveryLog.START_REMOVE_LOG); |
| |
| aboutToRemove(feature); |
| |
| // log files have been downloaded |
| recoveryLog.append(ErrorRecoveryLog.END_ABOUT_REMOVE); |
| |
| handler.uninstallInitiated(); |
| |
| // remove the feature and the plugins if they are not used and not activated |
| // get the plugins from the feature |
| IPluginEntry[] pluginsToRemove = getPluginEntriesOnlyReferencedBy(feature); |
| |
| if (monitor != null) { |
| monitor.beginTask(Messages.SiteFile_Removing + feature.getLabel(), pluginsToRemove.length + 1); |
| } |
| |
| // remove feature reference from the site |
| ISiteFeatureReference[] featureReferences = getFeatureReferences(); |
| if (featureReferences != null) { |
| for (int indexRef = 0; indexRef < featureReferences.length; indexRef++) { |
| IFeatureReference element = featureReferences[indexRef]; |
| if (element.getVersionedIdentifier().equals(feature.getVersionedIdentifier())) { |
| removeFeatureReferenceModel((FeatureReferenceModel) element); |
| break; |
| } |
| } |
| } |
| |
| if (InstallRegistry.getInstance().get("feature_"+feature.getVersionedIdentifier()) == null) { //$NON-NLS-1$ |
| UpdateCore.log(NLS.bind(Messages.SiteFile_featureNotRemoved, (new String[] { feature.getVersionedIdentifier().toString() })), null); |
| } else { |
| // remove the feature content |
| ContentReference[] references = feature.getFeatureContentProvider().getFeatureEntryArchiveReferences(monitor); |
| for (int i = 0; i < references.length; i++) { |
| try { |
| UpdateManagerUtils.removeFromFileSystem(references[i].asFile()); |
| if (monitor != null) |
| monitor.worked(1); |
| } catch (IOException e) { |
| throw Utilities.newCoreException(NLS.bind(Messages.SiteFile_CannotRemoveFeature, (new String[] { feature.getVersionedIdentifier().getIdentifier(), getURL().toExternalForm() })), e); |
| } |
| } |
| InstallRegistry.unregisterFeature(feature); |
| } |
| |
| //finds the contentReferences for an IPluginEntry |
| // and remove it |
| for (int i = 0; i < pluginsToRemove.length; i++) { |
| remove(feature, pluginsToRemove[i], monitor); |
| } |
| |
| // remove any children feature |
| IFeatureReference[] childrenRef = feature.getIncludedFeatureReferences(); |
| for (int i = 0; i < childrenRef.length; i++) { |
| IFeature childFeature = null; |
| try { |
| childFeature = childrenRef[i].getFeature(null); |
| } catch (CoreException e) { |
| UpdateCore.warn("Unable to retrieve feature to remove for:" + childrenRef[i]); //$NON-NLS-1$ |
| } |
| // do not remove nested feature if configured (i.e. used by another configured feature) |
| if (childFeature != null && !getCurrentConfiguredSite().isConfigured(childFeature)) |
| remove(childrenRef[i].getFeature(null), monitor); |
| } |
| |
| // remove the feature from the site cache |
| removeFeatureFromCache(feature.getURL()); |
| |
| handler.completeUninstall(); |
| |
| success = true; |
| } catch (Throwable t) { |
| originalException = t; |
| } finally { |
| Throwable newException = null; |
| try { |
| if (success) { |
| // close the log |
| recoveryLog.close(ErrorRecoveryLog.END_REMOVE_LOG); |
| recoveryLog.delete(); |
| } else { |
| recoveryLog.close(ErrorRecoveryLog.END_REMOVE_LOG); |
| } |
| handler.uninstallCompleted(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); |
| } |
| } |
| |
| /** |
| * returns the download size |
| * of the feature to be installed on the site. |
| * If the site is <code>null</code> returns the maximum size |
| * |
| * If one plug-in entry has an unknown size. |
| * then the download size is unknown. |
| * |
| */ |
| public long getDownloadSizeFor(IFeature feature) { |
| long result = 0; |
| //[132029] |
| //IPluginEntry[] entriesToInstall = feature.getPluginEntries(); |
| //IPluginEntry[] siteEntries = this.getPluginEntries(); |
| //entriesToInstall = UpdateManagerUtils.diff(entriesToInstall, siteEntries); |
| //[18355] |
| //INonPluginEntry[] nonPluginEntriesToInstall = feature.getNonPluginEntries(); |
| |
| try { |
| //[132029] |
| //result = feature.getFeatureContentProvider().getDownloadSizeFor(entriesToInstall, nonPluginEntriesToInstall); |
| IFeatureReference[] children = feature.getIncludedFeatureReferences(); |
| IFeature currentFeature = null; |
| for (int i = 0; i < children.length; i++) { |
| currentFeature = UpdateUtils.getIncludedFeature(feature, children[i]); |
| if (currentFeature != null) { |
| result += getDownloadSizeFor(currentFeature); |
| if(result == ContentEntryModel.UNKNOWN_SIZE) |
| return result; |
| } |
| } |
| |
| IPluginEntry[] entriesToInstall = feature.getPluginEntries(); |
| IPluginEntry[] siteEntries = this.getPluginEntries(); |
| entriesToInstall = UpdateManagerUtils.diff(entriesToInstall, siteEntries); |
| //[18355] |
| INonPluginEntry[] nonPluginEntriesToInstall = feature.getNonPluginEntries(); |
| |
| result += feature.getFeatureContentProvider().getDownloadSizeFor(entriesToInstall, nonPluginEntriesToInstall); |
| } catch (CoreException e) { |
| UpdateCore.warn(null, e); |
| result = ContentEntryModel.UNKNOWN_SIZE; |
| } |
| return result; |
| } |
| |
| /** |
| * returns the download size |
| * of the feature to be installed on the site. |
| * If the site is <code>null</code> returns the maximum size |
| * |
| * If one plug-in entry has an unknown size. |
| * then the download size is unknown. |
| * |
| * @see ISite#getDownloadSizeFor(IFeature) |
| * |
| */ |
| public long getInstallSizeFor(IFeature feature) { |
| long result = 0; |
| |
| try { |
| List pluginsToInstall = new ArrayList(); |
| |
| // get all the plugins [17304] |
| pluginsToInstall.addAll(Arrays.asList(feature.getPluginEntries())); |
| IFeatureReference[] children = feature.getIncludedFeatureReferences(); |
| IFeature currentFeature = null; |
| for (int i = 0; i < children.length; i++) { |
| currentFeature = UpdateUtils.getIncludedFeature(feature, children[i]); |
| if (currentFeature != null) { |
| //[132029] |
| //pluginsToInstall.addAll(Arrays.asList(currentFeature.getPluginEntries())); |
| result += getInstallSizeFor(currentFeature); |
| if (result == ContentEntryModel.UNKNOWN_SIZE) |
| return result; |
| } |
| } |
| |
| IPluginEntry[] entriesToInstall = new IPluginEntry[0]; |
| if (pluginsToInstall.size() > 0) { |
| entriesToInstall = new IPluginEntry[pluginsToInstall.size()]; |
| pluginsToInstall.toArray(entriesToInstall); |
| } |
| |
| IPluginEntry[] siteEntries = this.getPluginEntries(); |
| entriesToInstall = UpdateManagerUtils.diff(entriesToInstall, siteEntries); |
| |
| //[18355] |
| INonPluginEntry[] nonPluginEntriesToInstall = feature.getNonPluginEntries(); |
| |
| //[132029] |
| //result = feature.getFeatureContentProvider().getInstallSizeFor(entriesToInstall, nonPluginEntriesToInstall); |
| result += feature.getFeatureContentProvider().getInstallSizeFor(entriesToInstall, nonPluginEntriesToInstall); |
| } catch (CoreException e) { |
| UpdateCore.warn(null, e); |
| result = ContentEntryModel.UNKNOWN_SIZE; |
| } |
| |
| return result; |
| } |
| |
| /** |
| * Adds a plugin entry |
| * Either from parsing the file system or |
| * installing a feature |
| * |
| * We cannot figure out the list of plugins by reading the Site.xml as |
| * the archives tag are optionals |
| */ |
| public void addPluginEntry(IPluginEntry pluginEntry) { |
| pluginEntries.add(pluginEntry); |
| } |
| |
| public IPluginEntry[] getPluginEntries() { |
| IPluginEntry[] result = new IPluginEntry[0]; |
| if (!(pluginEntries == null || pluginEntries.isEmpty())) { |
| result = new IPluginEntry[pluginEntries.size()]; |
| pluginEntries.toArray(result); |
| } |
| return result; |
| } |
| |
| |
| public int getPluginEntryCount() { |
| return getPluginEntries().length; |
| } |
| |
| /** |
| * |
| */ |
| private IFeature createExecutableFeature(IFeature sourceFeature) throws CoreException { |
| IFeature result = null; |
| IFeatureFactory factory = FeatureTypeFactory.getInstance().getFactory(DEFAULT_INSTALLED_FEATURE_TYPE); |
| result = factory.createFeature(/*URL*/null, this, null); |
| |
| // at least set the version identifier to be the same |
| ((FeatureModel) result).setFeatureIdentifier(sourceFeature.getVersionedIdentifier().getIdentifier()); |
| ((FeatureModel) result).setFeatureVersion(sourceFeature.getVersionedIdentifier().getVersion().toString()); |
| return result; |
| } |
| |
| /** |
| * |
| */ |
| private void remove(IFeature feature, IPluginEntry pluginEntry, InstallMonitor monitor) throws CoreException { |
| |
| if (pluginEntry == null) |
| return; |
| |
| if (InstallRegistry.getInstance().get("plugin_"+pluginEntry.getVersionedIdentifier()) == null) { //$NON-NLS-1$ |
| UpdateCore.log(NLS.bind(Messages.SiteFile_pluginNotRemoved, (new String[] { pluginEntry.getVersionedIdentifier().toString() })), null); |
| return; |
| } |
| |
| ContentReference[] references = feature.getFeatureContentProvider().getPluginEntryArchiveReferences(pluginEntry, monitor); |
| for (int i = 0; i < references.length; i++) { |
| try { |
| UpdateManagerUtils.removeFromFileSystem(references[i].asFile()); |
| if (monitor != null) |
| monitor.worked(1); |
| } catch (IOException e) { |
| throw Utilities.newCoreException(NLS.bind(Messages.SiteFile_CannotRemovePlugin, (new String[] { pluginEntry.getVersionedIdentifier().toString(), getURL().toExternalForm() })), e); |
| } |
| } |
| pluginEntries.remove(pluginEntry); |
| InstallRegistry.unregisterPlugin(pluginEntry); |
| } |
| |
| /* |
| * |
| */ |
| private void aboutToRemove(IFeature feature) throws CoreException { |
| |
| ErrorRecoveryLog recoveryLog = ErrorRecoveryLog.getLog(); |
| // if the recovery is not turned on |
| if (!ErrorRecoveryLog.RECOVERY_ON) |
| return; |
| |
| //logFeature |
| if (feature != null) { |
| |
| // log feature URL |
| ContentReference[] references = feature.getFeatureContentProvider().getFeatureEntryArchiveReferences(null); |
| for (int i = 0; i < references.length; i++) { |
| try { |
| recoveryLog.appendPath(ErrorRecoveryLog.FEATURE_ENTRY, references[i].asFile().getAbsolutePath()); |
| } catch (IOException e) { |
| String id = UpdateCore.getPlugin().getBundle().getSymbolicName(); |
| throw Utilities.newCoreException(NLS.bind(Messages.SiteFile_CannotRemoveFeature, (new String[] { feature.getVersionedIdentifier().getIdentifier(), getURL().toExternalForm() })), e); |
| } |
| } |
| // log pluginEntry URL |
| IPluginEntry[] pluginsToRemove = getPluginEntriesOnlyReferencedBy(feature); |
| for (int i = 0; i < pluginsToRemove.length; i++) { |
| references = feature.getFeatureContentProvider().getPluginEntryArchiveReferences(pluginsToRemove[i], null); |
| for (int j = 0; j < references.length; j++) { |
| try { |
| recoveryLog.appendPath(ErrorRecoveryLog.BUNDLE_JAR_ENTRY, references[j].asFile().getAbsolutePath()); |
| } catch (IOException e) { |
| throw Utilities.newCoreException(NLS.bind(Messages.SiteFile_CannotRemovePlugin, (new String[] { pluginsToRemove[i].getVersionedIdentifier().toString(), getURL().toExternalForm() })), e); |
| } |
| } |
| } |
| } |
| |
| // call recursively for each children |
| IFeatureReference[] childrenRef = feature.getIncludedFeatureReferences(); |
| IFeature childFeature = null; |
| for (int i = 0; i < childrenRef.length; i++) { |
| try { |
| childFeature = childrenRef[i].getFeature(null); |
| } catch (CoreException e) { |
| UpdateCore.warn("Unable to retrieve feature to remove for:" + childrenRef[i]); //$NON-NLS-1$ |
| } |
| aboutToRemove(childFeature); |
| } |
| } |
| |
| } |