Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarin Wright2010-09-24 15:43:15 -0400
committerDarin Wright2010-09-24 15:43:15 -0400
commit9cabab095ea19a9d134bcb3770f5f9ebbaa8a586 (patch)
tree676494670a78f64b0c1587fcae783c7750234849
parent649575043f562fc67a6f5ae5767b003414180b18 (diff)
downloadeclipse.platform.debug-9cabab095ea19a9d134bcb3770f5f9ebbaa8a586.tar.gz
eclipse.platform.debug-9cabab095ea19a9d134bcb3770f5f9ebbaa8a586.tar.xz
eclipse.platform.debug-9cabab095ea19a9d134bcb3770f5f9ebbaa8a586.zip
Bug 326063 - org.eclipse.debug.core.IExpressionManager.getExpressions() is not thread safe that it causes java.lang.ArrayIndexOutOfBoundsException
-rw-r--r--org.eclipse.debug.core/core/org/eclipse/debug/core/DebugPlugin.java3
-rw-r--r--org.eclipse.debug.core/core/org/eclipse/debug/internal/core/ExpressionManager.java195
-rw-r--r--org.eclipse.debug.core/core/org/eclipse/debug/internal/core/WatchExpression.java10
-rw-r--r--org.eclipse.debug.tests/src/org/eclipse/debug/tests/expressions/ExpressionManagerTests.java569
4 files changed, 684 insertions, 93 deletions
diff --git a/org.eclipse.debug.core/core/org/eclipse/debug/core/DebugPlugin.java b/org.eclipse.debug.core/core/org/eclipse/debug/core/DebugPlugin.java
index 5349df649..308bcfb72 100644
--- a/org.eclipse.debug.core/core/org/eclipse/debug/core/DebugPlugin.java
+++ b/org.eclipse.debug.core/core/org/eclipse/debug/core/DebugPlugin.java
@@ -641,6 +641,9 @@ public class DebugPlugin extends Plugin {
ResourcesPlugin.getWorkspace().addSaveParticipant(getUniqueIdentifier(),
new ISaveParticipant() {
public void saving(ISaveContext saveContext) throws CoreException {
+ if (fExpressionManager != null) {
+ fExpressionManager.storeWatchExpressions();
+ }
Preferences.savePreferences(DebugPlugin.getUniqueIdentifier());
}
public void rollback(ISaveContext saveContext) {}
diff --git a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/ExpressionManager.java b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/ExpressionManager.java
index 17d3b6106..5b0360c12 100644
--- a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/ExpressionManager.java
+++ b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/ExpressionManager.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 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
@@ -263,33 +263,41 @@ public class ExpressionManager extends PlatformObject implements IExpressionMana
* @see org.eclipse.debug.core.IExpressionManager#addExpressions(org.eclipse.debug.core.model.IExpression[])
*/
public void addExpressions(IExpression[] expressions) {
- if (fExpressions == null) {
- fExpressions = new Vector(expressions.length);
- }
- boolean addedWatchExpression= false;
- 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 (expression instanceof IWatchExpression) {
- addedWatchExpression= true;
- }
- }
- }
+ List added = doAdd(expressions);
if (!added.isEmpty()) {
fireUpdate((IExpression[])added.toArray(new IExpression[added.size()]), ADDED);
}
- if (addedWatchExpression) {
- storeWatchExpressions();
+ }
+
+ /**
+ * Adds the given expressions to the list of managed expressions, and returns a list
+ * of expressions that were actually added. Expressions that already exist in the
+ * managed list are not added.
+ *
+ * @param expressions expressions to add
+ * @return list of expressions that were actually added.
+ */
+ private List doAdd(IExpression[] expressions) {
+ List added = new ArrayList(expressions.length);
+ synchronized (this) {
+ if (fExpressions == null) {
+ fExpressions = new Vector(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);
+ }
+ }
}
+ return added;
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.IExpressionManager#getExpressions()
*/
- public IExpression[] getExpressions() {
+ public synchronized IExpression[] getExpressions() {
if (fExpressions == null) {
return new IExpression[0];
}
@@ -301,7 +309,7 @@ public class ExpressionManager extends PlatformObject implements IExpressionMana
/* (non-Javadoc)
* @see org.eclipse.debug.core.IExpressionManager#getExpressions(java.lang.String)
*/
- public IExpression[] getExpressions(String modelIdentifier) {
+ public synchronized IExpression[] getExpressions(String modelIdentifier) {
if (fExpressions == null) {
return new IExpression[0];
}
@@ -331,38 +339,37 @@ public class ExpressionManager extends PlatformObject implements IExpressionMana
* @since 3.4
*/
public void insertExpressions(IExpression[] expressions, IExpression insertionLocation, boolean insertBefore){
- if (fExpressions == null) {
- addExpressions(expressions);
- return;
- }
-
- int insertionIndex = fExpressions.indexOf(insertionLocation);
- if (insertionIndex < 0){
- addExpressions(expressions);
- return;
- }
- if (!insertBefore){
- insertionIndex++;
- }
- boolean addedWatchExpression = false;
- List added = new ArrayList(expressions.length);
- for (int i = 0; i < expressions.length; i++) {
- IExpression expression = expressions[i];
- if (fExpressions.indexOf(expression) == -1) {
- //Insert in the same order as the array is passed
- fExpressions.add(insertionIndex+added.size(), expression);
- added.add(expression);
- if (expression instanceof IWatchExpression) {
- addedWatchExpression= true;
+ List added = null;
+ List inserted = null;
+ int insertionIndex = -1;
+ synchronized (this) {
+ if (fExpressions == null || ((insertionIndex = fExpressions.indexOf(insertionLocation)) < 0)) {
+ added = doAdd(expressions);
+ } else {
+ if (!insertBefore){
+ insertionIndex++;
}
- }
+ inserted = new ArrayList(expressions.length);
+ for (int i = 0; i < expressions.length; i++) {
+ IExpression expression = expressions[i];
+ if (fExpressions.indexOf(expression) == -1) {
+ //Insert in the same order as the array is passed
+ fExpressions.add(insertionIndex+inserted.size(), expression);
+ inserted.add(expression);
+ }
+ }
+ }
}
-
- if (!added.isEmpty()) {
- fireUpdate((IExpression[])added.toArray(new IExpression[added.size()]), INSERTED, insertionIndex);
+ if (added != null) {
+ if (!added.isEmpty()) {
+ fireUpdate((IExpression[])added.toArray(new IExpression[added.size()]), ADDED);
+ }
+ return;
}
- if (addedWatchExpression) {
- storeWatchExpressions();
+ if (inserted != null) {
+ if (!inserted.isEmpty()) {
+ fireUpdate((IExpression[])inserted.toArray(new IExpression[inserted.size()]), INSERTED, insertionIndex);
+ }
}
}
@@ -379,37 +386,40 @@ public class ExpressionManager extends PlatformObject implements IExpressionMana
* @since 3.4
*/
public void moveExpressions(IExpression[] expressions, IExpression insertionLocation, boolean insertBefore){
- if (fExpressions == null){
- return;
- }
- int insertionIndex = fExpressions.indexOf(insertionLocation);
- if (insertionIndex < 0){
- return;
- }
- if (!insertBefore){
- insertionIndex++;
- }
-
List movedExpressions = new ArrayList(expressions.length);
- for (int i = 0; i < expressions.length; i++) {
- int removeIndex = fExpressions.indexOf(expressions[i]);
- if (removeIndex >= 0){
- movedExpressions.add(expressions[i]);
- if (removeIndex < insertionIndex){
- insertionIndex--;
+ int insertionIndex = -1;
+ IExpression[] movedExpressionsArray = null;
+ synchronized (this) {
+ if (fExpressions == null){
+ return;
+ }
+ insertionIndex = fExpressions.indexOf(insertionLocation);
+ if (insertionIndex < 0){
+ return;
+ }
+ if (!insertBefore){
+ insertionIndex++;
+ }
+
+ for (int i = 0; i < expressions.length; i++) {
+ int removeIndex = fExpressions.indexOf(expressions[i]);
+ if (removeIndex >= 0){
+ movedExpressions.add(expressions[i]);
+ if (removeIndex < insertionIndex){
+ insertionIndex--;
+ }
+ fExpressions.remove(removeIndex);
}
- fExpressions.remove(removeIndex);
}
- }
- IExpression[] movedExpressionsArray = (IExpression[])movedExpressions.toArray(new IExpression[movedExpressions.size()]);
- for (int i = 0; i < movedExpressionsArray.length; i++) {
- // Insert the expressions in the same order as the passed array
- fExpressions.add(insertionIndex+i,movedExpressionsArray[i]);
+ movedExpressionsArray = (IExpression[])movedExpressions.toArray(new IExpression[movedExpressions.size()]);
+ for (int i = 0; i < movedExpressionsArray.length; i++) {
+ // Insert the expressions in the same order as the passed array
+ fExpressions.add(insertionIndex+i,movedExpressionsArray[i]);
+ }
}
if (!movedExpressions.isEmpty()) {
fireUpdate(movedExpressionsArray, MOVED, insertionIndex);
- storeWatchExpressions();
}
}
@@ -424,20 +434,25 @@ public class ExpressionManager extends PlatformObject implements IExpressionMana
* @see org.eclipse.debug.core.IExpressionManager#removeExpressions(org.eclipse.debug.core.model.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();
- }
+ synchronized (this) {
+ if (fExpressions == null) {
+ return;
+ }
+ for (int i = 0; i < expressions.length; i++) {
+ IExpression expression = expressions[i];
+ if (fExpressions.remove(expression)) {
+ removed.add(expression);
+ }
+ }
+ }
+ // dispose outside of the synchronized block
+ Iterator iterator = removed.iterator();
+ while (iterator.hasNext()) {
+ ((IExpression) iterator.next()).dispose();
}
if (!removed.isEmpty()) {
fireUpdate((IExpression[])removed.toArray(new IExpression[removed.size()]), REMOVED);
- storeWatchExpressions();
}
}
@@ -468,11 +483,14 @@ public class ExpressionManager extends PlatformObject implements IExpressionMana
* @param expression the changed expression
* @param persist whether to persist the expressions
*/
- protected void watchExpressionChanged(IWatchExpression expression, boolean persist) {
- if (fExpressions != null && fExpressions.contains(expression)) {
- if (persist) {
- storeWatchExpressions();
+ protected void watchExpressionChanged(IWatchExpression expression) {
+ boolean notify = false;
+ synchronized (this) {
+ if (fExpressions != null && fExpressions.contains(expression)) {
+ notify = true;
}
+ }
+ if (notify) {
fireUpdate(new IExpression[]{expression}, CHANGED);
}
}
@@ -505,7 +523,7 @@ public class ExpressionManager extends PlatformObject implements IExpressionMana
/* (non-Javadoc)
* @see org.eclipse.debug.core.IExpressionManager#hasExpressions()
*/
- public boolean hasExpressions() {
+ public synchronized boolean hasExpressions() {
return fExpressions != null && !fExpressions.isEmpty();
}
@@ -557,6 +575,7 @@ public class ExpressionManager extends PlatformObject implements IExpressionMana
public void run() throws Exception {
switch (fType) {
case ADDED:
+ case INSERTED:
fListener.expressionAdded(fExpression);
break;
case REMOVED:
diff --git a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/WatchExpression.java b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/WatchExpression.java
index ed51fc9e6..8be2ba3b4 100644
--- a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/WatchExpression.java
+++ b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/WatchExpression.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 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
@@ -149,8 +149,8 @@ public class WatchExpression implements IWatchExpression {
*
* @param persist whether to persist the expression
*/
- private void watchExpressionChanged(boolean persist) {
- ((ExpressionManager)DebugPlugin.getDefault().getExpressionManager()).watchExpressionChanged(this, persist);
+ private void watchExpressionChanged() {
+ ((ExpressionManager)DebugPlugin.getDefault().getExpressionManager()).watchExpressionChanged(this);
}
/**
@@ -233,7 +233,7 @@ public class WatchExpression implements IWatchExpression {
*/
public void setEnabled(boolean enabled) {
fEnabled= enabled;
- watchExpressionChanged(true);
+ watchExpressionChanged();
evaluate();
}
@@ -242,7 +242,7 @@ public class WatchExpression implements IWatchExpression {
*/
public void setExpressionText(String expression) {
fExpressionText= expression;
- watchExpressionChanged(true);
+ watchExpressionChanged();
evaluate();
}
diff --git a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/expressions/ExpressionManagerTests.java b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/expressions/ExpressionManagerTests.java
new file mode 100644
index 000000000..927632bcc
--- /dev/null
+++ b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/expressions/ExpressionManagerTests.java
@@ -0,0 +1,569 @@
+/*******************************************************************************
+ * Copyright (c) 2010 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
+ *******************************************************************************/
+package org.eclipse.debug.tests.expressions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.eclipse.debug.core.DebugPlugin;
+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;
+import org.eclipse.debug.core.model.IWatchExpression;
+import org.eclipse.debug.internal.core.ExpressionManager;
+import org.eclipse.debug.internal.core.IExpressionsListener2;
+
+/**
+ * Tests expression manager and listener call backs
+ */
+public class ExpressionManagerTests extends TestCase {
+
+ class SinlgeListener implements IExpressionListener {
+
+ List added = new ArrayList();
+ List removed = new ArrayList();
+ List changed = new ArrayList();
+ int addedCallbacks = 0;
+ int removedCallbacks = 0;
+ int changedCallbacks = 0;
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.IExpressionListener#expressionAdded(org.eclipse.debug.core.model.IExpression)
+ */
+ public void expressionAdded(IExpression expression) {
+ added.add(expression);
+ addedCallbacks++;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.IExpressionListener#expressionRemoved(org.eclipse.debug.core.model.IExpression)
+ */
+ public void expressionRemoved(IExpression expression) {
+ removed.add(expression);
+ removedCallbacks++;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.IExpressionListener#expressionChanged(org.eclipse.debug.core.model.IExpression)
+ */
+ public void expressionChanged(IExpression expression) {
+ changed.add(expression);
+ changedCallbacks++;
+ }
+
+ }
+
+ class MultiListener implements IExpressionsListener {
+
+ List added = new ArrayList();
+ List removed = new ArrayList();
+ List changed = new ArrayList();
+ int addedCallbacks = 0;
+ int removedCallbacks = 0;
+ int changedCallbacks = 0;
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.IExpressionsListener#expressionsAdded(org.eclipse.debug.core.model.IExpression[])
+ */
+ public void expressionsAdded(IExpression[] expressions) {
+ for (int i = 0; i < expressions.length; i++) {
+ added.add(expressions[i]);
+ }
+ addedCallbacks++;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.IExpressionsListener#expressionsRemoved(org.eclipse.debug.core.model.IExpression[])
+ */
+ public void expressionsRemoved(IExpression[] expressions) {
+ for (int i = 0; i < expressions.length; i++) {
+ removed.add(expressions[i]);
+ }
+ removedCallbacks++;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.IExpressionsListener#expressionsChanged(org.eclipse.debug.core.model.IExpression[])
+ */
+ public void expressionsChanged(IExpression[] expressions) {
+ for (int i = 0; i < expressions.length; i++) {
+ changed.add(expressions[i]);
+ }
+ changedCallbacks++;
+ }
+
+ }
+
+ class InsertMoveListener extends MultiListener implements IExpressionsListener2 {
+
+ List moved = new ArrayList();
+ List inserted = new ArrayList();
+ int insertIndex = -1;
+ int movedCallbacks = 0;
+ int insertedCallbacks = 0;
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.IExpressionsListener2#expressionsMoved(org.eclipse.debug.core.model.IExpression[], int)
+ */
+ public void expressionsMoved(IExpression[] expressions, int index) {
+ for (int i = 0; i < expressions.length; i++) {
+ moved.add(expressions[i]);
+ }
+ movedCallbacks++;
+ insertIndex = index;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.IExpressionsListener2#expressionsInserted(org.eclipse.debug.core.model.IExpression[], int)
+ */
+ public void expressionsInserted(IExpression[] expressions, int index) {
+ for (int i = 0; i < expressions.length; i++) {
+ inserted.add(expressions[i]);
+ }
+ insertedCallbacks++;
+ insertIndex = index;
+ }
+
+ }
+
+ /**
+ * Returns the expression manager.
+ *
+ * @return expression manager
+ */
+ protected IExpressionManager getManager() {
+ return DebugPlugin.getDefault().getExpressionManager();
+ }
+
+ /* (non-Javadoc)
+ * @see junit.framework.TestCase#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ // remove all expressions from the manager
+ super.tearDown();
+ getManager().removeExpressions(getManager().getExpressions());
+ }
+
+ /**
+ * Returns the index of the given expression in the given list or -1 if not present.
+ *
+ * @param expression candidate
+ * @param list list to search
+ * @return index or -1
+ */
+ private int indexOf(IExpression expression, IExpression[] list) {
+ for (int i = 0; i < list.length; i++) {
+ if (expression.equals(list[i])) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Add expressions and ensure proper call backs are received.
+ */
+ public void testAddExpressions() {
+ IExpressionManager manager = getManager();
+ SinlgeListener single = new SinlgeListener();
+ MultiListener multi = new MultiListener();
+ manager.addExpressionListener(single);
+ manager.addExpressionListener(multi);
+ try {
+ IWatchExpression exp1 = manager.newWatchExpression("exp1");
+ IWatchExpression exp2 = manager.newWatchExpression("exp2");
+ IWatchExpression exp3 = manager.newWatchExpression("exp3");
+ manager.addExpressions(new IExpression[]{exp1, exp2, exp3});
+ IExpression[] expressions = manager.getExpressions();
+ assertEquals("Wrong number of expressions", 3, expressions.length);
+ assertEquals(single.addedCallbacks, 3);
+ assertEquals(3, single.added.size());
+ assertEquals(0, single.added.indexOf(exp1));
+ assertEquals(1, single.added.indexOf(exp2));
+ assertEquals(2, single.added.indexOf(exp3));
+ assertEquals(0, single.removedCallbacks);
+ assertEquals(0, single.changedCallbacks);
+ assertEquals(1, multi.addedCallbacks);
+ assertEquals(0, multi.removedCallbacks);
+ assertEquals(0, multi.changedCallbacks);
+ assertEquals(0, indexOf(exp1, expressions));
+ assertEquals(1, indexOf(exp2, expressions));
+ assertEquals(2, indexOf(exp3, expressions));
+ } finally {
+ manager.removeExpressionListener(single);
+ manager.removeExpressionListener(multi);
+ }
+ }
+
+ /**
+ * Remove expressions and ensure proper call backs are received.
+ */
+ public void testRemoveExpressions() {
+ IExpressionManager manager = getManager();
+ SinlgeListener single = new SinlgeListener();
+ MultiListener multi = new MultiListener();
+ manager.addExpressionListener(single);
+ manager.addExpressionListener(multi);
+ try {
+ IWatchExpression exp1 = manager.newWatchExpression("exp1");
+ IWatchExpression exp2 = manager.newWatchExpression("exp2");
+ IWatchExpression exp3 = manager.newWatchExpression("exp3");
+ manager.addExpressions(new IExpression[]{exp1, exp2, exp3});
+ manager.removeExpressions(new IExpression[]{exp1, exp3});
+ IExpression[] expressions = manager.getExpressions();
+ assertEquals("Wrong number of expressions", 1, expressions.length);
+ assertEquals(single.addedCallbacks, 3);
+ assertEquals(3, single.added.size());
+ assertEquals(0, single.added.indexOf(exp1));
+ assertEquals(1, single.added.indexOf(exp2));
+ assertEquals(2, single.added.indexOf(exp3));
+ assertEquals(2, single.removedCallbacks);
+ assertEquals(0, single.removed.indexOf(exp1));
+ assertEquals(1, single.removed.indexOf(exp3));
+ assertEquals(0, single.changedCallbacks);
+ assertEquals(1, multi.addedCallbacks);
+ assertEquals(1, multi.removedCallbacks);
+ assertEquals(0, multi.removed.indexOf(exp1));
+ assertEquals(1, multi.removed.indexOf(exp3));
+ assertEquals(0, multi.changedCallbacks);
+ assertEquals(-1, indexOf(exp1, expressions));
+ assertEquals(0, indexOf(exp2, expressions));
+ assertEquals(-1, indexOf(exp3, expressions));
+ } finally {
+ manager.removeExpressionListener(single);
+ manager.removeExpressionListener(multi);
+ }
+ }
+
+ /**
+ * Change expressions and ensure proper call backs are received.
+ */
+ public void testChangeExpressions() {
+ IExpressionManager manager = getManager();
+ SinlgeListener single = new SinlgeListener();
+ MultiListener multi = new MultiListener();
+ manager.addExpressionListener(single);
+ manager.addExpressionListener(multi);
+ try {
+ IWatchExpression exp1 = manager.newWatchExpression("exp1");
+ IWatchExpression exp2 = manager.newWatchExpression("exp2");
+ IWatchExpression exp3 = manager.newWatchExpression("exp3");
+ manager.addExpressions(new IExpression[]{exp1, exp2, exp3});
+ IExpression[] expressions = manager.getExpressions();
+ exp1.setEnabled(false);
+ exp2.setExpressionText("exp2changed");
+ assertEquals("Wrong number of expressions", 3, expressions.length);
+ assertEquals(single.addedCallbacks, 3);
+ assertEquals(3, single.added.size());
+ assertEquals(0, single.added.indexOf(exp1));
+ assertEquals(1, single.added.indexOf(exp2));
+ assertEquals(2, single.added.indexOf(exp3));
+ assertEquals(0, single.removedCallbacks);
+ assertEquals(2, single.changedCallbacks);
+ assertEquals(0, single.changed.indexOf(exp1));
+ assertEquals(1, single.changed.indexOf(exp2));
+ assertEquals(1, multi.addedCallbacks);
+ assertEquals(0, multi.removedCallbacks);
+ assertEquals(2, multi.changedCallbacks);
+ assertEquals(0, multi.changed.indexOf(exp1));
+ assertEquals(1, multi.changed.indexOf(exp2));
+ assertEquals(0, indexOf(exp1, expressions));
+ assertEquals(1, indexOf(exp2, expressions));
+ assertEquals(2, indexOf(exp3, expressions));
+ } finally {
+ manager.removeExpressionListener(single);
+ manager.removeExpressionListener(multi);
+ }
+ }
+
+ /**
+ * Insert expressions and ensure proper call backs are received.
+ */
+ public void testInsertBeforeExpressions() {
+ ExpressionManager manager = (ExpressionManager) getManager();
+ SinlgeListener single = new SinlgeListener();
+ MultiListener multi = new MultiListener();
+ InsertMoveListener insert = new InsertMoveListener();
+ try {
+ IWatchExpression exp1 = manager.newWatchExpression("exp1");
+ IWatchExpression exp2 = manager.newWatchExpression("exp2");
+ IWatchExpression exp3 = manager.newWatchExpression("exp3");
+ IWatchExpression exp4 = manager.newWatchExpression("exp4");
+ IWatchExpression exp5 = manager.newWatchExpression("exp5");
+ manager.addExpressions(new IExpression[]{exp1, exp2, exp3});
+ IExpression[] expressions = manager.getExpressions();
+ assertEquals("Wrong number of expressions", 3, expressions.length);
+ assertEquals(0, indexOf(exp1, expressions));
+ assertEquals(1, indexOf(exp2, expressions));
+ assertEquals(2, indexOf(exp3, expressions));
+ // add listeners
+ manager.addExpressionListener(single);
+ manager.addExpressionListener(multi);
+ manager.addExpressionListener(insert);
+
+ manager.insertExpressions(new IExpression[] {exp4, exp5}, exp2, true);
+
+ assertEquals(2, single.addedCallbacks);
+ assertEquals(2, single.added.size());
+ assertEquals(0, single.removedCallbacks);
+ assertEquals(0, single.changedCallbacks);
+ assertEquals(1, multi.addedCallbacks);
+ assertEquals(2, multi.added.size());
+ assertEquals(0, multi.removedCallbacks);
+ assertEquals(0, multi.changedCallbacks);
+ assertEquals(1, insert.insertedCallbacks);
+ assertEquals(1, insert.insertIndex);
+ assertEquals(0, insert.movedCallbacks);
+ assertEquals(2, insert.inserted.size());
+ assertEquals(0, insert.inserted.indexOf(exp4));
+ assertEquals(1, insert.inserted.indexOf(exp5));
+
+ expressions = manager.getExpressions();
+ assertEquals("Wrong number of expressions", 5, expressions.length);
+ assertEquals(0, indexOf(exp1, expressions));
+ assertEquals(1, indexOf(exp4, expressions));
+ assertEquals(2, indexOf(exp5, expressions));
+ assertEquals(3, indexOf(exp2, expressions));
+ assertEquals(4, indexOf(exp3, expressions));
+
+ } finally {
+ manager.removeExpressionListener(single);
+ manager.removeExpressionListener(multi);
+ manager.removeExpressionListener(insert);
+ }
+ }
+
+ /**
+ * Insert expressions and ensure proper call backs are received.
+ */
+ public void testInsertAfterExpressions() {
+ ExpressionManager manager = (ExpressionManager) getManager();
+ SinlgeListener single = new SinlgeListener();
+ MultiListener multi = new MultiListener();
+ InsertMoveListener insert = new InsertMoveListener();
+ try {
+ IWatchExpression exp1 = manager.newWatchExpression("exp1");
+ IWatchExpression exp2 = manager.newWatchExpression("exp2");
+ IWatchExpression exp3 = manager.newWatchExpression("exp3");
+ IWatchExpression exp4 = manager.newWatchExpression("exp4");
+ IWatchExpression exp5 = manager.newWatchExpression("exp5");
+ manager.addExpressions(new IExpression[]{exp1, exp2, exp3});
+ IExpression[] expressions = manager.getExpressions();
+ assertEquals("Wrong number of expressions", 3, expressions.length);
+ assertEquals(0, indexOf(exp1, expressions));
+ assertEquals(1, indexOf(exp2, expressions));
+ assertEquals(2, indexOf(exp3, expressions));
+ // add listeners
+ manager.addExpressionListener(single);
+ manager.addExpressionListener(multi);
+ manager.addExpressionListener(insert);
+
+ manager.insertExpressions(new IExpression[] {exp4, exp5}, exp2, false);
+
+ assertEquals(2, single.addedCallbacks);
+ assertEquals(2, single.added.size());
+ assertEquals(0, single.removedCallbacks);
+ assertEquals(0, single.changedCallbacks);
+ assertEquals(1, multi.addedCallbacks);
+ assertEquals(2, multi.added.size());
+ assertEquals(0, multi.removedCallbacks);
+ assertEquals(0, multi.changedCallbacks);
+ assertEquals(1, insert.insertedCallbacks);
+ assertEquals(2, insert.insertIndex);
+ assertEquals(0, insert.movedCallbacks);
+ assertEquals(2, insert.inserted.size());
+ assertEquals(0, insert.inserted.indexOf(exp4));
+ assertEquals(1, insert.inserted.indexOf(exp5));
+
+ expressions = manager.getExpressions();
+ assertEquals("Wrong number of expressions", 5, expressions.length);
+ assertEquals(0, indexOf(exp1, expressions));
+ assertEquals(1, indexOf(exp2, expressions));
+ assertEquals(2, indexOf(exp4, expressions));
+ assertEquals(3, indexOf(exp5, expressions));
+ assertEquals(4, indexOf(exp3, expressions));
+
+ } finally {
+ manager.removeExpressionListener(single);
+ manager.removeExpressionListener(multi);
+ manager.removeExpressionListener(insert);
+ }
+ }
+
+ /**
+ * Move expressions and ensure proper call backs are received.
+ */
+ public void testMoveBeforeExpressions() {
+ ExpressionManager manager = (ExpressionManager) getManager();
+ SinlgeListener single = new SinlgeListener();
+ MultiListener multi = new MultiListener();
+ InsertMoveListener insert = new InsertMoveListener();
+ try {
+ IWatchExpression exp1 = manager.newWatchExpression("exp1");
+ IWatchExpression exp2 = manager.newWatchExpression("exp2");
+ IWatchExpression exp3 = manager.newWatchExpression("exp3");
+ IWatchExpression exp4 = manager.newWatchExpression("exp4");
+ IWatchExpression exp5 = manager.newWatchExpression("exp5");
+ manager.addExpressions(new IExpression[]{exp1, exp2, exp3, exp4, exp5});
+ // add listeners
+ manager.addExpressionListener(single);
+ manager.addExpressionListener(multi);
+ manager.addExpressionListener(insert);
+
+ manager.moveExpressions(new IExpression[]{exp1,exp2}, exp5, true);
+
+ assertEquals(0, single.addedCallbacks);
+ assertEquals(0, single.removedCallbacks);
+ assertEquals(0, single.changedCallbacks);
+ assertEquals(0, multi.addedCallbacks);
+ assertEquals(0, multi.removedCallbacks);
+ assertEquals(0, multi.changedCallbacks);
+ assertEquals(0, insert.insertedCallbacks);
+ assertEquals(1, insert.movedCallbacks);
+ assertEquals(2, insert.moved.size());
+ assertEquals(0, insert.moved.indexOf(exp1));
+ assertEquals(1, insert.moved.indexOf(exp2));
+ assertEquals(2, insert.insertIndex);
+
+ IExpression[] expressions = manager.getExpressions();
+ assertEquals("Wrong number of expressions", 5, expressions.length);
+ assertEquals(0, indexOf(exp3, expressions));
+ assertEquals(1, indexOf(exp4, expressions));
+ assertEquals(2, indexOf(exp1, expressions));
+ assertEquals(3, indexOf(exp2, expressions));
+ assertEquals(4, indexOf(exp5, expressions));
+
+ } finally {
+ manager.removeExpressionListener(single);
+ manager.removeExpressionListener(multi);
+ manager.removeExpressionListener(insert);
+ }
+ }
+
+ /**
+ * Move expressions and ensure proper call backs are received.
+ */
+ public void testMoveAfterExpressions() {
+ ExpressionManager manager = (ExpressionManager) getManager();
+ SinlgeListener single = new SinlgeListener();
+ MultiListener multi = new MultiListener();
+ InsertMoveListener insert = new InsertMoveListener();
+ try {
+ IWatchExpression exp1 = manager.newWatchExpression("exp1");
+ IWatchExpression exp2 = manager.newWatchExpression("exp2");
+ IWatchExpression exp3 = manager.newWatchExpression("exp3");
+ IWatchExpression exp4 = manager.newWatchExpression("exp4");
+ IWatchExpression exp5 = manager.newWatchExpression("exp5");
+ manager.addExpressions(new IExpression[]{exp1, exp2, exp3, exp4, exp5});
+ // add listeners
+ manager.addExpressionListener(single);
+ manager.addExpressionListener(multi);
+ manager.addExpressionListener(insert);
+
+ manager.moveExpressions(new IExpression[]{exp1,exp2}, exp3, false);
+
+ assertEquals(0, single.addedCallbacks);
+ assertEquals(0, single.removedCallbacks);
+ assertEquals(0, single.changedCallbacks);
+ assertEquals(0, multi.addedCallbacks);
+ assertEquals(0, multi.removedCallbacks);
+ assertEquals(0, multi.changedCallbacks);
+ assertEquals(0, insert.insertedCallbacks);
+ assertEquals(1, insert.movedCallbacks);
+ assertEquals(2, insert.moved.size());
+ assertEquals(0, insert.moved.indexOf(exp1));
+ assertEquals(1, insert.moved.indexOf(exp2));
+ assertEquals(1, insert.insertIndex);
+
+ IExpression[] expressions = manager.getExpressions();
+ assertEquals("Wrong number of expressions", 5, expressions.length);
+ assertEquals(0, indexOf(exp3, expressions));
+ assertEquals(1, indexOf(exp1, expressions));
+ assertEquals(2, indexOf(exp2, expressions));
+ assertEquals(3, indexOf(exp4, expressions));
+ assertEquals(4, indexOf(exp5, expressions));
+
+ } finally {
+ manager.removeExpressionListener(single);
+ manager.removeExpressionListener(multi);
+ manager.removeExpressionListener(insert);
+ }
+ }
+
+ /**
+ * Test persist and restore of expressions
+ */
+ public void testPersistExpressions() {
+ ExpressionManager manager = (ExpressionManager) getManager();
+ IWatchExpression exp1 = manager.newWatchExpression("exp1");
+ IWatchExpression exp2 = manager.newWatchExpression("exp2");
+ IWatchExpression exp3 = manager.newWatchExpression("exp3");
+ IWatchExpression exp4 = manager.newWatchExpression("exp4");
+ IWatchExpression exp5 = manager.newWatchExpression("exp5");
+ manager.addExpressions(new IExpression[]{exp1, exp2, exp3, exp4, exp5});
+ manager.storeWatchExpressions();
+
+ // create a new manager that will restore the expressions
+ ExpressionManager manager2 = new ExpressionManager();
+ IExpression[] expressions = manager2.getExpressions();
+ assertEquals("Wrong number of expressions", 5, expressions.length);
+ assertEquals("exp1", expressions[0].getExpressionText());
+ assertEquals("exp2", expressions[1].getExpressionText());
+ assertEquals("exp3", expressions[2].getExpressionText());
+ assertEquals("exp4", expressions[3].getExpressionText());
+ assertEquals("exp5", expressions[4].getExpressionText());
+ }
+
+ /**
+ * Tests concurrent access to expressions.
+ *
+ * @throws InterruptedException
+ */
+ public void testConcurrentAccess() throws InterruptedException {
+ final boolean[] done = new boolean[]{false};
+ final Exception[] ex = new Exception[]{null};
+ Runnable add = new Runnable() {
+ public void run() {
+ try {
+ for (int i = 0; i < 1000; i++) {
+ getManager().addExpression(getManager().newWatchExpression(Integer.toHexString(i)));
+ }
+ done[0] = true;
+ } catch (Exception e) {
+ ex[0] = e;
+ }
+ }
+ };
+ Runnable remove = new Runnable() {
+ public void run() {
+ try {
+ do {
+ getManager().removeExpressions(getManager().getExpressions());
+ } while (!done[0] || getManager().getExpressions().length > 0);
+ } catch (Exception e) {
+ ex[0] = e;
+ }
+ }
+ };
+ Thread t1 = new Thread(add);
+ Thread t2 = new Thread(remove);
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+ assertEquals(0, getManager().getExpressions().length);
+ assertNull(ex[0]);
+ }
+
+}

Back to the top