blob: cb977138be63ad07ed57fdf9b1b3a4abb1be15ef [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2015 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.core.tests.harness;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.core.runtime.IExtensionDelta;
import org.eclipse.core.runtime.IRegistryChangeEvent;
import org.eclipse.core.runtime.IRegistryChangeListener;
import org.eclipse.core.runtime.Platform;
/**
* Allows test cases to wait for event notification.
*/
public class TestRegistryChangeListener implements IRegistryChangeListener {
/**
* Indicates that no matching even has been received
*/
public static final int NO_EVENT = -1;
private List<IRegistryChangeEvent> events = new LinkedList<>();
private List<Integer> simpleEvents = new LinkedList<>();
private String xpNamespace;
private String xpId;
private String extNamespace;
private String extId;
/**
* Creates a new listener. The parameters allow filtering events based on extension point/extension's
* namespaces/ids.
*/
public TestRegistryChangeListener(String xpNamespace, String xpId, String extNamespace, String extId) {
if (xpId != null && xpNamespace == null) {
throw new IllegalArgumentException();
}
if (extId != null && extNamespace == null) {
throw new IllegalArgumentException();
}
if (xpId == null && extId != null) {
throw new IllegalArgumentException();
}
this.xpNamespace = xpNamespace;
this.xpId = xpId;
this.extNamespace = extNamespace;
this.extId = extId;
}
/**
* @see IRegistryChangeListener#registryChanged
*/
@Override
public synchronized void registryChanged(IRegistryChangeEvent newEvent) {
IExtensionDelta delta = null;
if (xpId != null) {
if (extId != null) {
delta = newEvent.getExtensionDelta(xpNamespace, xpId, extNamespace + '.' + extId);
} else {
IExtensionDelta[] deltas = newEvent.getExtensionDeltas(xpNamespace, xpId);
if (deltas.length != 0) {
delta = deltas[0];
}
}
}
if (delta == null) {
return; // this is not the event we are interested in
}
events.add(newEvent);
simpleEvents.add(Integer.valueOf(delta.getKind()));
notifyAll();
}
/**
* Returns the first event that is received, blocking for at most <code>timeout</code> milliseconds.
* Returns <code>null</code> if a event was not received for the time allowed.
* <p>
* Note: registry elements referred to by the event returned from this method might be
* invalid. Method is preserved for backward compatibility, but users are strongly encouraged
* to switch to {@link #eventTypeReceived(long)}.
* </p>
*
* @param timeout the maximum time to wait in milliseconds. If zero, this method will
* block until an event is received
* @return the first event received, or <code>null</code> if none was received
*
* @deprecated use {@link #eventTypeReceived(long)} instead
*/
public synchronized IRegistryChangeEvent getEvent(long timeout) {
if (!events.isEmpty()) {
return events.remove(0);
}
try {
wait(timeout);
} catch (InterruptedException e) {
// who cares?
}
return events.isEmpty() ? null : (IRegistryChangeEvent) events.remove(0);
}
/**
* Wait for a registry event that fits IDs specified in the constructor, blocking for
* at most <code>timeout</code> milliseconds.
* <p>
* Note: do NOT mix calls to {@link #getEvent(long)} with calls to this method in the same
* instance of this class.
* </p>
*
* @param timeout the maximum time to wait in milliseconds. If zero, this method will
* block until an event is received
* @return event type
*
* @since 3.4
*/
public synchronized int eventTypeReceived(long timeout) {
long start = System.currentTimeMillis();
while (simpleEvents.isEmpty()) {
try {
long sleepTime = timeout - (System.currentTimeMillis()-start);
if (sleepTime <= 0) {
break;
}
wait(sleepTime);
} catch (InterruptedException e) {
// who cares?
}
}
return simpleEvents.isEmpty() ? NO_EVENT : simpleEvents.remove(0).intValue();
}
/**
* Wait for a registry event that fits IDs specified in the constructor, blocking for
* at most <code>timeout</code> milliseconds.
* <p>
* Note: do NOT mix calls to {@link #getEvent(long)} with calls to this method in the same
* instance of this class.
* </p>
*
* @param timeout the maximum time to wait in milliseconds. If zero, this method will
* block until an event is received
* @return <code>true</code> if event was received; <code>false</code> otherwise
*
* @since 3.4
*/
public synchronized boolean eventReceived(long timeout) {
int notified = eventTypeReceived(timeout);
return notified != TestRegistryChangeListener.NO_EVENT;
}
public void register() {
Platform.getExtensionRegistry().addRegistryChangeListener(this, xpNamespace);
}
public void unregister() {
Platform.getExtensionRegistry().removeRegistryChangeListener(this);
}
public synchronized void reset() {
events.clear();
simpleEvents.clear();
}
}