com.aptana.ide.update.internal.manager.P2PluginManager.java Source code

Java tutorial

Introduction

Here is the source code for com.aptana.ide.update.internal.manager.P2PluginManager.java

Source

package com.aptana.ide.update.internal.manager;

import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.equinox.internal.p2.console.ProvisioningHelper;
import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
import org.eclipse.equinox.internal.p2.ui.sdk.ProvSDKUIActivator;
import org.eclipse.equinox.internal.p2.ui.sdk.prefs.PreferenceConstants;
import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepository;
import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepositoryManager;
import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
import org.eclipse.equinox.internal.provisional.p2.director.ProfileChangeRequest;
import org.eclipse.equinox.internal.provisional.p2.director.ProvisioningPlan;
import org.eclipse.equinox.internal.provisional.p2.engine.IProfile;
import org.eclipse.equinox.internal.provisional.p2.engine.IProfileRegistry;
import org.eclipse.equinox.internal.provisional.p2.engine.ProvisioningContext;
import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.internal.provisional.p2.metadata.query.InstallableUnitQuery;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepositoryManager;
import org.eclipse.equinox.internal.provisional.p2.query.Collector;
import org.eclipse.equinox.internal.provisional.p2.ui.IProvHelpContextIds;
import org.eclipse.equinox.internal.provisional.p2.ui.ProvUI;
import org.eclipse.equinox.internal.provisional.p2.ui.actions.InstallAction;
import org.eclipse.equinox.internal.provisional.p2.ui.dialogs.InstallWizard;
import org.eclipse.equinox.internal.provisional.p2.ui.dialogs.UninstallWizard;
import org.eclipse.equinox.internal.provisional.p2.ui.model.ProfileElement;
import org.eclipse.equinox.internal.provisional.p2.ui.operations.ProvisioningUtil;
import org.eclipse.equinox.internal.provisional.p2.ui.policy.LicenseManager;
import org.eclipse.equinox.internal.provisional.p2.ui.sdk.ProvPolicies;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.osgi.service.resolver.VersionRange;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.statushandlers.StatusManager;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.Version;

import com.aptana.ide.core.IdeLog;
import com.aptana.ide.internal.update.manager.AbstractPluginManager;
import com.aptana.ide.update.P2Activator;
import com.aptana.ide.update.manager.IPlugin;
import com.aptana.ide.update.manager.Plugin;
import com.aptana.ide.update.manager.PluginManagerException;

public class P2PluginManager extends AbstractPluginManager {

    /**
     * @see com.aptana.ide.update.manager.IPluginManager#checkForUpdates(boolean)
     */
    public void checkForUpdates(boolean immediate) {
        if (!immediate) {
            ProvSDKUIActivator.getDefault().getScheduler().earlyStartup();
            return;
        }
        // Force the P2 automatic update check pref to be turned on, and force a
        // reschedule of the update check
        Preferences prefs = ProvSDKUIActivator.getDefault().getPluginPreferences();
        // Grab existing values
        boolean wasEnabled = prefs.getBoolean(PreferenceConstants.PREF_AUTO_UPDATE_ENABLED);
        String oldSchedule = prefs.getString(PreferenceConstants.PREF_AUTO_UPDATE_SCHEDULE);
        // Force new ones temporarily
        prefs.setValue(PreferenceConstants.PREF_AUTO_UPDATE_ENABLED, true);
        prefs.setValue(PreferenceConstants.PREF_AUTO_UPDATE_SCHEDULE, PreferenceConstants.PREF_UPDATE_ON_STARTUP);
        ProvSDKUIActivator.getDefault().savePluginPreferences();
        // now check for updates
        ProvSDKUIActivator.getDefault().getScheduler().earlyStartup();
        // Now revert prefs
        prefs.setValue(PreferenceConstants.PREF_AUTO_UPDATE_ENABLED, wasEnabled);
        prefs.setValue(PreferenceConstants.PREF_AUTO_UPDATE_SCHEDULE, oldSchedule);
        ProvSDKUIActivator.getDefault().savePluginPreferences();
    }

