org.eclipse.equinox.p2.ui.ProvisioningUI.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.equinox.p2.ui.ProvisioningUI.java

Source

/*******************************************************************************
 * Copyright (c) 2009, 2011 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
 *     Sonatype, Inc. - ongoing development
 ******************************************************************************/

package org.eclipse.equinox.p2.ui;

import java.net.URI;
import java.util.Collection;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
import org.eclipse.equinox.internal.p2.core.helpers.Tracing;
import org.eclipse.equinox.internal.p2.ui.*;
import org.eclipse.equinox.internal.p2.ui.dialogs.*;
import org.eclipse.equinox.internal.provisional.p2.repository.RepositoryEvent;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.engine.IProfileRegistry;
import org.eclipse.equinox.p2.engine.ProvisioningContext;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.operations.*;
import org.eclipse.equinox.p2.repository.IRepository;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferencesUtil;

/**
 * ProvisioningUI defines the provisioning session, UI policy, and related services for a
 * provisioning UI.  
 * 
 * @since 2.0
 *
 */
public class ProvisioningUI {

    /**
     * Return the default ProvisioningUI.  
     * 
     * @return the default Provisioning UI.
     */
    public static ProvisioningUI getDefaultUI() {
        return ProvUIActivator.getDefault().getProvisioningUI();
    }

    private Policy policy;
    private ProvisioningSession session;
    private String profileId;
    private ProvisioningOperationRunner runner;

    /**
     * Creates a new instance of the provisioning user interface.
     * 
     * @param session The current provisioning session
     * @param profileId The profile that this user interface is operating on
     * @param policy The user interface policy settings to use
     */
    public ProvisioningUI(ProvisioningSession session, String profileId, Policy policy) {
        this.policy = policy;
        this.profileId = profileId;
        if (profileId == null)
            this.profileId = IProfileRegistry.SELF;
        this.session = session;
        this.runner = new ProvisioningOperationRunner(this);
        // register this UI with the agent so other UI related agent services can find it
        session.getProvisioningAgent().registerService(ProvisioningUI.class.getName(), this);
    }

    /**
     * Return the UI policy used for this instance of the UI.
     * 
     * @return the UI policy, must not be <code>null</code>
     */
    public Policy getPolicy() {
        return policy;
    }

    /**
     * Return the provisioning session that should be used to obtain
     * provisioning services.
     * 
     * @return the provisioning session, must not be <code>null</code>
     */
    public ProvisioningSession getSession() {
        return session;
    }

    /**
     * Return the license manager that should be used to remember
     * accepted user licenses.
     * @return  the license manager.  May be <code>null</code> if licenses are not
     * to be remembered.
     */
    public LicenseManager getLicenseManager() {
        return (LicenseManager) ServiceHelper.getService(ProvUIActivator.getContext(),
                LicenseManager.class.getName());
    }

    /**
     * Return the repository tracker that should be used to add, remove, and track the
     * statuses of known repositories.
     * 
     * @return the repository tracker, must not be <code>null</code>
     */
    public RepositoryTracker getRepositoryTracker() {
        return (RepositoryTracker) session.getProvisioningAgent().getService(RepositoryTracker.class.getName());
    }

    /**
     * Return the profile id that should be assumed for this ProvisioningUI if no other
     * id is otherwise specified.  Some UI classes are assigned a profile id, while others 
     * are not.  For those classes that are not assigned a current profile id, this id can
     * be used to obtain one.
     * 
     * @return a profile id
     */
    public String getProfileId() {
        return profileId;
    }

    /**
     * @since 2.2
     */
    public RelaxedUpdateInstallOperation getRelaxedUpdateOperation(ProvisioningContext context) {
        RelaxedUpdateInstallOperation luckyOperation = new RelaxedUpdateInstallOperation(getSession());
        luckyOperation.setProfileId(getProfileId());
        luckyOperation.setProvisioningContext(context);
        return luckyOperation;
    }

    /**
     * Return an install operation that describes installing the specified IInstallableUnits from the
     * provided list of repositories.
     * 
     * @param iusToInstall the IInstallableUnits to be installed
     * @param repositories the repositories to use for the operation
     * @return the install operation
     */
    public InstallOperation getInstallOperation(Collection<IInstallableUnit> iusToInstall, URI[] repositories) {
        InstallOperation op = new InstallOperation(getSession(), iusToInstall);
        op.setProfileId(getProfileId());
        op.setProvisioningContext(makeProvisioningContext(repositories));
        return op;
    }

