blob: 61d82adf3011a00b1a346970c1ba96a8bd76554f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2011 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.equinox.internal.p2.ui;
import java.util.EventObject;
import org.eclipse.equinox.internal.p2.core.helpers.Tracing;
import org.eclipse.equinox.internal.provisional.p2.core.eventbus.SynchronousProvisioningListener;
import org.eclipse.equinox.internal.provisional.p2.repository.RepositoryEvent;
import org.eclipse.equinox.p2.engine.IProfileEvent;
import org.eclipse.equinox.p2.repository.IRepository;
/**
* ProvisioningListener which handles event batching and other
* extensions to the provisioning event framework that are used by
* the UI.
*
* @since 3.5
*/
public abstract class ProvUIProvisioningListener implements SynchronousProvisioningListener {
public static final int PROV_EVENT_METADATA_REPOSITORY = 0x0001;
public static final int PROV_EVENT_IU = 0x0002;
public static final int PROV_EVENT_PROFILE = 0x0004;
public static final int PROV_EVENT_ARTIFACT_REPOSITORY = 0x0008;
int eventTypes = 0;
String name;
private ProvisioningOperationRunner runner;
public ProvUIProvisioningListener(String name, int eventTypes, ProvisioningOperationRunner runner) {
this.name = name;
this.eventTypes = eventTypes;
this.runner = runner;
}
@Override
public void notify(EventObject o) {
if (o instanceof RepositoryOperationBeginningEvent) {
if (Tracing.DEBUG_EVENTS_CLIENT)
Tracing.debug("Batch Eventing: Ignore Following Events. " + getReceiverString()); //$NON-NLS-1$
} else if (o instanceof RepositoryOperationEndingEvent) {
RepositoryOperationEndingEvent event = (RepositoryOperationEndingEvent) o;
if (Tracing.DEBUG_EVENTS_CLIENT)
Tracing.debug("Batch Eventing: Batch Ended. " + getReceiverString()); //$NON-NLS-1$
// A batch operation completed. Refresh.
if (runner.eventBatchCount <= 0) {
if (Tracing.DEBUG_EVENTS_CLIENT)
Tracing.debug("Batch Eventing Complete." + getReceiverString()); //$NON-NLS-1$
if (event.getEvent() == null && event.update()) {
if (Tracing.DEBUG_EVENTS_CLIENT) {
Tracing.debug("Refreshing After Batch." + getReceiverString()); //$NON-NLS-1$
}
refreshAll();
} else if (event.update()) {
if (Tracing.DEBUG_EVENTS_CLIENT)
Tracing.debug("Dispatching Last Event in Batch." + getReceiverString()); //$NON-NLS-1$
notify(event.getEvent());
} else if (Tracing.DEBUG_EVENTS_CLIENT) {
Tracing.debug("No Refresh on Batch Complete."); //$NON-NLS-1$
}
} else {
// We are still in the middle of a batch operation, but we've been notified
// about a nested batch that ended. See if it ended with a specific event.
// If it did, this means there was a user action involving a repository
// (rather than side-effect events). For example, the user might add a repo while a full
// background load is running. We want to honor that
// event. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=305478
RepositoryEvent innerEvent = event.getEvent();
if (innerEvent != null) {
handleRepositoryEvent(innerEvent);
}
}
} else if (runner.eventBatchCount > 0) {
// ignore raw events during a batch
if (Tracing.DEBUG_EVENTS_CLIENT)
Tracing.debug(name + " Ignoring: " + o.toString()); //$NON-NLS-1$
return;
} else if (o instanceof IProfileEvent && (((eventTypes & PROV_EVENT_IU) == PROV_EVENT_IU) || ((eventTypes & PROV_EVENT_PROFILE) == PROV_EVENT_PROFILE))) {
if (Tracing.DEBUG_EVENTS_CLIENT)
Tracing.debug(o.toString() + getReceiverString());
IProfileEvent event = (IProfileEvent) o;
if (event.getReason() == IProfileEvent.CHANGED) {
profileChanged(event.getProfileId());
} else if (event.getReason() == IProfileEvent.ADDED) {
profileAdded(event.getProfileId());
} else if (event.getReason() == IProfileEvent.REMOVED) {
profileRemoved(event.getProfileId());
}
} else if (o instanceof RepositoryEvent) {
if (Tracing.DEBUG_EVENTS_CLIENT)
Tracing.debug(o.toString() + getReceiverString());
handleRepositoryEvent((RepositoryEvent) o);
}
}
private String getReceiverString() {
return " -- <" + name + "> "; //$NON-NLS-1$//$NON-NLS-2$
}
private void handleRepositoryEvent(RepositoryEvent event) {
// Do not handle unless this is the type of repo that we are interested in
if ((event.getRepositoryType() == IRepository.TYPE_METADATA && (eventTypes & PROV_EVENT_METADATA_REPOSITORY) == PROV_EVENT_METADATA_REPOSITORY) || (event.getRepositoryType() == IRepository.TYPE_ARTIFACT && (eventTypes & PROV_EVENT_ARTIFACT_REPOSITORY) == PROV_EVENT_ARTIFACT_REPOSITORY)) {
if (event.getKind() == RepositoryEvent.ADDED && event.isRepositoryEnabled()) {
repositoryAdded(event);
} else if (event.getKind() == RepositoryEvent.REMOVED && event.isRepositoryEnabled()) {
repositoryRemoved(event);
} else if (event.getKind() == RepositoryEvent.DISCOVERED) {
repositoryDiscovered(event);
} else if (event.getKind() == RepositoryEvent.CHANGED) {
repositoryChanged(event);
} else if (event.getKind() == RepositoryEvent.ENABLEMENT) {
repositoryEnablement(event);
}
}
}
/**
* A repository has been added. Subclasses may override. May be called
* from a non-UI thread.
*
* @param event the RepositoryEvent describing the details
*/
protected void repositoryAdded(RepositoryEvent event) {
// Do nothing. This method is not abstract because subclasses
// may not be interested in repository events at all and should
// not have to implement it.
}
/**
* A repository has been removed. Subclasses may override. May be called
* from a non-UI thread.
*
* @param event the RepositoryEvent describing the details
*/
protected void repositoryRemoved(RepositoryEvent event) {
// Do nothing. This method is not abstract because subclasses
// may not be interested in repository events at all and should
// not have to implement it.
}
/**
* A repository has been discovered. Subclasses may override. May be called
* from a non-UI thread.
*
* @param event the RepositoryEvent describing the details
*/
protected void repositoryDiscovered(RepositoryEvent event) {
// Do nothing. This method is not abstract because subclasses
// may not be interested in repository events at all and should
// not have to implement it.
}
/**
* A repository has changed. Subclasses may override. May be called
* from a non-UI thread.
*
* @param event the RepositoryEvent describing the details
*/
protected void repositoryChanged(RepositoryEvent event) {
// Do nothing. This method is not abstract because subclasses
// may not be interested in repository events at all and should
// not have to implement it.
}
/**
* A repository's enablement state has changed. This is treated
* as repository addition or removal by default. Subclasses may
* override. May be called from a non-UI thread.
* @param event
*/
protected void repositoryEnablement(RepositoryEvent event) {
// We treat enablement of a repository as if one were added.
if (event.isRepositoryEnabled())
repositoryAdded(event);
else
repositoryRemoved(event);
}
/**
* The specified profile has changed. Subclasses may override. May be called
* from a non-UI thread.
*
* @param profileId the id of the profile that changed.
*/
protected void profileChanged(final String profileId) {
// Do nothing. This method is not abstract because subclasses
// may not be interested in profile events at all and should
// not have to implement it.
}
/**
* The specified profile has been added. Subclasses may override. May be called
* from a non-UI thread.
*
* @param profileId the id of the profile that has been added.
*/
protected void profileAdded(final String profileId) {
// Do nothing. This method is not abstract because subclasses
// may not be interested in profile events at all and should
// not have to implement it.
}
/**
* The specified profile has been removed. Subclasses may override. May be called
* from a non-UI thread.
*
* @param profileId the id of the profile that has been removed.
*/
protected void profileRemoved(final String profileId) {
// Do nothing. This method is not abstract because subclasses
// may not be interested in profile events at all and should
// not have to implement it.
}
/**
* An event requiring a complete refresh of the listener's state has
* been received. This is used, for example, when a batch change has
* completed. Subclasses may override. May be called from a non-UI
* thread.
*/
protected void refreshAll() {
// Do nothing by default.
}
public int getEventTypes() {
return eventTypes;
}
}