    /**
     * @see com.aptana.ide.installer.plugins.IPluginManager#install(org.eclipse.update.core.IFeatureReference[],
     *      org.eclipse.core.runtime.IProgressMonitor)
     */
    public IStatus install(IPlugin[] plugins, IProgressMonitor monitor) throws PluginManagerException {
        if (monitor == null)
            monitor = new NullProgressMonitor();
        if (monitor.isCanceled())
            return Status.CANCEL_STATUS;

        final String profileId = IProfileRegistry.SELF;
        IInstallableUnit[] toInstall = getInstallationUnits(plugins, profileId);
        if (toInstall.length <= 0) {
            throw new PluginManagerException(Messages.P2PluginManager_ERR_MSG_No_installable_units_found);
        }

        if (monitor.isCanceled())
            return Status.CANCEL_STATUS;

        final ProvisioningPlan result = getInstallationProvisioningPlan(toInstall, profileId);
        if (!validatePlan(result))
            return Status.CANCEL_STATUS;

        if (monitor.isCanceled())
            return Status.CANCEL_STATUS;

        final LicenseManager licenseManager = ProvSDKUIActivator.getDefault().getLicenseManager();
        InstallWizard wizard = new InstallWizard(profileId, toInstall, result, licenseManager);
        WizardDialog dialog = new WizardDialog(Display.getCurrent().getActiveShell(), wizard);
        dialog.create();
        PlatformUI.getWorkbench().getHelpSystem().setHelp(dialog.getShell(), IProvHelpContextIds.INSTALL_WIZARD);
        dialog.open();
        return Status.OK_STATUS;
    }

    private static IInstallableUnit[] getInstallationUnits(final IPlugin[] plugins, final String profileId)
            throws PluginManagerException {
        final List<IInstallableUnit> units = new ArrayList<IInstallableUnit>();
        IRunnableWithProgress runnable = new IRunnableWithProgress() {
            public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException

            {
                SubMonitor sub = SubMonitor.convert(monitor, plugins.length * 4);
                sub.setTaskName(Messages.P2PluginManager_Locating_selected_features_job_title);
                try {
                    for (int i = 0; i < plugins.length; i++) {
                        IPlugin plugin = plugins[i];
                        IMetadataRepositoryManager manager = (IMetadataRepositoryManager) ServiceHelper
                                .getService(P2Activator.getContext(), IMetadataRepositoryManager.class.getName());
                        IMetadataRepository repo = manager.loadRepository(plugin.getURL(),
                                new NullProgressMonitor());
                        if (repo == null) {
                            throw new ProvisionException(
                                    Messages.P2PluginManager_ERR_MSG_Metadata_repo_not_found + plugin.getURL());
                        }
                        if (!manager.isEnabled(plugin.getURL()))
                            manager.setEnabled(plugin.getURL(), true);
                        sub.worked(1);

                        IArtifactRepositoryManager artifactManager = (IArtifactRepositoryManager) ServiceHelper
                                .getService(P2Activator.getContext(), IArtifactRepositoryManager.class.getName());
                        IArtifactRepository artifactRepo = artifactManager.loadRepository(plugin.getURL(),
                                new NullProgressMonitor());
                        if (artifactRepo == null) {
                            throw new ProvisionException(
                                    Messages.P2PluginManager_ERR_MSG_Artifact_repo_not_found + plugin.getURL());
                        }
                        if (!artifactManager.isEnabled(plugin.getURL()))
                            artifactManager.setEnabled(plugin.getURL(), true);
                        sub.worked(1);

                        InstallableUnitQuery query = new InstallableUnitQuery(getFeatureGroupName(plugin),
                                VersionRange.emptyRange);
                        Collector roots = repo.query(query, new LatestIUVersionCollector(), monitor);

                        if (roots.size() <= 0) {
                            if (monitor.isCanceled())
                                return;

                            IProfile profile = ProvisioningHelper.getProfile(profileId);
                            roots = profile.query(query, roots, monitor);
                        }
                        units.addAll(roots.toCollection());
                        sub.worked(2);
                    }
                } catch (Exception e) {
                    throw new InvocationTargetException(e);
                } finally {
                    sub.done();
                }
            }
        };
        try {
            new ProgressMonitorDialog(Display.getDefault().getActiveShell()).run(true, true, runnable);
        } catch (InterruptedException e) {
            // don't report thread interruption
        } catch (InvocationTargetException e) {
            throw new PluginManagerException(Messages.ProfileModificationAction_UnexpectedError, e.getCause());
        }
        return units.toArray(new IInstallableUnit[units.size()]);
    }