    /**
     * Return an update operation that describes updating the specified IInstallableUnits from the
     * provided list of repositories.
     * 
     * @param iusToUpdate the IInstallableUnits to be updated
     * @param repositories the repositories to use for the operation
     * @return the update operation
     */
    public UpdateOperation getUpdateOperation(Collection<IInstallableUnit> iusToUpdate, URI[] repositories) {
        UpdateOperation op = new UpdateOperation(getSession(), iusToUpdate);
        op.setProfileId(getProfileId());
        op.setProvisioningContext(makeProvisioningContext(repositories));
        return op;
    }

    /**
     * Return an uninstall operation that describes uninstalling the specified IInstallableUnits, using
     * the supplied repositories to replace any metadata that must be retrieved for the uninstall.
     * 
     * @param iusToUninstall the IInstallableUnits to be installed
     * @param repositories the repositories to use for the operation
     * @return the uninstall operation
     */
    public UninstallOperation getUninstallOperation(Collection<IInstallableUnit> iusToUninstall,
            URI[] repositories) {
        UninstallOperation op = new UninstallOperation(getSession(), iusToUninstall);
        op.setProfileId(getProfileId());
        op.setProvisioningContext(makeProvisioningContext(repositories));
        return op;
    }

    private ProvisioningContext makeProvisioningContext(URI[] repos) {
        if (repos != null) {
            ProvisioningContext context = new ProvisioningContext(getSession().getProvisioningAgent());
            context.setMetadataRepositories(repos);
            context.setArtifactRepositories(repos);
            return context;
        }
        // look everywhere
        return new ProvisioningContext(getSession().getProvisioningAgent());
    }

    /**
     * Open an install wizard for installing the specified IInstallableUnits
     * 
     * @param initialSelections the IInstallableUnits that should be selected when the wizard opens.  May be <code>null</code>.
     * @param operation the operation describing the proposed install.  If this operation is not <code>null</code>, then a wizard showing
     * only the IInstallableUnits described in the operation will be shown.  If the operation is <code>null</code>, then a
     * wizard allowing the user to browse the repositories will be opened.
     * @param job a repository load job that is loading or has already loaded the repositories.  Can be used to pass along
     * an in-memory repository reference to the wizard.
     * 
     * @return the wizard return code
     */
    public int openInstallWizard(Collection<IInstallableUnit> initialSelections, InstallOperation operation,
            LoadMetadataRepositoryJob job) {
        if (operation == null) {
            InstallWizard wizard = new InstallWizard(this, operation, initialSelections, job);
            WizardDialog dialog = new ProvisioningWizardDialog(ProvUI.getDefaultParentShell(), wizard);
            dialog.create();
            PlatformUI.getWorkbench().getHelpSystem().setHelp(dialog.getShell(),
                    IProvHelpContextIds.INSTALL_WIZARD);
            return dialog.open();
        }
        PreselectedIUInstallWizard wizard = new PreselectedIUInstallWizard(this, operation, initialSelections, job);
        WizardDialog dialog = new ProvisioningWizardDialog(ProvUI.getDefaultParentShell(), wizard);
        dialog.create();
        PlatformUI.getWorkbench().getHelpSystem().setHelp(dialog.getShell(), IProvHelpContextIds.INSTALL_WIZARD);
        return dialog.open();
    }

    /**
     * Open an update wizard for the specified update operation.
     * 
     * @param skipSelectionsPage <code>true</code> if the selection page should be skipped so that the user is 
     * viewing the resolution results.  <code>false</code> if the update selection page should be shown first.
     * @param operation the operation describing the proposed update.  Must not be <code>null</code>.
     * @param job a repository load job that is loading or has already loaded the repositories.  Can be used to pass along
     * an in-memory repository reference to the wizard.
     * 
     * @return the wizard return code
     */
    public int openUpdateWizard(boolean skipSelectionsPage, UpdateOperation operation,
            LoadMetadataRepositoryJob job) {
        if (getPolicy().getUpdateWizardStyle() == Policy.UPDATE_STYLE_SINGLE_IUS
                && UpdateSingleIUWizard.validFor(operation)) {
            UpdateSingleIUWizard wizard = new UpdateSingleIUWizard(this, operation);
            WizardDialog dialog = new WizardDialog(ProvUI.getDefaultParentShell(), wizard);
            dialog.create();
            // TODO do we need a hook for providing custom help?  Or would this just be shown in the update browser?
            return dialog.open();
        }
        UpdateWizard wizard = new UpdateWizard(this, operation, operation.getSelectedUpdates(), job);
        wizard.setSkipSelectionsPage(skipSelectionsPage);
        WizardDialog dialog = new ProvisioningWizardDialog(ProvUI.getDefaultParentShell(), wizard);
        dialog.create();
        PlatformUI.getWorkbench().getHelpSystem().setHelp(dialog.getShell(), IProvHelpContextIds.UPDATE_WIZARD);
        if (wizard.getCurrentStatus().getSeverity() == IStatus.ERROR) {
            wizard.deselectLockedIUs();
        }
        return dialog.open();

    }

