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

Java tutorial

Introduction

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

Source

/**
 * This file Copyright (c) 2005-2010 Aptana, Inc. This program is
 * dual-licensed under both the Aptana Public License and the GNU General
 * Public license. You may elect to use one or the other of these licenses.
 * 
 * This program is distributed in the hope that it will be useful, but
 * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
 * NONINFRINGEMENT. Redistribution, except as permitted by whichever of
 * the GPL or APL you select, is prohibited.
 *
 * 1. For the GPL license (GPL), you can redistribute and/or modify this
 * program under the terms of the GNU General Public License,
 * Version 3, as published by the Free Software Foundation.  You should
 * have received a copy of the GNU General Public License, Version 3 along
 * with this program; if not, write to the Free Software Foundation, Inc., 51
 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 * 
 * Aptana provides a special exception to allow redistribution of this file
 * with certain Eclipse Public Licensed code and certain additional terms
 * pursuant to Section 7 of the GPL. You may view the exception and these
 * terms on the web at http://www.aptana.com/legal/gpl/.
 * 
 * 2. For the Aptana Public License (APL), this program and the
 * accompanying materials are made available under the terms of the APL
 * v1.0 which accompanies this distribution, and is available at
 * http://www.aptana.com/legal/apl/.
 * 
 * You may view the GPL, Aptana's exception and additional terms, and the
 * APL in the file titled license.html at the root of the corresponding
 * plugin containing this source file.
 * 
 * Any modifications to this file must keep this entire header intact.
 */
package com.aptana.ide.update.internal.manager;

import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
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.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
import org.eclipse.equinox.internal.p2.ui.sdk.scheduler.AutomaticUpdatePlugin;
import org.eclipse.equinox.internal.p2.ui.sdk.scheduler.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.core.Version;
import org.eclipse.equinox.internal.provisional.p2.core.VersionRange;
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.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.repository.IRepositoryManager;
import org.eclipse.equinox.internal.provisional.p2.ui.IProvHelpContextIds;
import org.eclipse.equinox.internal.provisional.p2.ui.QueryableMetadataRepositoryManager;
import org.eclipse.equinox.internal.provisional.p2.ui.actions.UninstallAction;
import org.eclipse.equinox.internal.provisional.p2.ui.dialogs.InstallWizard;
import org.eclipse.equinox.internal.provisional.p2.ui.dialogs.ProvisioningWizardDialog;
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.Policy;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

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

@SuppressWarnings("restriction")
public class P2Eclipse35PluginManager extends AbstractPluginManager {
    public P2Eclipse35PluginManager() {
    }

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