    private static ProvisioningPlan getInstallationProvisioningPlan(final IInstallableUnit[] ius,
            final String profileId) {
        final ProvisioningPlan[] plan = new ProvisioningPlan[1];
        IRunnableWithProgress runnable = new IRunnableWithProgress() {
            public void run(IProgressMonitor monitor) {
                try {
                    plan[0] = InstallAction.computeProvisioningPlan(ius, profileId, monitor);
                } catch (ProvisionException e) {
                    ProvUI.handleException(e, Messages.ProfileModificationAction_UnexpectedError,
                            StatusManager.BLOCK | StatusManager.LOG);
                }
            }
        };
        try {
            new ProgressMonitorDialog(Display.getDefault().getActiveShell()).run(true, true, runnable);
        } catch (InterruptedException e) {
            // don't report thread interruption
        } catch (InvocationTargetException e) {
            ProvUI.handleException(e.getCause(), Messages.ProfileModificationAction_UnexpectedError,
                    StatusManager.BLOCK | StatusManager.LOG);
        }
        return plan[0];
    }

    private static boolean validatePlan(ProvisioningPlan plan) {
        if (plan != null) {
            // Don't validate the plan if the user cancelled
            if (plan.getStatus().getSeverity() == IStatus.CANCEL)
                return false;
            if (ProvPolicies.getDefault().getPlanValidator() != null)
                return ProvPolicies.getDefault().getPlanValidator().continueWorkingWithPlan(plan,
                        Display.getDefault().getActiveShell());
            if (plan.getStatus().isOK())
                return true;
            ProvUI.reportStatus(plan.getStatus(), StatusManager.BLOCK | StatusManager.LOG);
            return false;
        }
        return false;
    }

    /**
     * @see com.aptana.ide.installer.plugins.IPluginManager#uninstall(org.eclipse.update.core.IFeatureReference,
     *      org.eclipse.core.runtime.IProgressMonitor)
     */
    public IStatus uninstall(IPlugin plugin, IProgressMonitor monitor) throws PluginManagerException {
        if (monitor.isCanceled())
            return Status.CANCEL_STATUS;

        final String profileId = IProfileRegistry.SELF;
        Collector roots = new Collector();
        try {
            InstallableUnitQuery query = new InstallableUnitQuery(getFeatureGroupName(plugin),
                    new Version(plugin.getVersion()));
            ProfileElement element = new ProfileElement(profileId);
            roots = element.getQueryable().query(query, roots, monitor);
        } catch (CoreException e) {
            IdeLog.logError(P2Activator.getDefault(), e.getMessage(), e);
        }

        if (roots == null || roots.size() <= 0) {
            throw new PluginManagerException(Messages.P2PluginManager_ERR_MSG_No_installable_units_found);
        }
        IInstallableUnit[] ius = (IInstallableUnit[]) roots.toArray(IInstallableUnit.class);

        if (monitor.isCanceled())
            return Status.CANCEL_STATUS;

        ProvisioningPlan plan = getUninstallationProvisioningPlan(ius, profileId);

        if (monitor.isCanceled())
            return Status.CANCEL_STATUS;

        UninstallWizard wizard = new UninstallWizard(profileId, ius, plan);
        WizardDialog dialog = new WizardDialog(Display.getCurrent().getActiveShell(), wizard);
        dialog.create();
        PlatformUI.getWorkbench().getHelpSystem().setHelp(dialog.getShell(), IProvHelpContextIds.UNINSTALL_WIZARD);
        dialog.open();
        return Status.OK_STATUS;
    }