    /**
     * Open an uninstall wizard for the specified uninstall operation.
     * 
     * @param initialSelections the IInstallableUnits that should be selected when the wizard opens.  May be <code>null</code>.
     * @param operation the operation describing the proposed uninstall.  Must not be <code>null</code>.
     * @param job a repository load job that is loading or has already loaded the repositories.  Can be used to pass along
     * an in-memory repository reference to the wizard.
     * 
     * @return the wizard return code
     */
    public int openUninstallWizard(Collection<IInstallableUnit> initialSelections, UninstallOperation operation,
            LoadMetadataRepositoryJob job) {
        UninstallWizard wizard = new UninstallWizard(this, operation, initialSelections, job);
        WizardDialog dialog = new ProvisioningWizardDialog(ProvUI.getDefaultParentShell(), wizard);
        dialog.create();
        PlatformUI.getWorkbench().getHelpSystem().setHelp(dialog.getShell(), IProvHelpContextIds.UNINSTALL_WIZARD);
        return dialog.open();
    }

    /**
     * Open a UI that allows the user to manipulate the repositories.
     * @param shell the shell that should parent the UI
     */
    public void manipulateRepositories(Shell shell) {
        if (policy.getRepositoryPreferencePageId() != null) {
            PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(shell,
                    policy.getRepositoryPreferencePageId(), null, null);
            dialog.open();
        } else {
            TitleAreaDialog dialog = new TitleAreaDialog(shell) {
                RepositoryManipulationPage page;

                protected Control createDialogArea(Composite parent) {
                    page = new RepositoryManipulationPage();
                    page.setProvisioningUI(ProvisioningUI.this);
                    page.init(PlatformUI.getWorkbench());
                    page.createControl(parent);
                    this.setTitle(ProvUIMessages.RepositoryManipulationPage_Title);
                    this.setMessage(ProvUIMessages.RepositoryManipulationPage_Description);

                    Control control = page.getControl();
                    control.setLayoutData(new GridData(GridData.FILL_BOTH));
                    return page.getControl();
                }

                protected boolean isResizable() {
                    return true;
                }

                protected void okPressed() {
                    if (page.performOk())
                        super.okPressed();
                }

                protected void cancelPressed() {
                    if (page.performCancel())
                        super.cancelPressed();
                }
            };
            dialog.open();
        }
    }

    /**
     * Schedule a job to execute the supplied ProvisioningOperation.
     * 
     * @param job The operation to execute
     * @param errorStyle the flags passed to the StatusManager for error reporting
     */
    public void schedule(final ProvisioningJob job, final int errorStyle) {
        job.setUser(true);
        runner.schedule(job, errorStyle);
    }

    /**
     * Manage the supplied job as a provisioning operation.  This will allow
     * the ProvisioningUI to be aware that a provisioning job is running, as well
     * as manage the restart behavior for the job.
     * 
     * @param job the job to be managed
     * @param jobRestartPolicy an integer constant specifying whether the
     * supplied job should cause a restart of the system.  The UI Policy's
     * restart policy is used in conjunction with this constant to determine
     * what actually occurs when a job completes.
     * 
     * @see ProvisioningJob#RESTART_NONE
     * @see ProvisioningJob#RESTART_ONLY
     * @see ProvisioningJob#RESTART_OR_APPLY
     */
    public void manageJob(Job job, final int jobRestartPolicy) {
        runner.manageJob(job, jobRestartPolicy);
    }

    /**
     * Return a boolean indicating whether the receiver has scheduled any operations
     * for the profile under management.
     * 
     * @return <code>true</code> if other provisioning operations have been scheduled,
     * <code>false</code> if there are no operations scheduled.
     */
    public boolean hasScheduledOperations() {
        return getSession().hasScheduledOperationsFor(profileId);
    }

