blob: 9582167448ccc8ea5dc22230502a43d82052d1f5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.debug.internal.core;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IDebugEventSetListener;
import org.eclipse.debug.core.IExpressionListener;
import org.eclipse.debug.core.IExpressionManager;
import org.eclipse.debug.core.IExpressionsListener;
import org.eclipse.debug.core.model.IExpression;
/**
* The expression manager manages all registered expressions
* for the debug plugin. It is instantiated by the debug plugin
* at startup.
*
* [XXX: expression persistence not yet implemented]
*
* @see IExpressionManager
*/
public class ExpressionManager implements IExpressionManager, IDebugEventSetListener {
/**
* Collection of registered expressions.
*/
private Vector fExpressions = null;
/**
* List of expression listeners
*/
private ListenerList fListeners = null;
/**
* List of (multi) expressions listeners
*/
private ListenerList fExpressionsListeners = null;
// Constants for add/remove/change notification
private static final int ADDED = 1;
private static final int CHANGED = 2;
private static final int REMOVED = 3;
/**
* @see IExpressionManager#addExpression(IExpression)
*/
public void addExpression(IExpression expression) {
addExpressions(new IExpression[]{expression});
}
/**
* @see IExpressionManager#addExpressions(IExpression[])
*/
public void addExpressions(IExpression[] expressions) {
if (fExpressions == null) {
fExpressions = new Vector(expressions.length);
}
boolean wasEmpty = fExpressions.isEmpty();
List added = new ArrayList(expressions.length);
for (int i = 0; i < expressions.length; i++) {
IExpression expression = expressions[i];
if (fExpressions.indexOf(expression) == -1) {
added.add(expression);
fExpressions.add(expression);
}
}
if (wasEmpty) {
DebugPlugin.getDefault().addDebugEventListener(this);
}
if (!added.isEmpty()) {
fireUpdate((IExpression[])added.toArray(new IExpression[added.size()]), ADDED);
}
}
/**
* @see IExpressionManager#getExpressions()
*/
public IExpression[] getExpressions() {
if (fExpressions == null) {
return new IExpression[0];
}
IExpression[] temp= new IExpression[fExpressions.size()];
fExpressions.copyInto(temp);
return temp;
}
/**
* @see IExpressionManager#getExpressions(String)
*/
public IExpression[] getExpressions(String modelIdentifier) {
if (fExpressions == null) {
return new IExpression[0];
}
ArrayList temp= new ArrayList(fExpressions.size());
Iterator iter= fExpressions.iterator();
while (iter.hasNext()) {
IExpression expression= (IExpression) iter.next();
String id= expression.getModelIdentifier();
if (id != null && id.equals(modelIdentifier)) {
temp.add(expression);
}
}
return (IExpression[]) temp.toArray(new IExpression[temp.size()]);
}
/**
* @see IExpressionManager#removeExpression(IExpression)
*/
public void removeExpression(IExpression expression) {
removeExpressions(new IExpression[] {expression});
}
/**
* @see IExpressionManager#removeExpressions(IExpression[])
*/
public void removeExpressions(IExpression[] expressions) {
if (fExpressions == null) {
return;
}
List removed = new ArrayList(expressions.length);
for (int i = 0; i < expressions.length; i++) {
IExpression expression = expressions[i];
if (fExpressions.remove(expression)) {
removed.add(expression);
expression.dispose();
}
}
if (fExpressions.isEmpty()) {
DebugPlugin.getDefault().removeDebugEventListener(this);
}
if (!removed.isEmpty()) {
fireUpdate((IExpression[])removed.toArray(new IExpression[removed.size()]), REMOVED);
}
}
/**
* @see IExpressionManager#addExpressionListener(IExpressionListener)
*/
public void addExpressionListener(IExpressionListener listener) {
if (fListeners == null) {
fListeners = new ListenerList(2);
}
fListeners.add(listener);
}
/**
* @see IExpressionManager#removeExpressionListener(IExpressionListener)
*/
public void removeExpressionListener(IExpressionListener listener) {
if (fListeners == null) {
return;
}
fListeners.remove(listener);
}
/**
* @see IDebugEventSetListener#handleDebugEvent(DebugEvent)
*/
public void handleDebugEvents(DebugEvent[] events) {
for (int i = 0; i < events.length; i++) {
List changed = null;
DebugEvent event = events[i];
if (event.getSource() instanceof IExpression) {
switch (event.getKind()) {
case DebugEvent.CHANGE:
if (changed == null) {
changed = new ArrayList(1);
}
changed.add(event.getSource());
break;
default:
break;
}
}
if (changed != null) {
IExpression[] array = (IExpression[])changed.toArray(new IExpression[changed.size()]);
fireUpdate(array, CHANGED);
}
}
}
/**
* Notifies listeners of the adds/removes/changes
*
* @param breakpoints associated breakpoints
* @param deltas or <code>null</code>
* @param update type of change
*/
private void fireUpdate(IExpression[] expressions, int update) {
// single listeners
getExpressionNotifier().notify(expressions, update);
// multi listeners
getExpressionsNotifier().notify(expressions, update);
}
/**
* @see IExpressionManager#hasExpressions()
*/
public boolean hasExpressions() {
return fExpressions != null;
}
/**
* @see org.eclipse.debug.core.IExpressionManager#addExpressionListener(org.eclipse.debug.core.IExpressionsListener)
*/
public void addExpressionListener(IExpressionsListener listener) {
if (fExpressionsListeners == null) {
fExpressionsListeners = new ListenerList(2);
}
fExpressionsListeners.add(listener);
}
/**
* @see org.eclipse.debug.core.IExpressionManager#removeExpressionListener(org.eclipse.debug.core.IExpressionsListener)
*/
public void removeExpressionListener(IExpressionsListener listener) {
if (fExpressionsListeners == null) {
return;
}
fExpressionsListeners.remove(listener);
}
private ExpressionNotifier getExpressionNotifier() {
return new ExpressionNotifier();
}
/**
* Notifies an expression listener (single expression) in a safe runnable to
* handle exceptions.
*/
class ExpressionNotifier implements ISafeRunnable {
private IExpressionListener fListener;
private int fType;
private IExpression fExpression;
/**
* @see org.eclipse.core.runtime.ISafeRunnable#handleException(java.lang.Throwable)
*/
public void handleException(Throwable exception) {
IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, DebugCoreMessages.getString("ExpressionManager.An_exception_occurred_during_expression_change_notification._1"), exception); //$NON-NLS-1$
DebugPlugin.log(status);
}
/**
* @see org.eclipse.core.runtime.ISafeRunnable#run()
*/
public void run() throws Exception {
switch (fType) {
case ADDED:
fListener.expressionAdded(fExpression);
break;
case REMOVED:
fListener.expressionRemoved(fExpression);
break;
case CHANGED:
fListener.expressionChanged(fExpression);
break;
}
}
/**
* Notifies listeners of the add/change/remove
*
* @param expression the expression that has changed
* @param update the type of change
*/
public void notify(IExpression[] expressions, int update) {
if (fListeners != null) {
fType = update;
Object[] copiedListeners= fListeners.getListeners();
for (int i= 0; i < copiedListeners.length; i++) {
fListener = (IExpressionListener)copiedListeners[i];
for (int j = 0; j < expressions.length; j++) {
fExpression = expressions[j];
Platform.run(this);
}
}
}
fListener = null;
fExpression = null;
}
}
private ExpressionsNotifier getExpressionsNotifier() {
return new ExpressionsNotifier();
}
/**
* Notifies an expression listener (multiple expressions) in a safe runnable
* to handle exceptions.
*/
class ExpressionsNotifier implements ISafeRunnable {
private IExpressionsListener fListener;
private int fType;
private IExpression[] fExpressions;
/**
* @see org.eclipse.core.runtime.ISafeRunnable#handleException(java.lang.Throwable)
*/
public void handleException(Throwable exception) {
IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, DebugCoreMessages.getString("ExpressionManager.An_exception_occurred_during_expression_change_notification._1"), exception); //$NON-NLS-1$
DebugPlugin.log(status);
}
/**
* @see org.eclipse.core.runtime.ISafeRunnable#run()
*/
public void run() throws Exception {
switch (fType) {
case ADDED:
fListener.expressionsAdded(fExpressions);
break;
case REMOVED:
fListener.expressionsRemoved(fExpressions);
break;
case CHANGED:
fListener.expressionsChanged(fExpressions);
break;
}
}
/**
* Notifies listeners of the adds/changes/removes
*
* @param expressions the expressions that changed
* @param update the type of change
*/
public void notify(IExpression[] expressions, int update) {
if (fExpressionsListeners != null) {
fExpressions = expressions;
fType = update;
Object[] copiedListeners = fExpressionsListeners.getListeners();
for (int i= 0; i < copiedListeners.length; i++) {
fListener = (IExpressionsListener)copiedListeners[i];
Platform.run(this);
}
}
fExpressions = null;
fListener = null;
}
}
}