    /**
     * @see com.aptana.ide.update.manager.IPluginManager#addUpdateSite(java.net.URL)
     */
    public boolean addUpdateSite(URL siteURL) {
        URL[] existingMetaRepos = ProvisioningHelper.getMetadataRepositories();
        if (contains(existingMetaRepos, siteURL))
            return false;

        ProvisioningHelper.addMetadataRepository(siteURL);
        ProvisioningHelper.addArtifactRepository(siteURL);
        return true;
    }

    /**
     * @see com.aptana.ide.update.manager.IPluginManager#removeUpdateSite(java.net.URL)
     */
    public void removeUpdateSite(URL siteURL) {
        ProvisioningHelper.removeMetadataRepository(siteURL);
        ProvisioningHelper.removeArtifactRepository(siteURL);
    }

    private static String getFeatureGroupName(IPlugin plugin) throws CoreException {
        return plugin.getId() + ".feature.group"; //$NON-NLS-1$
    }

    private static ProvisioningPlan getUninstallationProvisioningPlan(final IInstallableUnit[] ius,
            final String profileId) {
        final ProvisioningPlan[] plan = new ProvisioningPlan[1];
        IRunnableWithProgress runnable = new IRunnableWithProgress() {
            public void run(IProgressMonitor monitor) {
                try {
                    ProfileChangeRequest request = ProfileChangeRequest.createByProfileId(profileId);
                    request.removeInstallableUnits(ius);
                    plan[0] = ProvisioningUtil.getProvisioningPlan(request, new ProvisioningContext(), monitor);
                } catch (ProvisionException e) {
                    ProvUI.handleException(e, Messages.ProfileModificationAction_UnexpectedError,
                            StatusManager.BLOCK | StatusManager.LOG);
                }
            }
        };
        try {
            new ProgressMonitorDialog(Display.getDefault().getActiveShell()).run(true, true, runnable);
        } catch (InterruptedException e) {
            // don't report thread interruption
        } catch (InvocationTargetException e) {
            ProvUI.handleException(e.getCause(), Messages.ProfileModificationAction_UnexpectedError,
                    StatusManager.BLOCK | StatusManager.LOG);
        }
        return plan[0];
    }

    private static boolean contains(URL[] existingMetaRepos, URL updateSiteURL) {
        if (existingMetaRepos == null)
            return false;
        for (int i = 0; i < existingMetaRepos.length; i++) {
            if (existingMetaRepos[i].equals(updateSiteURL))
                return true;
        }
        return false;
    }

    private static class LatestIUVersionCollector extends Collector {
        private Map<String, Object> uniqueIds = new HashMap<String, Object>();

        /**
         * Accepts a result that matches the query criteria.
         * 
         * @param match
         *            an object matching the query
         * @return <code>true</code> if the query should continue, or <code>false</code> to indicate the query should
         *         stop.
         */
        public boolean accept(Object match) {
            if (!(match instanceof IInstallableUnit))
                return true;
            IInstallableUnit iu = (IInstallableUnit) match;
            // Look for the latest element
            Object matchElement = uniqueIds.get(iu.getId());
            if (matchElement == null || iu.getVersion().compareTo(getIU(matchElement).getVersion()) > 0) {
                if (matchElement != null)
                    getList().remove(matchElement);

                matchElement = makeDefaultElement(iu);
                uniqueIds.put(iu.getId(), matchElement);
                return super.accept(matchElement);
            }
            return true;
        }

        private Object makeDefaultElement(IInstallableUnit iu) {
            return iu;
        }

        protected IInstallableUnit getIU(Object matchElement) {
            if (matchElement instanceof IInstallableUnit)
                return (IInstallableUnit) matchElement;
            return null;
        }
    }

    public boolean isFeatureInstalled(String id) {
        return getInstalledFeature(id) != null;
    }