    /**
     * This method is for automated testing only.
     * @return the provisioning operation that can suppress restart for automated testing.
     * @noreference This method is not intended to be referenced by clients.
     */
    public ProvisioningOperationRunner getOperationRunner() {
        return runner;
    }

    /**
     * Signal that a repository operation is about to begin.  This allows clients to ignore intermediate
     * events until the operation is completed.  Callers are responsible for ensuring that
     * a corresponding operation ending event is signaled.
     */
    public void signalRepositoryOperationStart() {
        runner.eventBatchCount++;
        if (Tracing.DEBUG_EVENTS_CLIENT)
            Tracing.debug("Batch Count Incremented to:  " + Integer.toString(runner.eventBatchCount)); //$NON-NLS-1$
        ProvUI.getProvisioningEventBus(getSession()).publishEvent(new RepositoryOperationBeginningEvent(this));
    }

    /**
     * Signal that a repository operation has completed.
     * 
     * @param event a {@link RepositoryEvent} that describes the overall operation.  May be <code>null</code>, which
     * indicates that there was no single event that can describe the operation.  
     * @param update <code>true</code> if the event should be reflected in the UI, false if it should be ignored.
     */
    public void signalRepositoryOperationComplete(RepositoryEvent event, boolean update) {
        runner.eventBatchCount--;
        if (Tracing.DEBUG_EVENTS_CLIENT)
            Tracing.debug("Batch Count Decremented to:  " + Integer.toString(runner.eventBatchCount)); //$NON-NLS-1$
        ProvUI.getProvisioningEventBus(getSession())
                .publishEvent(new RepositoryOperationEndingEvent(this, update, event));
    }

    /**
     * Load the specified metadata repository, signaling a repository operation start event
     * before loading, and a repository operation complete event after loading.
     * 
     * @param location the location of the repository
     * @param notify <code>true</code> if the UI should be updated as a result of the load, <code>false</code> if it should not
     * @param monitor the progress monitor to be used
     * @return the repository
     * @throws ProvisionException if the repository could not be loaded
     */

    public IMetadataRepository loadMetadataRepository(URI location, boolean notify, IProgressMonitor monitor)
            throws ProvisionException {
        IMetadataRepository repo = null;
        try {
            signalRepositoryOperationStart();
            IMetadataRepositoryManager manager = ProvUI.getMetadataRepositoryManager(getSession());
            repo = manager.loadRepository(location, monitor);
            // If there is no user nickname assigned to this repo but there is a provider name, then set the nickname.
            // This will keep the name in the manager even when the repo is not loaded
            String name = manager.getRepositoryProperty(location, IRepository.PROP_NICKNAME);
            if (name == null || name.length() == 0) {
                name = repo.getName();
                if (name != null && name.length() > 0)
                    manager.setRepositoryProperty(location, IRepository.PROP_NICKNAME, name);
            }
        } catch (ProvisionException e) {
            getRepositoryTracker().reportLoadFailure(location, e);
        } finally {
            // We have no idea how many repos may have been touched as a result of loading this one.
            signalRepositoryOperationComplete(null, notify);
        }
        return repo;
    }

    /**
     * Load the specified artifact repository, signaling a repository operation start event
     * before loading, and a repository operation complete event after loading.
     * 
     * @param location the location of the repository
     * @param update <code>true</code> if the UI should be updated as a result of the load, <code>false</code> if it should not
     * @param monitor the progress monitor to be used
     * @return the repository
     * @throws ProvisionException if the repository could not be loaded
     */
    public IArtifactRepository loadArtifactRepository(URI location, boolean update, IProgressMonitor monitor)
            throws ProvisionException {
        IArtifactRepository repo;
        signalRepositoryOperationStart();
        try {
            IArtifactRepositoryManager manager = ProvUI.getArtifactRepositoryManager(getSession());
            repo = manager.loadRepository(location, monitor);

            // If there is no user nickname assigned to this repo but there is a provider name, then set the nickname.
            // This will keep the name in the manager even when the repo is not loaded
            String name = manager.getRepositoryProperty(location, IRepository.PROP_NICKNAME);
            if (name == null) {
                name = manager.getRepositoryProperty(location, IRepository.PROP_NAME);
                if (name != null)
                    manager.setRepositoryProperty(location, IRepository.PROP_NICKNAME, name);
            }
        } finally {
            // We have no idea how many repos may have been touched as a result of loading this one,
            // so we do not use a specific repository event to represent it.
            signalRepositoryOperationComplete(null, update);
        }
        return repo;
    }
}