            ProvisioningUtil.addMetadataRepository(siteURI, false);
            ProvisioningUtil.addArtifactRepository(siteURI, false);
            return true;
        } catch (Exception e) {
            // ignores the exception
        }
        return false;
    }

    /**
     * @see com.aptana.ide.update.manager.IPluginManager#removeUpdateSite(java.net.URL)
     */
    public void removeUpdateSite(URL siteURL) {
        try {
            URI siteURI = siteURL.toURI();
            ProvisioningUtil.removeMetadataRepository(siteURI);
            ProvisioningUtil.removeArtifactRepository(siteURI);
        } catch (Exception e) {
            // ignores the exception
        }
    }

    /**
     * @see com.aptana.ide.update.manager.IPluginManager#checkForUpdates(boolean)
     */
    public void checkForUpdates(boolean immediate) {
        if (!immediate) {
            AutomaticUpdatePlugin.getDefault().getScheduler().earlyStartup();
            return;
        }
        // Force the P2 automatic update check pref to be turned on, and force a
        // reschedule of the update check
        IPreferenceStore prefs = AutomaticUpdatePlugin.getDefault().getPreferenceStore();
        // 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);
        AutomaticUpdatePlugin.getDefault().savePreferences();
        // now check for updates
        AutomaticUpdatePlugin.getDefault().getScheduler().earlyStartup();
        // Now revert prefs
        prefs.setValue(PreferenceConstants.PREF_AUTO_UPDATE_ENABLED, wasEnabled);
        prefs.setValue(PreferenceConstants.PREF_AUTO_UPDATE_SCHEDULE, oldSchedule);
        AutomaticUpdatePlugin.getDefault().savePreferences();
    }

    /**
     * @see com.aptana.ide.update.manager.IPluginManager#install(Plugin[], IProgressMonitor)
     */
    public IStatus install(final IPlugin[] plugins, IProgressMonitor monitor) throws PluginManagerException {
        if (monitor == null) {
            monitor = new NullProgressMonitor();
        }
        if (monitor.isCanceled()) {
            return Status.CANCEL_STATUS;
        }

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

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

        QueryableMetadataRepositoryManager queryableManager = new QueryableMetadataRepositoryManager(
                Policy.getDefault().getQueryContext(), false) {
            @Override
            protected URI[] getRepoLocations(IRepositoryManager manager) {
                URI[] result = new URI[plugins.length];
                int i = 0;
                for (IPlugin ref : plugins) {
                    try {
                        result[i++] = ref.getURL().toURI();
                    } catch (URISyntaxException e) {
                        // ignore for now
                    }
                }
                return result;
            }
        };

        InstallWizard wizard = new InstallWizard(generateNonManipulatingRepoPolicy(), profileId, toInstall, null,
                queryableManager);
        WizardDialog dialog = new ProvisioningWizardDialog(Display.getDefault().getActiveShell(), wizard);
        dialog.create();
        PlatformUI.getWorkbench().getHelpSystem().setHelp(dialog.getShell(), IProvHelpContextIds.INSTALL_WIZARD);
        dialog.open();

        return Status.OK_STATUS;
    }

    /**
     * Generates a copy of the default policy but removes the ability to manipulate repos, so that that portion of
     * Install Wizard UI doesn't show and mess up our installation process!
     * 
     * @return
     */
    private Policy generateNonManipulatingRepoPolicy() {
        Policy newPolicy = new Policy();
        newPolicy.setLicenseManager(Policy.getDefault().getLicenseManager());
        newPolicy.setPlanValidator(Policy.getDefault().getPlanValidator());
        newPolicy.setProfileChooser(Policy.getDefault().getProfileChooser());
        newPolicy.setQueryContext(Policy.getDefault().getQueryContext());
        newPolicy.setQueryProvider(Policy.getDefault().getQueryProvider());
        newPolicy.setRepositoryManipulator(null);
        return newPolicy;
    }

    /**
     * @see com.aptana.ide.update.manager.IPluginManager#uninstall(IPlugin, IProgressMonitor)
     */
    public IStatus uninstall(IPlugin plugin, IProgressMonitor monitor) throws PluginManagerException {
        if (monitor.isCanceled()) {
            return Status.CANCEL_STATUS;
        }

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

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

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

        UninstallAction action = new UninstallAction(Policy.getDefault(), new ISelectionProvider() {

            public void addSelectionChangedListener(ISelectionChangedListener listener) {
            }

            public ISelection getSelection() {
                return new StructuredSelection(ius);
            }

            public void removeSelectionChangedListener(ISelectionChangedListener listener) {
            }

            public void setSelection(ISelection selection) {
            }

        }, profileId);
        action.run();

        return Status.OK_STATUS;
    }

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

    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(P2Eclipse35Messages.P2PluginManager_Locating_selected_features_job_title);
                try {
                    for (IPlugin plugin : plugins) {
                        URI siteURL = plugin.getURL().toURI();

                        IMetadataRepositoryManager manager = (IMetadataRepositoryManager) ServiceHelper.getService(
                                P2Eclipse35Activator.getContext(), IMetadataRepositoryManager.class.getName());
                        IMetadataRepository repo = manager.loadRepository(siteURL, new NullProgressMonitor());
                        if (repo == null) {
                            throw new ProvisionException(
                                    P2Eclipse35Messages.P2PluginManager_ERR_MSG_Metadata_repo_not_found + siteURL);
                        }
                        if (!manager.isEnabled(siteURL)) {
                            manager.setEnabled(siteURL, true);
                        }
                        sub.worked(1);

                        IArtifactRepositoryManager artifactManager = (IArtifactRepositoryManager) ServiceHelper
                                .getService(P2Eclipse35Activator.getContext(),
                                        IArtifactRepositoryManager.class.getName());
                        IArtifactRepository artifactRepo = artifactManager.loadRepository(siteURL,
                                new NullProgressMonitor());
                        if (artifactRepo == null) {
                            throw new ProvisionException(
                                    P2Eclipse35Messages.P2PluginManager_ERR_MSG_Artifact_repo_not_found + siteURL);
                        }
                        if (!artifactManager.isEnabled(siteURL)) {
                            artifactManager.setEnabled(siteURL, 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 = ProvisioningUtil.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(P2Eclipse35Messages.ProfileModificationAction_UnexpectedError,
                    e.getCause());
        }
        return units.toArray(new IInstallableUnit[units.size()]);
    }

    private static String getFeatureGroupName(IPlugin plugin) throws CoreException {
        return plugin.getId() + FEATURE_IU_SUFFIX;
    }

    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) {
                    getCollection().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 IPlugin getInstalledFeature(String id) {
        if (id == null)
            return null;

        if (!id.endsWith(FEATURE_IU_SUFFIX)) {
            id += FEATURE_IU_SUFFIX;
        }
        BundleContext context = P2Eclipse35Activator.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];
            }
        }
        if (profile == null)
            return null;
        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(P2Eclipse35Activator.getDefault(), e.getMessage(), e);
        }
        return null;
    }

    public List<IPlugin> getInstalledPlugins() {
        BundleContext context = P2Eclipse35Activator.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") //$NON-NLS-1$
        {
            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(P2Eclipse35Activator.getDefault(), e.getMessage(), e);
            }
        }
        return plugins;
    }

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

    private Plugin toPlugin(IInstallableUnit iu) throws MalformedURLException {
        String name = iu.getProperty("df_LT.featureName"); //$NON-NLS-1$
        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, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
                null, "", null); //$NON-NLS-1$
    }

    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() throws PluginManagerException {
        try {
            return ProvisioningUtil.getMetadataRepositories(IRepositoryManager.REPOSITORIES_ALL);
        } catch (Exception e) {
            throw new PluginManagerException(e);
        }
    }

}