    public Plugin getInstalledFeature(String id) {
        if (id == null)
            return null;

        if (!id.endsWith(FEATURE_IU_SUFFIX)) {
            id += FEATURE_IU_SUFFIX;
        }
        BundleContext context = P2Activator.getDefault().getBundle().getBundleContext();
        ServiceReference ref = context.getServiceReference(IProfileRegistry.class.getName());
        if (ref == null)
            return null;
        IProfileRegistry profileRegistry = (IProfileRegistry) context.getService(ref);
        if (profileRegistry == null)
            return null;
        IProfile profile = profileRegistry.getProfile(IProfileRegistry.SELF);
        if (profile == null) {
            IProfile[] profiles = profileRegistry.getProfiles();

            if (profiles != null && profiles.length > 0) {
                profile = profiles[0];
            }
        }
        Collector roots = profile.available(new InstallableUnitQuery(id), new Collector(),
                new NullProgressMonitor());
        if (roots == null || roots.size() == 0)
            return null;
        try {
            return toPlugin((IInstallableUnit) roots.iterator().next());
        } catch (MalformedURLException e) {
            IdeLog.logError(P2Activator.getDefault(), e.getMessage(), e);
        }
        return null;
    }

    public List<IPlugin> getInstalledPlugins() {
        BundleContext context = P2Activator.getDefault().getBundle().getBundleContext();
        ServiceReference ref = context.getServiceReference(IProfileRegistry.class.getName());
        if (ref == null)
            return Collections.emptyList();
        IProfileRegistry profileRegistry = (IProfileRegistry) context.getService(ref);
        if (profileRegistry == null)
            return Collections.emptyList();
        IProfile profile = profileRegistry.getProfile(IProfileRegistry.SELF);
        if (profile == null) {
            IProfile[] profiles = profileRegistry.getProfiles();

            if (profiles != null && profiles.length > 0) {
                profile = profiles[0];
            }
        }
        if (profile == null)
            return Collections.emptyList();
        Collector roots = profile.available(new InstallableUnitQuery("FakeId") {
            public boolean isMatch(Object object) {
                if (!(object instanceof IInstallableUnit))
                    return false;

                IInstallableUnit candidate = (IInstallableUnit) object;
                String name = candidate.getId();

                if (name == null || !name.endsWith(FEATURE_IU_SUFFIX)) // only features
                    return false;

                return true;
            }
        }, new Collector(), new NullProgressMonitor());
        IInstallableUnit[] ius = (IInstallableUnit[]) roots.toArray(IInstallableUnit.class);
        // Convert them to Plugin objects
        List<IPlugin> plugins = new ArrayList<IPlugin>();
        for (IInstallableUnit iu : ius) {
            try {
                plugins.add(toPlugin(iu));
            } catch (MalformedURLException e) {
                IdeLog.logError(P2Activator.getDefault(), e.getMessage(), e);
            }
        }
        return plugins;
    }

    public String getUpdatePreferencePageId() {
        return "org.eclipse.equinox.internal.p2.ui.sdk.AutomaticUpdatesPreferencePage"; //$NON-NLS-1$
    }

    private Plugin toPlugin(IInstallableUnit iu) throws MalformedURLException {
        String name = iu.getProperty("df_LT.featureName");
        if (name == null)
            name = iu.getProperty(IInstallableUnit.PROP_NAME);
        if (name == null)
            name = iu.getId();
        return new Plugin(stripFeatureGroup(iu.getId()), name, iu.getVersion().toString(), null,
                iu.getProperty("df_LT.description"), new URL("file:/fake/" + iu.getId()), "", "", 0, null, "",
                null);
    }

    private String stripFeatureGroup(String id) {
        if (id == null)
            return null;
        if (id.endsWith(FEATURE_IU_SUFFIX))
            return id.substring(0, id.length() - FEATURE_IU_SUFFIX.length());
        return id;
    }

    public URI[] getAllMetadataRepositories() {
        List<URI> uris = new ArrayList<URI>();
        URL[] urls = ProvisioningHelper.getMetadataRepositories();
        for (URL url : urls) {
            try {
                uris.add(url.toURI());
            } catch (Exception e) {
                // ignore
            }
        }
        return uris.toArray(new URI[0]);
    }
}