Test-only changes that add support for "dual mode" tests that can run against either mock or real workspace objects.
diff --git a/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/DualModeCoreTests.java b/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/DualModeCoreTests.java
new file mode 100644
index 0000000..7823c5f
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/DualModeCoreTests.java
@@ -0,0 +1,27 @@
+package org.eclipse.jst.jsf.core.tests;
+
+import org.eclipse.jst.jsf.core.tests.resource.AllLifecycleListenerTests;
+import org.eclipse.jst.jsf.core.tests.resource.FastClasspathEntryLifecycleTests;
+import org.eclipse.jst.jsf.core.tests.resource.TestDefaultJarLocator;
+import org.eclipse.jst.jsf.core.tests.resource.TestResourceTracker;
+import org.eclipse.jst.jsf.core.tests.serialization.TLDAttributeSerializationTests;
+import org.eclipse.jst.jsf.test.util.junit4.DualModeEnvironment;
+import org.junit.experimental.categories.Categories.IncludeCategory;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+/**
+ * Tests that can be run as either plugin or regular JUnit tests.
+ * @author cbateman
+ *
+ */
+@RunWith(Suite.class)
+@IncludeCategory(DualModeEnvironment.class)
+@SuiteClasses(
+{ AllLifecycleListenerTests.class,
+        TestResourceTracker.class,TLDAttributeSerializationTests.class ,
+        FastClasspathEntryLifecycleTests.class, TestDefaultJarLocator.class})
+public class DualModeCoreTests
+{
+}
diff --git a/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/AllLifecycleListenerTests.java b/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/AllLifecycleListenerTests.java
index c71dc6a..0eded2f 100644
--- a/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/AllLifecycleListenerTests.java
+++ b/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/AllLifecycleListenerTests.java
@@ -1,13 +1,13 @@
 package org.eclipse.jst.jsf.core.tests.resource;
 
-import org.eclipse.jst.jsf.test.util.junit4.FastTest;
-import org.junit.experimental.categories.Categories;
+import org.eclipse.jst.jsf.test.util.junit4.DualModeEnvironment;
 import org.junit.experimental.categories.Categories.IncludeCategory;
 import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
 import org.junit.runners.Suite.SuiteClasses;
 
-@RunWith(Categories.class)
-@IncludeCategory(FastTest.class)
+@RunWith(Suite.class)
+@IncludeCategory(DualModeEnvironment.class)
 @SuiteClasses(
 { FastLifecycleListenerTests.class, FastLifecycleListenerTests_Scenario.class })
 public class AllLifecycleListenerTests
diff --git a/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/FastClasspathEntryLifecycleTests.java b/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/FastClasspathEntryLifecycleTests.java
index 0c86f4d..558a986 100644
--- a/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/FastClasspathEntryLifecycleTests.java
+++ b/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/FastClasspathEntryLifecycleTests.java
@@ -1,12 +1,13 @@
 package org.eclipse.jst.jsf.core.tests.resource;
 
+import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.jdt.core.ElementChangedEvent;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jst.jsf.common.internal.resource.ClasspathEntryLifecycleListener;
 import org.eclipse.jst.jsf.common.internal.resource.IClasspathLifecycleListener.ClasspathLifecycleEvent;
 import org.eclipse.jst.jsf.test.util.junit4.NoPluginEnvironment;
-import org.eclipse.jst.jsf.test.util.mock.MockProject;
+import org.eclipse.jst.jsf.test.util.mock.IWorkspaceContext;
 import org.eclipse.jst.jsf.test.util.mock.MockWorkspaceContext;
 import org.eclipse.jst.jsf.test.util.mock.java.MockJDTWorkspaceContext;
 import org.eclipse.jst.jsf.test.util.mock.java.MockJavaChangeEventFactory;
@@ -20,9 +21,9 @@
 @Category(NoPluginEnvironment.class)
 public class FastClasspathEntryLifecycleTests
 {
-    private MockWorkspaceContext _wsContext;
+    private IWorkspaceContext _wsContext;
     private MockJavaChangeEventFactory _factory;
-    private MockProject _project;
+    private IProject _project;
     private MockJDTWorkspaceContext _jdtContext;
     private MockJavaProject _javaProject;
 
diff --git a/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/FastLifecycleListenerTests.java b/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/FastLifecycleListenerTests.java
index 541b327..7499bf8 100644
--- a/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/FastLifecycleListenerTests.java
+++ b/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/FastLifecycleListenerTests.java
@@ -6,34 +6,39 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
 import org.eclipse.jst.jsf.common.internal.resource.LifecycleListener;
 import org.eclipse.jst.jsf.common.internal.resource.ResourceLifecycleEvent.EventType;
 import org.eclipse.jst.jsf.common.internal.resource.ResourceLifecycleEvent.ReasonType;
 import org.eclipse.jst.jsf.test.util.junit4.NoPluginEnvironment;
-import org.eclipse.jst.jsf.test.util.mock.MockFile;
-import org.eclipse.jst.jsf.test.util.mock.MockProject;
+import org.eclipse.jst.jsf.test.util.junit4.WorkspaceContext;
+import org.eclipse.jst.jsf.test.util.junit4.WorkspaceRunner;
+import org.eclipse.jst.jsf.test.util.mock.IWorkspaceContextWithEvents;
 import org.eclipse.jst.jsf.test.util.mock.MockResourceChangeEventFactory;
-import org.eclipse.jst.jsf.test.util.mock.MockWorkspaceContext;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
 
+@RunWith(WorkspaceRunner.class)
 @Category(NoPluginEnvironment.class)
 public class FastLifecycleListenerTests
 {
-    private MockWorkspaceContext _wsContext;
+    @WorkspaceContext
+    private IWorkspaceContextWithEvents _wsContext;
     private MockResourceChangeEventFactory _factory;
-    private MockProject _project;
-    private MockFile _file;
+    private IProject _project;
+    private IFile _file;
 
     @Before
     public void setUp() throws Exception
     {
-        _wsContext = new MockWorkspaceContext();
         _project = _wsContext.createProject("SomeTestProject");
-        _file = (MockFile) _project.getFile("myfile.txt");
+        _file = _project.getFile("myfile.txt");
         _factory = new MockResourceChangeEventFactory(_wsContext);
     }
 
@@ -55,24 +60,27 @@
     @Test
     public void testAddRemoveResource()
     {
+        final List<Class<? extends IResourceChangeListener>> includeListeners = 
+            new ArrayList<Class<? extends IResourceChangeListener>>();
+        includeListeners.add(LifecycleListener.class);
         final LifecycleListener listener = new LifecycleListener(_wsContext
                 .getWorkspace());
         final MyTestListener tester = new MyTestListener(_wsContext, listener);
         final IResourceChangeEvent event = _factory.createSimpleFileChange(
                 _file, true);
         tester.fireAndExpectNull(event);
-        assertEquals(0, _wsContext.getWorkspace().getListeners().size());
+        assertEquals(0, _wsContext.getListeners(includeListeners).size());
 
         // now add the resource and verify the event
         listener.addResource(_file);
         tester.fireAndExpect(event, _file, EventType.RESOURCE_CHANGED,
                 ReasonType.RESOURCE_CHANGED_CONTENTS);
-        assertEquals(1, _wsContext.getWorkspace().getListeners().size());
+        assertEquals(1, _wsContext.getListeners(includeListeners).size());
 
         // remove it again and verify no event.
         listener.removeResource(_file);
         tester.fireAndExpectNull(event);
-        assertEquals(0, _wsContext.getWorkspace().getListeners().size());
+        assertEquals(0, _wsContext.getListeners(includeListeners).size());
     }
 
     @Test(expected = IllegalStateException.class)
diff --git a/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/FastLifecycleListenerTests_Scenario.java b/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/FastLifecycleListenerTests_Scenario.java
index ee7f237..06c2f9f 100644
--- a/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/FastLifecycleListenerTests_Scenario.java
+++ b/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/FastLifecycleListenerTests_Scenario.java
@@ -8,38 +8,42 @@
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResourceChangeEvent;
 import org.eclipse.jst.jsf.common.internal.resource.LifecycleListener;
 import org.eclipse.jst.jsf.common.internal.resource.ResourceLifecycleEvent.EventType;
 import org.eclipse.jst.jsf.common.internal.resource.ResourceLifecycleEvent.ReasonType;
 import org.eclipse.jst.jsf.core.tests.resource.MyTestListener.EventData;
-import org.eclipse.jst.jsf.test.util.junit4.NoPluginEnvironment;
-import org.eclipse.jst.jsf.test.util.mock.MockFile;
-import org.eclipse.jst.jsf.test.util.mock.MockProject;
+import org.eclipse.jst.jsf.test.util.junit4.DualModeEnvironment;
+import org.eclipse.jst.jsf.test.util.junit4.WorkspaceContext;
+import org.eclipse.jst.jsf.test.util.junit4.WorkspaceRunner;
+import org.eclipse.jst.jsf.test.util.mock.IWorkspaceContextWithEvents;
 import org.eclipse.jst.jsf.test.util.mock.MockResourceChangeEventFactory;
-import org.eclipse.jst.jsf.test.util.mock.MockWorkspaceContext;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
 
-@Category(NoPluginEnvironment.class)
+@RunWith(WorkspaceRunner.class)
+@Category(DualModeEnvironment.class)
 public class FastLifecycleListenerTests_Scenario
 {
-    private MockWorkspaceContext _wsContext;
+    @WorkspaceContext
+    private IWorkspaceContextWithEvents _wsContext;
     private MockResourceChangeEventFactory _factory;
-    private MockProject _project;
-    private MockFile _file;
+    private IProject _project;
+    private IFile _file;
     private IFolder _folderInProject;
     private IFolder _folderInFolder;
 
     @Before
     public void setUp() throws Exception
     {
-        _wsContext = new MockWorkspaceContext();
+//        _wsContext = new MockWorkspaceContext();
         _project = _wsContext.createProject("SomeTestProject");
         _folderInProject = _project.getFolder("/folder");
         _folderInFolder = _project.getFolder("/folder/folderInFolder");
-        _file = (MockFile) _project.getFile("/folder/myfile.txt");
+        _file = _project.getFile("/folder/myfile.txt");
         _factory = new MockResourceChangeEventFactory(_wsContext);
     }
 
diff --git a/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/MyTestListener.java b/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/MyTestListener.java
index 88c4965..a49ac97 100644
--- a/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/MyTestListener.java
+++ b/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/MyTestListener.java
@@ -17,19 +17,19 @@
 import org.eclipse.jst.jsf.common.internal.resource.ResourceLifecycleEvent;
 import org.eclipse.jst.jsf.common.internal.resource.ResourceLifecycleEvent.EventType;
 import org.eclipse.jst.jsf.common.internal.resource.ResourceLifecycleEvent.ReasonType;
-import org.eclipse.jst.jsf.test.util.mock.MockWorkspaceContext;
+import org.eclipse.jst.jsf.test.util.mock.IWorkspaceContextWithEvents;
 
 class MyTestListener extends AbstractTestListener<ResourceLifecycleEvent> implements IResourceLifecycleListener
 {
     private final List<EventData> _events = new ArrayList<EventData>();
-    private final MockWorkspaceContext _wsContext;
+    private final IWorkspaceContextWithEvents _wsContext;
 
-    public MyTestListener(final MockWorkspaceContext wsContext)
+    public MyTestListener(final IWorkspaceContextWithEvents wsContext)
     {
         _wsContext = wsContext;
     }
 
-    public MyTestListener(final MockWorkspaceContext wsContext,
+    public MyTestListener(final IWorkspaceContextWithEvents wsContext,
             final LifecycleListener listener)
     {
         listener.addListener(this);
diff --git a/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/TestDefaultJarLocator.java b/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/TestDefaultJarLocator.java
index 0eb8e13..71aac84 100644
--- a/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/TestDefaultJarLocator.java
+++ b/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/TestDefaultJarLocator.java
@@ -6,6 +6,7 @@
 import java.io.File;
 import java.util.Collection;
 
+import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.jdt.core.ElementChangedEvent;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
@@ -15,7 +16,7 @@
 import org.eclipse.jst.jsf.common.internal.resource.IJarLocator.JarChangeEvent.Type;
 import org.eclipse.jst.jsf.common.internal.resource.IJarLocator.JarChangeListener;
 import org.eclipse.jst.jsf.test.util.junit4.NoPluginEnvironment;
-import org.eclipse.jst.jsf.test.util.mock.MockProject;
+import org.eclipse.jst.jsf.test.util.mock.IWorkspaceContext;
 import org.eclipse.jst.jsf.test.util.mock.MockWorkspaceContext;
 import org.eclipse.jst.jsf.test.util.mock.java.MockJDTWorkspaceContext;
 import org.eclipse.jst.jsf.test.util.mock.java.MockJavaChangeEventFactory;
@@ -29,8 +30,8 @@
 @Category(NoPluginEnvironment.class)
 public class TestDefaultJarLocator
 {
-    private MockWorkspaceContext _wsContext;
-    private MockProject _project;
+    private IWorkspaceContext _wsContext;
+    private IProject _project;
     private MockJavaChangeEventFactory _factory;
     private MockJDTWorkspaceContext _jdtContext;
     private MockJavaProject _javaProject;
diff --git a/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/TestResourceTracker.java b/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/TestResourceTracker.java
index 66f5372..4211006 100644
--- a/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/TestResourceTracker.java
+++ b/jsf/tests/org.eclipse.jst.jsf.core.tests/src/org/eclipse/jst/jsf/core/tests/resource/TestResourceTracker.java
@@ -8,22 +8,25 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IResourceChangeEvent;
-import org.eclipse.core.runtime.Path;
 import org.eclipse.jst.jsf.common.internal.resource.LifecycleListener;
 import org.eclipse.jst.jsf.common.internal.resource.ResourceLifecycleEvent.ReasonType;
 import org.eclipse.jst.jsf.common.internal.resource.ResourceTracker;
 import org.eclipse.jst.jsf.test.util.junit4.NoPluginEnvironment;
-import org.eclipse.jst.jsf.test.util.mock.MockFile;
-import org.eclipse.jst.jsf.test.util.mock.MockProject;
+import org.eclipse.jst.jsf.test.util.junit4.WorkspaceContext;
+import org.eclipse.jst.jsf.test.util.junit4.WorkspaceRunner;
+import org.eclipse.jst.jsf.test.util.mock.IWorkspaceContextWithEvents;
 import org.eclipse.jst.jsf.test.util.mock.MockResourceChangeEventFactory;
-import org.eclipse.jst.jsf.test.util.mock.MockWorkspaceContext;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
 
+@RunWith(WorkspaceRunner.class)
 @Category(NoPluginEnvironment.class)
 public class TestResourceTracker
 {
@@ -98,22 +101,23 @@
     }
 
     private MockResourceChangeEventFactory _eventFactory;
-    private MockWorkspaceContext _wsContext;
-    private MockFile _testResource;
+    @WorkspaceContext
+    private IWorkspaceContextWithEvents _wsContext;
+    private IFile _testResource;
     private TestableResourceTracker _resourceTracker;
     private LifecycleListener _lifecycleListener;
-    private MockFile _uninterestedInRes;
+    private IFile _uninterestedInRes;
 
     @Before
     public void setUp() throws Exception
     {
-        _wsContext = new MockWorkspaceContext();
+//        _wsContext = new MockWorkspaceContext();
         _eventFactory = new MockResourceChangeEventFactory(_wsContext);
-        final MockProject createProject = _wsContext.createProject(new Path(
-                "TestResourceTracker_Project"));
-        _testResource = (MockFile) createProject
+        final IProject createProject = _wsContext.createProject(
+                "TestResourceTracker_Project");
+        _testResource = createProject
                 .getFile("/WebContent/resources/foo/resource/somelib/foo.xhtml");
-        _uninterestedInRes = (MockFile) createProject
+        _uninterestedInRes = createProject
                 .getFile("/WebContent/resources/foo/resource/uninterestedInMe/foo.xhtml");
         _resourceTracker = new TestableResourceTracker(_testResource);
         _lifecycleListener = new LifecycleListener(_wsContext.getWorkspace());
@@ -137,14 +141,14 @@
     @Test
     public void testGetLastModifiedStamp()
     {
-        assertEquals(0, _resourceTracker.getLastModifiedStamp());
+        assertEquals(-1, _resourceTracker.getLastModifiedStamp());
     }
 
     @Test
     public void testFireResourceInAccessible()
     {
         final IResourceChangeEvent event = _eventFactory
-                .createSimpleProjectDeleted((MockProject) _testResource
+                .createSimpleProjectDeleted( _testResource
                         .getProject());
         _wsContext.fireWorkspaceEvent(event);
         assertTrue(_resourceTracker.isInAccessibleFired());
diff --git a/jsf/tests/org.eclipse.jst.jsf.designtime.tests/src/org/eclipse/jst/jsf/designtime/tests/DesignTimeFastTests.java b/jsf/tests/org.eclipse.jst.jsf.designtime.tests/src/org/eclipse/jst/jsf/designtime/tests/DesignTimeFastTests.java
index 0cc683f..6f9d508 100644
--- a/jsf/tests/org.eclipse.jst.jsf.designtime.tests/src/org/eclipse/jst/jsf/designtime/tests/DesignTimeFastTests.java
+++ b/jsf/tests/org.eclipse.jst.jsf.designtime.tests/src/org/eclipse/jst/jsf/designtime/tests/DesignTimeFastTests.java
@@ -1,14 +1,14 @@
 package org.eclipse.jst.jsf.designtime.tests;
 
 import org.eclipse.jst.jsf.designtime.tests.resources.FastResourceLocatorSuite;
-import org.eclipse.jst.jsf.test.util.junit4.FastTest;
-import org.junit.experimental.categories.Categories;
+import org.eclipse.jst.jsf.test.util.junit4.DualModeEnvironment;
 import org.junit.experimental.categories.Categories.IncludeCategory;
 import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
 import org.junit.runners.Suite.SuiteClasses;
 
-@RunWith(Categories.class)
-@IncludeCategory(FastTest.class)
+@RunWith(Suite.class)
+@IncludeCategory(DualModeEnvironment.class)
 @SuiteClasses(
 { FastResourceLocatorSuite.class})
 public class DesignTimeFastTests
diff --git a/jsf/tests/org.eclipse.jst.jsf.designtime.tests/src/org/eclipse/jst/jsf/designtime/tests/resources/ChangeTester.java b/jsf/tests/org.eclipse.jst.jsf.designtime.tests/src/org/eclipse/jst/jsf/designtime/tests/resources/ChangeTester.java
index e047c3b..37b213c 100644
--- a/jsf/tests/org.eclipse.jst.jsf.designtime.tests/src/org/eclipse/jst/jsf/designtime/tests/resources/ChangeTester.java
+++ b/jsf/tests/org.eclipse.jst.jsf.designtime.tests/src/org/eclipse/jst/jsf/designtime/tests/resources/ChangeTester.java
@@ -1,7 +1,6 @@
 package org.eclipse.jst.jsf.designtime.tests.resources;
 
 import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertTrue;
 import static org.junit.Assert.assertNotNull;
 
 import java.util.ArrayList;
@@ -10,14 +9,13 @@
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IFolder;
 import org.eclipse.core.resources.IResourceChangeEvent;
-import org.eclipse.jst.jsf.test.util.mock.MockFile;
+import org.eclipse.jst.jsf.test.util.mock.IWorkspaceContextWithEvents;
 import org.eclipse.jst.jsf.test.util.mock.MockResourceChangeEventFactory;
-import org.eclipse.jst.jsf.test.util.mock.MockWorkspaceContext;
 
 public abstract class ChangeTester<EVENTTYPE, CHANGETYPE>
 {
     protected final List<EVENTTYPE> _events = new ArrayList<EVENTTYPE>();
-    private final MockWorkspaceContext _context;
+    private final IWorkspaceContextWithEvents _context;
     private final MockResourceChangeEventFactory _eventFactory;
     private final IFolder _resourceRoot;
 
@@ -26,7 +24,7 @@
      * @param factory
      * @param resourceRoot
      */
-    public ChangeTester(final MockWorkspaceContext context,
+    public ChangeTester(final IWorkspaceContextWithEvents context,
             final MockResourceChangeEventFactory factory,
             final IFolder resourceRoot)
     {
@@ -40,7 +38,7 @@
         installListener();
         final IFile file = getFile(resourceId);
         final IResourceChangeEvent event = _eventFactory
-                .createSimpleFileChange((MockFile) file, true);
+                .createSimpleFileChange(file, true);
         _context.fireWorkspaceEvent(event);
         removeListener();
     }
@@ -50,7 +48,7 @@
         installListener();
         final IFile file = _resourceRoot.getFile(resourceId);
         final IResourceChangeEvent event = _eventFactory
-                .createSimpleFileAdded((MockFile) file);
+                .createSimpleFileAdded(file);
         _context.fireWorkspaceEvent(event);
         removeListener();
     }
@@ -59,7 +57,7 @@
     {
         final IFile file = _resourceRoot.getFile(resourceId);
         assertNotNull(file);
-        assertTrue(file.exists());
+//        assertTrue(file.exists());
         return file;
     }
 
@@ -67,7 +65,7 @@
     {
         final IFolder folder = _resourceRoot.getFolder(folderName);
         assertNotNull(folder);
-        assertTrue(folder.exists());
+//        assertTrue(folder.exists());
         return folder;
     }
 
@@ -81,7 +79,7 @@
         installListener();
         final IFile file = getFile(resourceId);
         final IResourceChangeEvent event = _eventFactory
-                .createSimpleFileRemove((MockFile) file);
+                .createSimpleFileRemove(file);
         _context.fireWorkspaceEvent(event);
         removeListener();
     }
diff --git a/jsf/tests/org.eclipse.jst.jsf.designtime.tests/src/org/eclipse/jst/jsf/designtime/tests/resources/FastResourceLocatorSuite.java b/jsf/tests/org.eclipse.jst.jsf.designtime.tests/src/org/eclipse/jst/jsf/designtime/tests/resources/FastResourceLocatorSuite.java
index 65a1707..2d41978 100644
--- a/jsf/tests/org.eclipse.jst.jsf.designtime.tests/src/org/eclipse/jst/jsf/designtime/tests/resources/FastResourceLocatorSuite.java
+++ b/jsf/tests/org.eclipse.jst.jsf.designtime.tests/src/org/eclipse/jst/jsf/designtime/tests/resources/FastResourceLocatorSuite.java
@@ -1,13 +1,13 @@
 package org.eclipse.jst.jsf.designtime.tests.resources;
 
-import org.eclipse.jst.jsf.test.util.junit4.FastTest;
-import org.junit.experimental.categories.Categories;
+import org.eclipse.jst.jsf.test.util.junit4.DualModeEnvironment;
 import org.junit.experimental.categories.Categories.IncludeCategory;
 import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
 import org.junit.runners.Suite.SuiteClasses;
 
-@RunWith(Categories.class)
-@IncludeCategory(FastTest.class)
+@RunWith(Suite.class)
+@IncludeCategory(DualModeEnvironment.class)
 @SuiteClasses({TestResourceIdentifierFactory.class,
     TestJarBasedJSFResource.class, TestJarBasedJSFResourceLocator.class,
     TestWorkspaceBasedJSFResource.class, TestWorkspaceBasedResourceLocator.class,
diff --git a/jsf/tests/org.eclipse.jst.jsf.designtime.tests/src/org/eclipse/jst/jsf/designtime/tests/resources/TestJarBasedJSFResourceLocator.java b/jsf/tests/org.eclipse.jst.jsf.designtime.tests/src/org/eclipse/jst/jsf/designtime/tests/resources/TestJarBasedJSFResourceLocator.java
index 37b28e5..6ff559a 100644
--- a/jsf/tests/org.eclipse.jst.jsf.designtime.tests/src/org/eclipse/jst/jsf/designtime/tests/resources/TestJarBasedJSFResourceLocator.java
+++ b/jsf/tests/org.eclipse.jst.jsf.designtime.tests/src/org/eclipse/jst/jsf/designtime/tests/resources/TestJarBasedJSFResourceLocator.java
@@ -10,6 +10,7 @@
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
 
+import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.jst.jsf.common.internal.locator.ILocatorChangeListener;
 import org.eclipse.jst.jsf.common.internal.resource.ContentTypeResolver;
@@ -18,8 +19,8 @@
 import org.eclipse.jst.jsf.designtime.internal.resources.IJSFResourceFragment;
 import org.eclipse.jst.jsf.designtime.internal.resources.JarBasedJSFResourceLocator;
 import org.eclipse.jst.jsf.test.util.junit4.NoPluginEnvironment;
+import org.eclipse.jst.jsf.test.util.mock.IWorkspaceContext;
 import org.eclipse.jst.jsf.test.util.mock.MockContentTypeManager;
-import org.eclipse.jst.jsf.test.util.mock.MockProject;
 import org.eclipse.jst.jsf.test.util.mock.MockWorkspaceContext;
 import org.eclipse.jst.jsf.test.util.mock.java.MockJDTWorkspaceContext;
 import org.eclipse.jst.jsf.test.util.mock.java.MockJavaCoreMediator;
@@ -33,9 +34,8 @@
     private IJarLocator _jarProvider;
     private JarBasedJSFResourceLocator _locator;
     private MockJDTWorkspaceContext _jdtContext;
-    private MockWorkspaceContext _wsContext;
-    private MockProject _project;
-//    private MockFile _jarIFile;
+    private IWorkspaceContext _wsContext;
+    private IProject _project;
 
     @SuppressWarnings("unchecked")
     @Before
diff --git a/jsf/tests/org.eclipse.jst.jsf.designtime.tests/src/org/eclipse/jst/jsf/designtime/tests/resources/TestWorkspaceBasedResourceLocator.java b/jsf/tests/org.eclipse.jst.jsf.designtime.tests/src/org/eclipse/jst/jsf/designtime/tests/resources/TestWorkspaceBasedResourceLocator.java
index 9bbede3..d369743 100644
--- a/jsf/tests/org.eclipse.jst.jsf.designtime.tests/src/org/eclipse/jst/jsf/designtime/tests/resources/TestWorkspaceBasedResourceLocator.java
+++ b/jsf/tests/org.eclipse.jst.jsf.designtime.tests/src/org/eclipse/jst/jsf/designtime/tests/resources/TestWorkspaceBasedResourceLocator.java
@@ -11,9 +11,10 @@
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.zip.ZipFile;
 
+import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.jst.jsf.common.internal.locator.ILocatorChangeListener;
@@ -35,24 +36,31 @@
 import org.eclipse.jst.jsf.designtime.internal.resources.WorkspaceJSFResourceLocator;
 import org.eclipse.jst.jsf.test.util.junit4.BugRegressionTest;
 import org.eclipse.jst.jsf.test.util.junit4.NoPluginEnvironment;
-import org.eclipse.jst.jsf.test.util.mock.MockContainer;
+import org.eclipse.jst.jsf.test.util.junit4.WorkspaceContext;
+import org.eclipse.jst.jsf.test.util.junit4.WorkspaceRunner;
+import org.eclipse.jst.jsf.test.util.mock.FileSystemZipLoader;
+import org.eclipse.jst.jsf.test.util.mock.IWorkspaceContextWithEvents;
 import org.eclipse.jst.jsf.test.util.mock.MockContentTypeManager;
-import org.eclipse.jst.jsf.test.util.mock.MockProject;
 import org.eclipse.jst.jsf.test.util.mock.MockResource;
 import org.eclipse.jst.jsf.test.util.mock.MockResourceChangeEventFactory;
 import org.eclipse.jst.jsf.test.util.mock.MockVirtualComponentQuery;
-import org.eclipse.jst.jsf.test.util.mock.MockWorkspaceContext;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
+import org.junit.rules.TestName;
+import org.junit.runner.RunWith;
 
+@RunWith(WorkspaceRunner.class)
 @Category(NoPluginEnvironment.class)
 public class TestWorkspaceBasedResourceLocator
 {
+    @Rule public TestName name = new TestName();
+
     private WorkspaceJSFResourceLocator _locator;
-    private MockWorkspaceContext _context;
-    private MockProject _project;
-    private MockContainer _webContentFolder;
+    @WorkspaceContext private IWorkspaceContextWithEvents _context;
+    private IProject _project;
+    private IContainer _webContentFolder;
     private IFolder _resourceRoot;
     private MockResourceChangeEventFactory _eventFactory;
     private ResourceIdentifierFactory _resourceIdFactory;
@@ -63,14 +71,13 @@
     @Before
     public void setUp() throws Exception
     {
-        _context = new MockWorkspaceContext();
         final File file = new File("./testdata/TestProject.zip");
         assertTrue(file.exists());
-        final ZipFile zipFile = new ZipFile(file);
+        final FileSystemZipLoader zipFileLoader = new FileSystemZipLoader(file, "Test2/");
         _project = _context.loadProject(
-                new Path("TestProjectTaglibDescriptor"), zipFile, "Test2/");
-        _project.loadAllMembers();
-        _webContentFolder = (MockContainer) _context.getResource(_project
+                new Path("TestProjectTaglibDescriptor_"+name.getMethodName()), zipFileLoader);
+        _context.ensureAllMembers(_project);
+        _webContentFolder = (IContainer) _context.getResource(_project
                 .getFullPath().append("/WebContent"));
         assertNotNull(_webContentFolder);
         _resourceRoot = _webContentFolder.getFolder(new Path("resources"));
@@ -311,7 +318,7 @@
         _locator.start(_project);
         // the workspace listener should get added event though the resource
         // root doesn't yet exist.
-        assertEquals(1, _context.getWorkspace().getListeners().size());
+        assertEquals(1, _context.getListeners().size());
         // simulate adding the folder
         ((MockResource) _resourceRoot).setExists(true);
         _changeTester.fireResourceFolderAdd("");
@@ -333,14 +340,14 @@
     public void testRemoveResourceRootAndAdd()
     {
         _locator.start(_project);
-        assertEquals(1, _context.getWorkspace().getListeners().size());
+        assertEquals(1, _context.getListeners().size());
         // delete the folder
         _changeTester.fireResourceFolderDelete("");
         // should get an event for root, lib333 and lib333/tag1.xhtml
         _changeTester.assertNumEvents(3);
         // should still be listening event after root is removed in case
         // it gets added back
-        assertEquals(1, _context.getWorkspace().getListeners().size());
+        assertEquals(1, _context.getListeners().size());
         // now add back the folder
         _changeTester.fireResourceFolderAdd("");
         _changeTester.assertNumEvents(1);
@@ -364,7 +371,7 @@
     public void testAddNoneResourceFolderToWebContent()
     {
         _locator.start(_project);
-        assertEquals(1, _context.getWorkspace().getListeners().size());
+        assertEquals(1, _context.getListeners().size());
         // delete the folder
         _changeTester.fireResourceFolderAdd("../foobar");
         _changeTester.assertNumEvents(0);
@@ -375,7 +382,7 @@
     public void testRemoveRecursiveFolder()
     {
         _locator.start(_project);
-        assertEquals(1, _context.getWorkspace().getListeners().size());
+        assertEquals(1, _context.getListeners().size());
         // delete the folder
         _changeTester.fireResourceFileDeleteRecusive("");
         final int expectedEvents = 3;
@@ -399,7 +406,7 @@
     public void testRenameFileInRootFolder()
     {
         _locator.start(_project);
-        assertEquals(1, _context.getWorkspace().getListeners().size());
+        assertEquals(1, _context.getListeners().size());
         _changeTester.fireResourceFileRename("../t11.jsp", "../t11.jspx");
         // the workspace resource locator shouldn't care if something outside
         // the resources sub-dir changes.
@@ -416,7 +423,7 @@
     	// condition with this regression test, but it was not previously
     	// covered
         _locator.start(_project);
-        assertEquals(1, _context.getWorkspace().getListeners().size());
+        assertEquals(1, _context.getListeners().size());
         _changeTester.fireResourceFolderAdd("mylib");
         // the mylib should register a library add
         _changeTester.assertNumEvents(1);
diff --git a/jsf/tests/org.eclipse.jst.jsf.metadata.tests/src/org/eclipse/jst/jsf/common/metadata/tests/updated/MetaDataModelManagerFactoryTests.java b/jsf/tests/org.eclipse.jst.jsf.metadata.tests/src/org/eclipse/jst/jsf/common/metadata/tests/updated/MetaDataModelManagerFactoryTests.java
index 1ec0ed4..9182423 100644
--- a/jsf/tests/org.eclipse.jst.jsf.metadata.tests/src/org/eclipse/jst/jsf/common/metadata/tests/updated/MetaDataModelManagerFactoryTests.java
+++ b/jsf/tests/org.eclipse.jst.jsf.metadata.tests/src/org/eclipse/jst/jsf/common/metadata/tests/updated/MetaDataModelManagerFactoryTests.java
@@ -16,6 +16,7 @@
 import org.eclipse.core.resources.IProject;
 import org.eclipse.jst.jsf.common.metadata.internal.IMetaDataModelManager;
 import org.eclipse.jst.jsf.common.metadata.internal.MetaDataModelManagerFactory;
+import org.eclipse.jst.jsf.test.util.mock.IWorkspaceContext;
 import org.eclipse.jst.jsf.test.util.mock.MockWorkspaceContext;
 
 public class MetaDataModelManagerFactoryTests extends TestCase {
@@ -23,7 +24,7 @@
 	private IProject _project;
 	
 	public void setUp() throws Exception {
-		MockWorkspaceContext context = new MockWorkspaceContext();
+		IWorkspaceContext context = new MockWorkspaceContext();
 		_project = context.createProject("MetaDataModelManagerFactoryTests"+"_"+getName());
 	}
 
diff --git a/jsf/tests/org.eclipse.jst.jsf.metadata.tests/src/org/eclipse/jst/jsf/common/metadata/tests/updated/MetaDataQueryFactoryTests.java b/jsf/tests/org.eclipse.jst.jsf.metadata.tests/src/org/eclipse/jst/jsf/common/metadata/tests/updated/MetaDataQueryFactoryTests.java
index 437085b..e1590b8 100644
--- a/jsf/tests/org.eclipse.jst.jsf.metadata.tests/src/org/eclipse/jst/jsf/common/metadata/tests/updated/MetaDataQueryFactoryTests.java
+++ b/jsf/tests/org.eclipse.jst.jsf.metadata.tests/src/org/eclipse/jst/jsf/common/metadata/tests/updated/MetaDataQueryFactoryTests.java
@@ -20,6 +20,7 @@
 import org.eclipse.jst.jsf.common.metadata.query.internal.MetaDataQueryContextFactory;
 import org.eclipse.jst.jsf.common.metadata.query.internal.MetaDataQueryFactory;
 import org.eclipse.jst.jsf.common.metadata.query.internal.taglib.ITaglibDomainMetaDataQuery;
+import org.eclipse.jst.jsf.test.util.mock.IWorkspaceContext;
 import org.eclipse.jst.jsf.test.util.mock.MockWorkspaceContext;
 import org.junit.Test;
 
@@ -28,7 +29,7 @@
 	private IProject _project;
 	
 	public void setUp() throws Exception {
-		MockWorkspaceContext context = new MockWorkspaceContext();
+		IWorkspaceContext context = new MockWorkspaceContext();
 		_project = context.createProject("MetaDataQueryFactoryTests"+"_"+getName());
 	}
 
diff --git a/jsf/tests/org.eclipse.jst.jsf.metadata.tests/src/org/eclipse/jst/jsf/metadata/tests/taglibprocessing/JSFHTMLTestCase.java b/jsf/tests/org.eclipse.jst.jsf.metadata.tests/src/org/eclipse/jst/jsf/metadata/tests/taglibprocessing/JSFHTMLTestCase.java
index b15c217..e752e9b 100644
--- a/jsf/tests/org.eclipse.jst.jsf.metadata.tests/src/org/eclipse/jst/jsf/metadata/tests/taglibprocessing/JSFHTMLTestCase.java
+++ b/jsf/tests/org.eclipse.jst.jsf.metadata.tests/src/org/eclipse/jst/jsf/metadata/tests/taglibprocessing/JSFHTMLTestCase.java
@@ -13,6 +13,7 @@
 
 import java.util.List;
 
+import org.eclipse.core.resources.IProject;
 import org.eclipse.jst.jsf.common.metadata.Entity;
 import org.eclipse.jst.jsf.common.metadata.Model;
 import org.eclipse.jst.jsf.common.metadata.Trait;
@@ -31,7 +32,6 @@
 import org.eclipse.jst.jsf.tagdisplay.internal.paletteinfos.PaletteInfo;
 import org.eclipse.jst.jsf.tagdisplay.internal.paletteinfos.PaletteInfos;
 import org.eclipse.jst.jsf.tagdisplay.internal.paletteinfos.TagCreationInfo;
-import org.eclipse.jst.jsf.test.util.mock.MockProject;
 import org.eclipse.jst.jsf.test.util.mock.MockWorkspaceContext;
 
 public class JSFHTMLTestCase extends JSPTestCase implements IJSFRuntimeRequiredV11{
@@ -100,7 +100,7 @@
 	
 	public void testQuery() throws Exception {
 		//tests querying JSF_HTML using new APIs
-		MockProject project = new MockWorkspaceContext().createProject("test"); 
+		IProject project = new MockWorkspaceContext().createProject("test"); 
 		IMetaDataDomainContext context = MetaDataQueryContextFactory.getInstance().createTaglibDomainModelContext(project);
 		ITaglibDomainMetaDataQuery query = MetaDataQueryFactory.getInstance().createQuery(context); 
 		
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/TestUtil.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/TestUtil.java
index 72d5922..31b83d2 100644
--- a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/TestUtil.java
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/TestUtil.java
@@ -13,6 +13,7 @@
 
 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -53,8 +54,6 @@
  */
 public class TestUtil
 {
-
-
     /**
      * 
      * @param prjname
@@ -66,13 +65,21 @@
     public static IProject createProjectFromZip(Bundle bundle, String prjname,
             String path) throws Exception
     {
-
         URL url = FileLocator.find(bundle, new Path(path), null);
         // if this fails, it most likely that path is wrong.
         Assert.assertNotNull(url);
         return createProjectFromZip(prjname, url);
     }
 
+    public static IProject createProjectFromZip(File file, String prjname)
+            throws Exception
+    {
+        URL url = file.toURL();
+        // if this fails, it most likely that path is wrong.
+        Assert.assertNotNull(url);
+        return createProjectFromZip(prjname, url);
+    }
+
     /**
      * build a project
      * 
@@ -97,11 +104,9 @@
      * @param dir
      * @throws Exception
      */
-    private static void expandZip(URL url, IContainer dir)
-            throws Exception
+    private static void expandZip(URL url, IContainer dir) throws Exception
     {
         ZipInputStream zis = null;
-
         try
         {
             // first, count number of items in zip file
@@ -126,8 +131,7 @@
                         ensurePath(folder);
                         folder.create(true, true, null);
                     }
-                } 
-                else
+                } else
                 {
                     IFile file = dir.getFile(new Path(name));
                     ensurePath(file);
@@ -141,7 +145,6 @@
                         file.create(new ZipStreamWrapper(zis), true, null);
                     }
                 }
-
                 ze = zis.getNextEntry();
             }
         } finally
@@ -157,14 +160,14 @@
         }
     }
 
-    private static String getPrefix(ZipInputStream zipStream) throws IOException
+    private static String getPrefix(ZipInputStream zipStream)
+            throws IOException
     {
         ZipEntry ze = zipStream.getNextEntry();
         while (ze != null)
         {
             String name = ze.getName();
-            if (name != null && name.endsWith(".project")
-                    && !ze.isDirectory())
+            if (name != null && name.endsWith(".project") && !ze.isDirectory())
             {
                 int index = name.lastIndexOf(".project");
                 return name.substring(0, index);
@@ -201,14 +204,11 @@
      * 
      * @return
      */
-    public static IFile copyFile(Bundle bundle, IProject project, String targetPath,
-            String sourcePath) throws Exception
+    public static IFile copyFile(Bundle bundle, IProject project,
+            String targetPath, String sourcePath) throws Exception
     {
-
-        URL url = FileLocator.find(bundle,
-                new Path(sourcePath), null);
+        URL url = FileLocator.find(bundle, new Path(sourcePath), null);
         InputStream stream = url.openStream();
-
         IFile file = null;
         IPath path = new Path(sourcePath);
         if (targetPath != null && targetPath.length() > 0)
@@ -219,7 +219,6 @@
         {
             file = project.getFile(path.lastSegment());
         }
-
         if (!file.exists())
         {
             ensurePath(file);
@@ -228,7 +227,6 @@
         {
             file.setContents(stream, IFile.FORCE, null);
         }
-
         return file;
     }
 
@@ -246,8 +244,8 @@
     {
         IFile file = project.getFile(filePath);
         ensurePath(file);
-        ByteArrayInputStream stream = new ByteArrayInputStream(content
-                .getBytes());
+        ByteArrayInputStream stream = new ByteArrayInputStream(
+                content.getBytes());
         file.create(stream, true, null);
         return file;
     }
@@ -263,7 +261,6 @@
      */
     public static String getFileAsString(String path) throws Exception
     {
-
         URL url = FileLocator.find(Activator.getDefault().getBundle(),
                 new Path(path), null);
         InputStream stream = url.openStream();
@@ -282,38 +279,43 @@
     }
 
     /**
-	 * create a project from a zip file.
-	 * 
-	 * @param prjname
-	 * @param zipStream
-	 * @throws Exception
-	 */
-	private static IProject createProjectFromZip(final String prjname,
-			final URL url) throws Exception {
-		final IProject[] holder = new IProject[1];
-		IWorkspaceRunnable r = new IWorkspaceRunnable() {
-			public void run(IProgressMonitor monitor) throws CoreException {
-				IProject prj = ResourcesPlugin.getWorkspace().getRoot()
-						.getProject(prjname);
-				if (!prj.exists()) {
-					prj.create(null);
-				}
-				prj.open(null);
-				ValidationFramework.getDefault().suspendValidation(prj, true);
-				try {
-					expandZip(url, prj);
-				} catch (Exception ex) {
-					throw new CoreException(new Status(0,
-							Activator.PLUGIN_ID, 0, ex
-									.getMessage(), ex));
-				}
-				holder[0] = prj;
-			}
-		};
+     * create a project from a zip file.
+     * 
+     * @param prjname
+     * @param zipStream
+     * @throws Exception
+     */
+    private static IProject createProjectFromZip(final String prjname,
+            final URL url) throws Exception
+    {
+        final IProject[] holder = new IProject[1];
+        IWorkspaceRunnable r = new IWorkspaceRunnable()
+        {
+            public void run(IProgressMonitor monitor) throws CoreException
+            {
+                IProject prj = ResourcesPlugin.getWorkspace().getRoot()
+                        .getProject(prjname);
+                if (!prj.exists())
+                {
+                    prj.create(null);
+                }
+                prj.open(null);
+                ValidationFramework.getDefault().suspendValidation(prj, true);
+                try
+                {
+                    expandZip(url, prj);
+                } catch (Exception ex)
+                {
+                    throw new CoreException(new Status(0, Activator.PLUGIN_ID,
+                            0, ex.getMessage(), ex));
+                }
+                holder[0] = prj;
+            }
+        };
         ResourcesPlugin.getWorkspace().run(r, null);
-		return holder[0];
-	}
-	
+        return holder[0];
+    }
+
     public static String removeAllWhitespace(String s)
     {
         StringBuffer buffer = new StringBuffer(s.length());
@@ -326,6 +328,7 @@
         }
         return buffer.toString();
     }
+
     /**
      * remove resource, following schedule rule.
      * 
@@ -341,7 +344,6 @@
         }
         Job job = new Job("DeleteProject")
         {
-
             protected IStatus run(IProgressMonitor monitor)
             {
                 try
@@ -353,12 +355,10 @@
                 }
                 return Status.OK_STATUS;
             }
-
         };
         job.setPriority(Job.SHORT);
         job.setRule(ResourcesPlugin.getWorkspace().getRoot());
         job.schedule();
-
         // wait
         try
         {
@@ -373,8 +373,9 @@
     public static boolean verifyProjectStatus(final IProject project,
             final boolean isOpenCondition, final int waitTimeInMs)
     {
-        return TestUtil.waitForCondition(createProjectStatusCondition(project,
-                isOpenCondition), waitTimeInMs, 20);
+        return TestUtil.waitForCondition(
+                createProjectStatusCondition(project, isOpenCondition),
+                waitTimeInMs, 20);
     }
 
     public static TestCondition createProjectStatusCondition(
@@ -413,14 +414,12 @@
         {
             Assert.fail("Your wait interval is less than 1");
         }
-
         do
         {
             if (condition.test())
             {
                 return true;
             }
-
             try
             {
                 Thread.sleep(waitPerInterval);
@@ -429,7 +428,6 @@
                 // ignore.
             }
         } while (curIteration++ < numIntervals);
-
         // if we get to here, then the condition was not satisified in the
         // time alloted
         return false;
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/junit4/DualModeEnvironment.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/junit4/DualModeEnvironment.java
new file mode 100644
index 0000000..7935264
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/junit4/DualModeEnvironment.java
@@ -0,0 +1,12 @@
+package org.eclipse.jst.jsf.test.util.junit4;
+
+/**
+ * This class should never be used directly. It is used to mark JUnit test
+ * classes that can run either with or without a plugin environment.
+ * 
+ * Such tests may require a special test runner such as {@link WorkspaceRunner}
+ * 
+ */
+public interface DualModeEnvironment extends NoPluginEnvironment
+{
+}
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/junit4/RealWorkspaceContext.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/junit4/RealWorkspaceContext.java
new file mode 100644
index 0000000..290db12
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/junit4/RealWorkspaceContext.java
@@ -0,0 +1,916 @@
+package org.eclipse.jst.jsf.test.util.junit4;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.eclipse.core.internal.events.BuildManager;
+import org.eclipse.core.internal.events.ILifecycleListener;
+import org.eclipse.core.internal.events.NotificationManager;
+import org.eclipse.core.internal.localstore.FileSystemResourceManager;
+import org.eclipse.core.internal.properties.IPropertyManager;
+import org.eclipse.core.internal.refresh.RefreshManager;
+import org.eclipse.core.internal.resources.AliasManager;
+import org.eclipse.core.internal.resources.CharsetManager;
+import org.eclipse.core.internal.resources.ContentDescriptionManager;
+import org.eclipse.core.internal.resources.LocalMetaArea;
+import org.eclipse.core.internal.resources.MarkerManager;
+import org.eclipse.core.internal.resources.NatureManager;
+import org.eclipse.core.internal.resources.Resource;
+import org.eclipse.core.internal.resources.ResourceInfo;
+import org.eclipse.core.internal.resources.SaveManager;
+import org.eclipse.core.internal.resources.WorkManager;
+import org.eclipse.core.internal.resources.Workspace;
+import org.eclipse.core.internal.resources.WorkspaceDescription;
+import org.eclipse.core.internal.watson.ElementTree;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFilterMatcherDescriptor;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IPathVariableManager;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IProjectNatureDescriptor;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceRuleFactory;
+import org.eclipse.core.resources.ISaveParticipant;
+import org.eclipse.core.resources.ISavedState;
+import org.eclipse.core.resources.ISynchronizer;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceDescription;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.resources.WorkspaceLock;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.SafeRunner;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.jst.jsf.test.util.Activator;
+import org.eclipse.jst.jsf.test.util.JSFTestUtil;
+import org.eclipse.jst.jsf.test.util.ProjectTestEnvironment;
+import org.eclipse.jst.jsf.test.util.TestUtil;
+import org.eclipse.jst.jsf.test.util.mock.AbstractWorkspaceContextWithEvents;
+import org.eclipse.swt.widgets.Display;
+
+@SuppressWarnings("deprecation")
+public class RealWorkspaceContext extends AbstractWorkspaceContextWithEvents
+{
+    private DecoratedWorkspace _workspace;
+    private final CopyOnWriteArrayList<IResourceChangeListener> _listeners;
+    private final Workspace _actualWorkspace;
+
+    public RealWorkspaceContext()
+    {
+        _listeners = new CopyOnWriteArrayList<IResourceChangeListener>();
+        _actualWorkspace = (Workspace) ResourcesPlugin.getWorkspace();
+        _workspace = new DecoratedWorkspace(this, _actualWorkspace, _listeners);
+    }
+
+    @Override
+    protected void doInit() throws Exception
+    {
+        setWorkspace(_workspace);
+        setWorkspace(_actualWorkspace.getRoot(), _workspace);
+    }
+
+    private static void setWorkspace(final IResource root,
+            final IWorkspace workspace) throws Exception
+    {
+        final Class<Resource> rootClass = Resource.class;
+        final Field declaredField = rootClass.getDeclaredField("workspace");
+        declaredField.setAccessible(true);
+        declaredField.set(root, workspace);
+    }
+
+    private void setWorkspace(final IWorkspace workspace) throws Exception
+    {
+        final Class<ResourcesPlugin> resPlugin = ResourcesPlugin.class;
+        final Field declaredField = resPlugin.getDeclaredField("workspace");
+        declaredField.setAccessible(true);
+        declaredField.set(null, workspace);
+    }
+
+    @Override
+    public void doDispose() throws Exception
+    {
+        setWorkspace(_actualWorkspace.getRoot(), _actualWorkspace);
+        setWorkspace(_workspace._ws);
+        _workspace = null;
+    }
+
+    public IWorkspace getWorkspace()
+    {
+        assertInitialized();
+        return _workspace;
+    }
+
+    public IResource getResource(final IPath path)
+    {
+        assertInitialized();
+        final IWorkspaceRoot root = _workspace.getRoot();
+        final IResource res = root.findMember(path, false);
+        if (res != null && res.exists())
+        {
+            return res;
+        }
+        return null;
+    }
+
+    public IFile getFile(final IPath path)
+    {
+        return (IFile) getResource(path);
+    }
+
+    public IProject getProject(final IPath path)
+    {
+        return (IProject) getResource(path);
+    }
+
+    public IProject createProject(final String baseId)
+    {
+        assertInitialized();
+        int suffix = 0;
+        String projectName = null;
+        do
+        {
+            projectName = baseId + "_" + suffix++;
+        } while ((_workspace.getRoot().getProject(projectName).exists()));
+        assertNotNull(projectName);
+        return createProject2(projectName);
+    }
+
+    private IProject createProject2(final String projectName)
+    {
+        assertInitialized();
+        final ProjectTestEnvironment testEnv = new ProjectTestEnvironment(
+                projectName);
+        assertTrue(testEnv.createProject(false));
+        return testEnv.getTestProject();
+    }
+
+    public IProject createProject(final IPath path)
+    {
+        return createProject2(path.toString());
+    }
+
+    public IProject loadProject(final IPath path,
+            final ZipFileLoader zipFileLoader) throws Exception
+    {
+        assertInitialized();
+        assertFalse(_workspace.getRoot().getProject(path.toString()).exists());
+        return TestUtil.createProjectFromZip(zipFileLoader.getFile(),
+                path.toString());
+    }
+
+    public IFile attachFile(final IProject project,
+            final IPath projectRelativePath, final File file) throws Exception
+    {
+        assertInitialized();
+        final ByteArrayOutputStream stream = JSFTestUtil.loadFromFile(file);
+        return TestUtil.createFile(project, projectRelativePath.toString(),
+                stream.toString());
+    }
+
+    public void fireWorkspaceEvent(final IResourceChangeEvent event)
+    {
+        assertInitialized();
+        for (final IResourceChangeListener listener : _listeners)
+        {
+            SafeRunner.run(new ISafeRunnable()
+            {
+                public void run() throws Exception
+                {
+                    listener.resourceChanged(event);
+                }
+
+                public void handleException(final Throwable exception)
+                {
+                    Activator.log("While processing mock resource event",
+                            exception);
+                }
+            });
+        }
+    }
+
+    public List<IResourceChangeListener> getListeners()
+    {
+        assertInitialized();
+        return Collections.unmodifiableList(_listeners);
+    }
+    
+    public List<IResourceChangeListener> getListeners(final List<Class<? extends IResourceChangeListener>>  includeListeners)
+    {
+        List<IResourceChangeListener> listeners = new ArrayList<IResourceChangeListener>();
+        for (final IResourceChangeListener listener : getListeners())
+        {
+            SEARCH_CLASSES: for (final Class<? extends IResourceChangeListener> clazz : includeListeners)
+            {
+                if (clazz.isAssignableFrom(listener.getClass()))
+                {
+                    listeners.add(listener);
+                    break SEARCH_CLASSES;
+                }
+            }
+        }
+        return listeners;
+    }
+
+    @Override
+    protected void assertInitialized()
+    {
+        super.assertInitialized();
+    }
+
+    public void ensureAllMembers(final IProject project) throws Exception
+    {
+        // do nothing; the real workspace always is "loaded".
+    }
+
+    private static class DecoratedWorkspace extends Workspace
+    {
+        private final Workspace _ws;
+        private final List<IResourceChangeListener> _listeners;
+        private final RealWorkspaceContext _wsContext;
+
+        /**
+         * @param ws
+         * @param listeners
+         */
+        public DecoratedWorkspace(final RealWorkspaceContext wsContext,
+                final Workspace ws,
+                final List<IResourceChangeListener> listeners)
+        {
+            _wsContext = wsContext;
+            _ws = ws;
+            _listeners = listeners;
+        }
+
+        @Override
+        protected void flushBuildOrder()
+        {
+            invokeOnWorkspace("flushBuildOrder", new Class<?>[0], new Object[0]);
+        }
+
+        private void invokeOnWorkspace(final String name,
+                final Class<?>[] classes, final Object[] values)
+        {
+            try
+            {
+                final Class<Workspace> workspaceClass = Workspace.class;
+                final Method declaredMethod = workspaceClass.getDeclaredMethod(
+                        name, classes);
+                declaredMethod.setAccessible(true);
+                declaredMethod.invoke(_ws, values);
+            } catch (final SecurityException e)
+            {
+                throw new RuntimeException(e);
+            } catch (final NoSuchMethodException e)
+            {
+                throw new RuntimeException(e);
+            } catch (final IllegalArgumentException e)
+            {
+                throw new RuntimeException(e);
+            } catch (final IllegalAccessException e)
+            {
+                throw new RuntimeException(e);
+            } catch (final InvocationTargetException e)
+            {
+                throw new RuntimeException(e);
+            }
+        }
+
+        @Override
+        public void addLifecycleListener(final ILifecycleListener listener)
+        {
+            _ws.addLifecycleListener(listener);
+        }
+
+        @Override
+        public void addResourceChangeListener(
+                final IResourceChangeListener listener)
+        {
+            addResourceChangeListener(listener, IResourceChangeEvent.PRE_CLOSE
+                    | IResourceChangeEvent.PRE_DELETE
+                    | IResourceChangeEvent.POST_CHANGE);
+        }
+
+        @Override
+        public void addResourceChangeListener(
+                final IResourceChangeListener listener, final int eventMask)
+        {
+            _wsContext.assertInitialized();
+            if (Thread.currentThread() == Display.getDefault().getThread())
+            {
+                _listeners.add(listener);
+            }
+            _ws.addResourceChangeListener(listener, eventMask);
+        }
+
+        @Override
+        public ISavedState addSaveParticipant(final Plugin plugin,
+                final ISaveParticipant participant) throws CoreException
+        {
+            return _ws.addSaveParticipant(plugin, participant);
+        }
+
+        @Override
+        public ISavedState addSaveParticipant(final String pluginId,
+                final ISaveParticipant participant) throws CoreException
+        {
+            return _ws.addSaveParticipant(pluginId, participant);
+        }
+
+        @Override
+        public void beginOperation(final boolean createNewTree)
+                throws CoreException
+        {
+            _ws.beginOperation(createNewTree);
+        }
+
+        @Override
+        public void broadcastBuildEvent(final Object source, final int type,
+                final int buildTrigger)
+        {
+            _ws.broadcastBuildEvent(source, type, buildTrigger);
+        }
+
+        @Override
+        public void broadcastPostChange()
+        {
+            _ws.broadcastPostChange();
+        }
+
+        @Override
+        public void build(final int trigger, final IProgressMonitor monitor)
+                throws CoreException
+        {
+            _ws.build(trigger, monitor);
+        }
+
+        @Override
+        public void checkpoint(final boolean build)
+        {
+            _ws.checkpoint(build);
+        }
+
+        @Override
+        public void close(final IProgressMonitor monitor) throws CoreException
+        {
+            _ws.close(monitor);
+        }
+
+        @Override
+        public IProject[][] computePrerequisiteOrder(final IProject[] targets)
+        {
+            return _ws.computePrerequisiteOrder(targets);
+        }
+
+        @Override
+        public ProjectOrder computeProjectOrder(final IProject[] projects)
+        {
+            return _ws.computeProjectOrder(projects);
+        }
+
+        @Override
+        public IStatus copy(final IResource[] resources,
+                final IPath destination, final boolean force,
+                final IProgressMonitor monitor) throws CoreException
+        {
+            return _ws.copy(resources, destination, force, monitor);
+        }
+
+        @Override
+        public IStatus copy(final IResource[] resources,
+                final IPath destination, final int updateFlags,
+                final IProgressMonitor monitor) throws CoreException
+        {
+            return _ws.copy(resources, destination, updateFlags, monitor);
+        }
+
+        @Override
+        public int countResources(final IPath root, final int depth,
+                final boolean phantom)
+        {
+            return _ws.countResources(root, depth, phantom);
+        }
+
+        @Override
+        public ResourceInfo createResource(final IResource resource,
+                final boolean phantom) throws CoreException
+        {
+            return _ws.createResource(resource, phantom);
+        }
+
+        @Override
+        public ResourceInfo createResource(final IResource resource,
+                final int updateFlags) throws CoreException
+        {
+            return _ws.createResource(resource, updateFlags);
+        }
+
+        @Override
+        public ResourceInfo createResource(final IResource resource,
+                final ResourceInfo info, final boolean phantom,
+                final boolean overwrite, final boolean keepSyncInfo)
+                throws CoreException
+        {
+            return _ws.createResource(resource, info, phantom, overwrite,
+                    keepSyncInfo);
+        }
+
+        @Override
+        public IStatus delete(final IResource[] resources, final boolean force,
+                final IProgressMonitor monitor) throws CoreException
+        {
+            return _ws.delete(resources, force, monitor);
+        }
+
+        @Override
+        public IStatus delete(final IResource[] resources,
+                final int updateFlags, final IProgressMonitor monitor)
+                throws CoreException
+        {
+            return _ws.delete(resources, updateFlags, monitor);
+        }
+
+        @Override
+        public void deleteMarkers(final IMarker[] markers) throws CoreException
+        {
+            _ws.deleteMarkers(markers);
+        }
+
+        @Override
+        public void endOperation(final ISchedulingRule rule,
+                final boolean build, final IProgressMonitor monitor)
+                throws CoreException
+        {
+            _ws.endOperation(rule, build, monitor);
+        }
+
+//        @Override
+//        public boolean equals(final Object obj)
+//        {
+//            return _ws.equals(obj);
+//        }
+
+        @Override
+        public Object getAdapter(
+                @SuppressWarnings("rawtypes") final Class adapter)
+        {
+            return _ws.getAdapter(adapter);
+        }
+
+        @Override
+        public void forgetSavedTree(final String pluginId)
+        {
+            _ws.forgetSavedTree(pluginId);
+        }
+
+        @Override
+        public AliasManager getAliasManager()
+        {
+            return _ws.getAliasManager();
+        }
+
+        @Override
+        public BuildManager getBuildManager()
+        {
+            return _ws.getBuildManager();
+        }
+
+        @Override
+        public IProject[] getBuildOrder()
+        {
+            return _ws.getBuildOrder();
+        }
+
+        @Override
+        public CharsetManager getCharsetManager()
+        {
+            return _ws.getCharsetManager();
+        }
+
+        @Override
+        public ContentDescriptionManager getContentDescriptionManager()
+        {
+            return _ws.getContentDescriptionManager();
+        }
+
+        @Override
+        @SuppressWarnings("rawtypes")
+        public Map getDanglingReferences()
+        {
+            return _ws.getDanglingReferences();
+        }
+
+        @Override
+        public IWorkspaceDescription getDescription()
+        {
+            return _ws.getDescription();
+        }
+
+        @Override
+        public ElementTree getElementTree()
+        {
+            return _ws.getElementTree();
+        }
+
+        @Override
+        public FileSystemResourceManager getFileSystemManager()
+        {
+            return _ws.getFileSystemManager();
+        }
+
+        @Override
+        public MarkerManager getMarkerManager()
+        {
+            return _ws.getMarkerManager();
+        }
+
+        @Override
+        public LocalMetaArea getMetaArea()
+        {
+            return _ws.getMetaArea();
+        }
+
+        @Override
+        public IFilterMatcherDescriptor getFilterMatcherDescriptor(
+                final String filterMAtcherId)
+        {
+            return _ws.getFilterMatcherDescriptor(filterMAtcherId);
+        }
+
+        @Override
+        public IFilterMatcherDescriptor[] getFilterMatcherDescriptors()
+        {
+            return _ws.getFilterMatcherDescriptors();
+        }
+
+        @Override
+        public IProjectNatureDescriptor getNatureDescriptor(
+                final String natureId)
+        {
+            return _ws.getNatureDescriptor(natureId);
+        }
+
+        @Override
+        public IProjectNatureDescriptor[] getNatureDescriptors()
+        {
+            return _ws.getNatureDescriptors();
+        }
+
+        @Override
+        public NatureManager getNatureManager()
+        {
+            return _ws.getNatureManager();
+        }
+
+        @Override
+        public NotificationManager getNotificationManager()
+        {
+            return _ws.getNotificationManager();
+        }
+
+        @Override
+        public IPathVariableManager getPathVariableManager()
+        {
+            return _ws.getPathVariableManager();
+        }
+
+        @Override
+        public IPropertyManager getPropertyManager()
+        {
+            return _ws.getPropertyManager();
+        }
+
+        @Override
+        public RefreshManager getRefreshManager()
+        {
+            return _ws.getRefreshManager();
+        }
+
+        @Override
+        public ResourceInfo getResourceInfo(final IPath path,
+                final boolean phantom, final boolean mutable)
+        {
+            return _ws.getResourceInfo(path, phantom, mutable);
+        }
+
+        @Override
+        public IWorkspaceRoot getRoot()
+        {
+            return _ws.getRoot();
+        }
+
+        @Override
+        public IResourceRuleFactory getRuleFactory()
+        {
+            return _ws.getRuleFactory();
+        }
+
+        @Override
+        public SaveManager getSaveManager()
+        {
+            return _ws.getSaveManager();
+        }
+
+        @Override
+        public ISynchronizer getSynchronizer()
+        {
+            return _ws.getSynchronizer();
+        }
+
+        @Override
+        public WorkManager getWorkManager() throws CoreException
+        {
+            return _ws.getWorkManager();
+        }
+
+        @Override
+        public int hashCode()
+        {
+            return _ws.hashCode();
+        }
+
+        @Override
+        public WorkspaceDescription internalGetDescription()
+        {
+            return _ws.internalGetDescription();
+        }
+
+        @Override
+        public boolean isAutoBuilding()
+        {
+            return _ws.isAutoBuilding();
+        }
+
+        @Override
+        public boolean isOpen()
+        {
+            return _ws.isOpen();
+        }
+
+        @Override
+        public boolean isTreeLocked()
+        {
+            return _ws.isTreeLocked();
+        }
+
+        @Override
+        public IProjectDescription loadProjectDescription(
+                final InputStream stream) throws CoreException
+        {
+            return _ws.loadProjectDescription(stream);
+        }
+
+        @Override
+        public IProjectDescription loadProjectDescription(final IPath path)
+                throws CoreException
+        {
+            return _ws.loadProjectDescription(path);
+        }
+
+        @Override
+        public IStatus move(final IResource[] resources,
+                final IPath destination, final boolean force,
+                final IProgressMonitor monitor) throws CoreException
+        {
+            return _ws.move(resources, destination, force, monitor);
+        }
+
+        @Override
+        public IStatus move(final IResource[] resources,
+                final IPath destination, final int updateFlags,
+                final IProgressMonitor monitor) throws CoreException
+        {
+            return _ws.move(resources, destination, updateFlags, monitor);
+        }
+
+        @Override
+        public IProjectDescription newProjectDescription(
+                final String projectName)
+        {
+            return _ws.newProjectDescription(projectName);
+        }
+
+        @Override
+        public Resource newResource(final IPath path, final int type)
+        {
+            Resource res = _ws.newResource(path, type);
+            try
+            {
+                setWorkspace(res, this);
+            } catch (Exception e)
+            {
+                throw new RuntimeException(e);
+            }
+            return res;
+        }
+
+        @Override
+        public ElementTree newWorkingTree()
+        {
+            return _ws.newWorkingTree();
+        }
+
+        @Override
+        public IStatus open(final IProgressMonitor monitor)
+                throws CoreException
+        {
+            return _ws.open(monitor);
+        }
+
+        @Override
+        public void prepareOperation(final ISchedulingRule rule,
+                final IProgressMonitor monitor) throws CoreException
+        {
+            _ws.prepareOperation(rule, monitor);
+        }
+
+        @Override
+        public void removeResourceChangeListener(
+                final IResourceChangeListener listener)
+        {
+            _wsContext.assertInitialized();
+            if (Thread.currentThread() == Display.getDefault().getThread())
+            {
+                _listeners.remove(listener);
+            }
+            _ws.removeResourceChangeListener(listener);
+        }
+
+        @Override
+        public void removeSaveParticipant(final Plugin plugin)
+        {
+            _ws.removeSaveParticipant(plugin);
+        }
+
+        @Override
+        public void removeSaveParticipant(final String pluginId)
+        {
+            _ws.removeSaveParticipant(pluginId);
+        }
+
+        @Override
+        public void run(final IWorkspaceRunnable action,
+                final IProgressMonitor monitor) throws CoreException
+        {
+            _ws.run(action, monitor);
+        }
+
+        @Override
+        public void run(final IWorkspaceRunnable action,
+                final ISchedulingRule rule, final int options,
+                final IProgressMonitor monitor) throws CoreException
+        {
+            _ws.run(action, rule, options, monitor);
+        }
+
+        @Override
+        public IStatus save(final boolean full, final IProgressMonitor monitor)
+                throws CoreException
+        {
+            return _ws.save(full, monitor);
+        }
+
+        @Override
+        public IStatus save(final boolean full,
+                final boolean keepConsistencyWhenCanceled,
+                final IProgressMonitor monitor) throws CoreException
+        {
+            return _ws.save(full, keepConsistencyWhenCanceled, monitor);
+        }
+
+        @Override
+        public void setCrashed(final boolean value)
+        {
+            _ws.setCrashed(value);
+        }
+
+        @Override
+        public void setDescription(final IWorkspaceDescription value)
+        {
+            _ws.setDescription(value);
+        }
+
+        @Override
+        public void setTreeLocked(final boolean locked)
+        {
+            _ws.setTreeLocked(locked);
+        }
+
+        @Override
+        public void setWorkspaceLock(final WorkspaceLock lock)
+        {
+            _ws.setWorkspaceLock(lock);
+        }
+
+        @Override
+        public String[] sortNatureSet(final String[] natureIds)
+        {
+            return _ws.sortNatureSet(natureIds);
+        }
+
+        @Override
+        public String toDebugString()
+        {
+            return _ws.toDebugString();
+        }
+
+        @Override
+        public String toString()
+        {
+            return _ws.toString();
+        }
+
+        @Override
+        public URI transferVariableDefinition(final IResource source,
+                final IResource dest, final URI sourceURI) throws CoreException
+        {
+            return _ws.transferVariableDefinition(source, dest, sourceURI);
+        }
+
+        @Override
+        public void updateModificationStamp(final ResourceInfo info)
+        {
+            info.incrementModificationStamp();
+        }
+
+        @Override
+        public IStatus validateEdit(final IFile[] files, final Object context)
+        {
+            return _ws.validateEdit(files, context);
+        }
+
+        @Override
+        public IStatus validateLinkLocation(final IResource resource,
+                final IPath unresolvedLocation)
+        {
+            return _ws.validateLinkLocation(resource, unresolvedLocation);
+        }
+
+        @Override
+        public IStatus validateLinkLocationURI(final IResource resource,
+                final URI unresolvedLocation)
+        {
+            return _ws.validateLinkLocationURI(resource, unresolvedLocation);
+        }
+
+        @Override
+        public IStatus validateName(final String segment, final int type)
+        {
+            return _ws.validateName(segment, type);
+        }
+
+        @Override
+        public IStatus validateNatureSet(final String[] natureIds)
+        {
+            return _ws.validateNatureSet(natureIds);
+        }
+
+        @Override
+        public IStatus validatePath(final String path, final int type)
+        {
+            return _ws.validatePath(path, type);
+        }
+
+        @Override
+        public IStatus validateProjectLocation(final IProject context,
+                final IPath location)
+        {
+            return _ws.validateProjectLocation(context, location);
+        }
+
+        @Override
+        public IStatus validateProjectLocationURI(final IProject project,
+                final URI location)
+        {
+            return _ws.validateProjectLocationURI(project, location);
+        }
+
+        @Override
+        public IStatus validateFiltered(final IResource resource)
+        {
+            return _ws.validateFiltered(resource);
+        }
+    }
+}
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/junit4/TestDataBaseLocation.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/junit4/TestDataBaseLocation.java
new file mode 100644
index 0000000..fa51690
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/junit4/TestDataBaseLocation.java
@@ -0,0 +1,22 @@
+package org.eclipse.jst.jsf.test.util.junit4;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a field in a JUnit test into which the base location for the test's data
+ * is to be injected.  The field must be of type java.io.File.  Resources
+ * loaded by the test should be referenced relative to this base location.
+ * 
+ * Generally, the base location will be dictated by the runtime.
+ * 
+ * @author cbateman
+ *
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD})
+public @interface TestDataBaseLocation
+{
+}
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/junit4/WorkspaceContext.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/junit4/WorkspaceContext.java
new file mode 100644
index 0000000..ed3ea1a
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/junit4/WorkspaceContext.java
@@ -0,0 +1,20 @@
+package org.eclipse.jst.jsf.test.util.junit4;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates a non-static field declared on a test class (may be any visibility)
+ * of type IWorkspaceContext that will have an appropriate instance injected into
+ * it.
+ *  
+ * @author cbateman
+ *
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD})
+public @interface WorkspaceContext
+{
+}
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/junit4/WorkspaceRunner.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/junit4/WorkspaceRunner.java
new file mode 100644
index 0000000..4cee075
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/junit4/WorkspaceRunner.java
@@ -0,0 +1,114 @@
+package org.eclipse.jst.jsf.test.util.junit4;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.util.List;
+
+import junit.framework.Assert;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jst.jsf.test.util.JSFTestUtil;
+import org.eclipse.jst.jsf.test.util.mock.IWorkspaceContext;
+import org.eclipse.jst.jsf.test.util.mock.MockWorkspaceContext;
+import org.eclipse.osgi.baseadaptor.loader.BaseClassLoader;
+import org.junit.Rule;
+import org.junit.rules.MethodRule;
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.Statement;
+import org.osgi.framework.Bundle;
+
+public class WorkspaceRunner extends BlockJUnit4ClassRunner
+{
+    @Rule
+    public MethodRule rule = new WorkspaceContextInjector();
+
+    public interface IWorkspaceContextFactory
+    {
+        IWorkspaceContext createContext();
+    }
+
+    public WorkspaceRunner(final Class<?> klass) throws InitializationError
+    {
+        super(klass);
+    }
+
+    @Override
+    protected List<MethodRule> rules(final Object test)
+    {
+        final List<MethodRule> rules = super.rules(test);
+        rules.add(new WorkspaceContextInjector());
+        return rules;
+    }
+
+    public static class WorkspaceContextInjector implements MethodRule
+    {
+        protected IWorkspaceContext before(final FrameworkMethod method,
+                final Object target) throws Throwable
+        {
+            final Class<?> declaringClass = method.getMethod()
+                    .getDeclaringClass();
+            final ClassLoader classLoader = declaringClass.getClassLoader();
+            final Field[] declaredFields = declaringClass.getDeclaredFields();
+            final IWorkspaceContext context = Platform.isRunning() ? new RealWorkspaceContext()
+                    : new MockWorkspaceContext();
+            context.init();
+            File baseLoc = null;
+            if (Platform.isRunning() && classLoader instanceof BaseClassLoader)
+            {
+                final Bundle bundle = ((BaseClassLoader) classLoader).getBundle();
+                final IPath absolutePath = JSFTestUtil.getAbsolutePath(bundle, "/");
+                baseLoc = absolutePath.toFile();
+            } else
+            {
+                baseLoc = new File(".").getAbsoluteFile();
+            }
+            Assert.assertTrue(baseLoc.isDirectory());
+            for (final Field field : declaredFields)
+            {
+                final WorkspaceContext annotation = field
+                        .getAnnotation(WorkspaceContext.class);
+                if (annotation != null)
+                {
+                    field.setAccessible(true);
+                    field.set(target, context);
+                }
+                final TestDataBaseLocation locAnnotation = field
+                        .getAnnotation(TestDataBaseLocation.class);
+                if (locAnnotation != null)
+                {
+                    field.setAccessible(true);
+                    field.set(target, baseLoc);
+                }
+            }
+            return context;
+        }
+
+        protected void after(final IWorkspaceContext context) throws Exception
+        {
+            context.dispose();
+        }
+
+        public Statement apply(final Statement base,
+                final FrameworkMethod method, final Object target)
+        {
+            return new Statement()
+            {
+                @Override
+                public void evaluate() throws Throwable
+                {
+                    final IWorkspaceContext context = before(method, target);
+                    try
+                    {
+                        base.evaluate();
+                    } finally
+                    {
+                        after(context);
+                    }
+                }
+            };
+        }
+    }
+}
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/AbstractWorkspaceContextWithEvents.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/AbstractWorkspaceContextWithEvents.java
new file mode 100644
index 0000000..55962f8
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/AbstractWorkspaceContextWithEvents.java
@@ -0,0 +1,42 @@
+package org.eclipse.jst.jsf.test.util.mock;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import junit.framework.Assert;
+
+public abstract class AbstractWorkspaceContextWithEvents implements
+        IWorkspaceContextWithEvents
+{
+    private AtomicBoolean _isInitialized = new AtomicBoolean(false);
+    private AtomicBoolean _isDisposed = new AtomicBoolean(false);
+
+    public final void init() throws Exception
+    {
+        if (_isInitialized.compareAndSet(false, true))
+        {
+            doInit();
+            return;
+        }
+        throw new IllegalStateException();
+    }
+
+    protected abstract void doInit() throws Exception;
+
+    public final void dispose() throws Exception
+    {
+        if (_isDisposed.compareAndSet(false, true))
+        {
+            doDispose();
+            return;
+        }
+        throw new IllegalStateException();
+    }
+
+    protected abstract void doDispose() throws Exception;
+    
+    protected void assertInitialized()
+    {
+        Assert.assertTrue("context must be initialized", _isInitialized.get());
+        Assert.assertFalse("context cannot be used after it is disposed", _isDisposed.get());
+    }
+}
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/FileSystemZipLoader.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/FileSystemZipLoader.java
new file mode 100644
index 0000000..5788c11
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/FileSystemZipLoader.java
@@ -0,0 +1,52 @@
+package org.eclipse.jst.jsf.test.util.mock;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
+
+import org.eclipse.jst.jsf.test.util.mock.IWorkspaceContext.ZipFileLoader;
+
+/**
+ * Allows a zip to be loaded directly from the file system.
+ * 
+ * @author cbateman
+ *
+ */
+public class FileSystemZipLoader extends ZipFileLoader
+{
+    private final File _file;
+    private String _pathIntoZip;
+
+    public FileSystemZipLoader(final File file)
+    {
+        this(file, "");
+    }
+    
+    
+    public FileSystemZipLoader(File file, String pathIntoZip)
+    {
+        _file = file;
+        _pathIntoZip = pathIntoZip;
+    }
+
+
+    @Override
+    public ZipFile getZipFile() throws ZipException, IOException
+    {
+        return new ZipFile(_file);
+    }
+
+    @Override
+    public String getPathInZip()
+    {
+        return _pathIntoZip;
+    }
+
+
+    @Override
+    public File getFile()
+    {
+        return _file;
+    }
+}
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/IWorkspaceContext.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/IWorkspaceContext.java
new file mode 100644
index 0000000..5b25da3
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/IWorkspaceContext.java
@@ -0,0 +1,84 @@
+package org.eclipse.jst.jsf.test.util.mock;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * @author cbateman
+ * 
+ */
+public interface IWorkspaceContext
+{
+    public abstract void init() throws Exception;
+    public abstract void dispose() throws Exception;
+
+    public abstract IWorkspace getWorkspace();
+
+    /**
+     * @param path
+     * @return a resource for path only if it exists null otherwise. This is a
+     *         departure from normal ws handle ops that always answer non-null
+     *         and you have to check if something exists.
+     */
+    public abstract IResource getResource(final IPath path);
+
+    /**
+     * Fully equivalent to (IFile) getResource(path).
+     * 
+     * @param path
+     * @return the IFile or null if none for path.
+     * @throws ClassCastException
+     *             if path exists but doesn't not point to a file.
+     */
+    public abstract IFile getFile(final IPath path);
+
+    /**
+     * Equivalent to (IProject) getResource(path).
+     * 
+     * @param path
+     * @return the project for the path or null if it isn't currently in the
+     *         context.
+     */
+    public abstract IProject getProject(final IPath path);
+
+    /**
+     * @return a mock project with a generated name that is guaranteed not to
+     *         conflict with any that already exist in this context.
+     */
+    public abstract IProject createProject(final String baseId);
+
+    public abstract IProject createProject(final IPath path);
+
+    public IFile attachFile(IProject project, IPath projectRelativePath,
+            File file) throws Exception;
+    /**
+     * @param path
+     * @param zipFileLoader
+     * @return an IProject loaded from zipFileLoader into the path provided.
+     * @throws Exception
+     */
+    public abstract IProject loadProject(final IPath path,
+            final ZipFileLoader zipFileLoader) throws Exception;
+
+    /**
+     * Method that implementers may choose to noop.
+     * 
+     * @param project
+     * @throws Exception 
+     */
+    public abstract void ensureAllMembers(final IProject project) throws Exception;
+    public abstract static class ZipFileLoader
+    {
+        public abstract ZipFile getZipFile() throws ZipException, IOException;
+        public abstract File  getFile();
+        public abstract String getPathInZip();
+    }
+}
\ No newline at end of file
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/IWorkspaceContextWithEvents.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/IWorkspaceContextWithEvents.java
new file mode 100644
index 0000000..00e5a66
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/IWorkspaceContextWithEvents.java
@@ -0,0 +1,20 @@
+package org.eclipse.jst.jsf.test.util.mock;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+
+/**
+ * An IWorkspaceContext object that has the ability to simulate workspace change
+ * events at test time.
+ * 
+ * @author cbateman
+ *
+ */
+public interface IWorkspaceContextWithEvents extends IWorkspaceContext
+{
+    public abstract void fireWorkspaceEvent(final IResourceChangeEvent event);
+    public abstract List<IResourceChangeListener> getListeners();
+    public abstract List<IResourceChangeListener> getListeners(List<Class<? extends IResourceChangeListener>> includeTypes);
+}
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockFile.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockFile.java
index da3c413..a3e744a 100644
--- a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockFile.java
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockFile.java
@@ -50,8 +50,7 @@
     public void create(final InputStream source, final boolean force,
             final IProgressMonitor monitor) throws CoreException
     {
-        throw new UnsupportedOperationException();
-
+        setContents(source, 0, monitor);
     }
 
     public void create(final InputStream source, final int updateFlags,
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockProject.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockProject.java
index 4cc2f94..e29e49a 100644
--- a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockProject.java
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockProject.java
@@ -26,7 +26,7 @@
 
     public MockProject(final IPath path, final IMockResourceFactory resFactory)
     {
-        super(IResource.PROJECT, new Path("MockProject_"+path), resFactory);
+        super(IResource.PROJECT,path, resFactory);
         setProject(this);
     }
 
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockResource.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockResource.java
index 209b40d..cafd39e 100644
--- a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockResource.java
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockResource.java
@@ -33,7 +33,7 @@
     private boolean _exists = true; // always exist by default
     private MockWorkspace _workspace;
     private IProject _project;
-    private long _modificationStamp;
+    private long _modificationStamp = -1;
 	private Map<QualifiedName, Object> _sessionProps;
     public final static List<Integer> VALID_TYPES;
 
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockResourceChangeEvent.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockResourceChangeEvent.java
index 5936223..4df805a 100644
--- a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockResourceChangeEvent.java
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockResourceChangeEvent.java
@@ -1,12 +1,18 @@
 package org.eclipse.jst.jsf.test.util.mock;
 
+import java.util.EventObject;
+
 import org.eclipse.core.resources.IMarkerDelta;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IResourceChangeEvent;
 import org.eclipse.core.resources.IResourceDelta;
 
-public class MockResourceChangeEvent implements IResourceChangeEvent
+public class MockResourceChangeEvent extends EventObject implements IResourceChangeEvent
 {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 6425297945375951902L;
     private final MockResourceDelta _delta;
     private final IResource _resource;
     private final int _type;
@@ -18,6 +24,7 @@
      */
     public MockResourceChangeEvent(final IResource resource, final int type, final MockResourceDelta delta)
     {
+        super(resource != null ? resource.getWorkspace() : new Object());
         _delta = delta;
         _resource = resource;
         _type = type;
@@ -34,7 +41,8 @@
 
     public int getBuildKind()
     {
-        throw new UnsupportedOperationException();
+        // we currently don't support build events
+        return 0;
     }
 
     public IResourceDelta getDelta()
@@ -47,11 +55,6 @@
         return _resource;
     }
 
-    public Object getSource()
-    {
-        throw new UnsupportedOperationException();
-    }
-
     public int getType()
     {
         return _type;
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockResourceChangeEventFactory.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockResourceChangeEventFactory.java
index 938b3f8..1786cca 100644
--- a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockResourceChangeEventFactory.java
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockResourceChangeEventFactory.java
@@ -2,6 +2,7 @@
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResourceChangeEvent;
 
 public class MockResourceChangeEventFactory
@@ -14,31 +15,31 @@
         _deltaFactory = deltaFactory;
     }
 
-    public MockResourceChangeEventFactory(final MockWorkspaceContext wsContext)
+    public MockResourceChangeEventFactory(final IWorkspaceContext wsContext)
     {
         this(new MockResourceDeltaFactory(wsContext));
     }
 
-    public IResourceChangeEvent createSimpleFileChange(final MockFile file,
+    public IResourceChangeEvent createSimpleFileChange(final IFile file,
             final boolean incrementModStamp)
     {
         final MockResourceDelta delta = _deltaFactory
                 .createSimpleFileChange(file);
-        if (incrementModStamp)
+        if (incrementModStamp && file instanceof MockFile)
         {
-            file.incrementModStamp();
+            ((MockResource) file).incrementModStamp();
         }
         return newPostChangeEvent(delta);
     }
 
-    public IResourceChangeEvent createSimpleFileRemove(final MockFile file)
+    public IResourceChangeEvent createSimpleFileRemove(final IFile file)
     {
         final MockResourceDelta delta = _deltaFactory
                 .createSimpleFileRemoved(file);
         return newPostChangeEvent(delta);
     }
 
-    public IResourceChangeEvent createSimpleFileAdded(final MockFile file)
+    public IResourceChangeEvent createSimpleFileAdded(final IFile file)
     {
         final MockResourceDelta delta = _deltaFactory
                 .createSimpleFileAdded(file);
@@ -46,14 +47,14 @@
     }
 
     public IResourceChangeEvent createSimpleProjectClosed(
-            final MockProject project)
+            final IProject project)
     {
         return new MockResourceChangeEvent(project,
                 IResourceChangeEvent.PRE_CLOSE, null);
     }
 
     public IResourceChangeEvent createSimpleProjectDeleted(
-            final MockProject project)
+            final IProject project)
     {
         return new MockResourceChangeEvent(project,
                 IResourceChangeEvent.PRE_DELETE, null);
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockResourceDeltaFactory.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockResourceDeltaFactory.java
index 0b70027..a61ef86 100644
--- a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockResourceDeltaFactory.java
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockResourceDeltaFactory.java
@@ -20,7 +20,7 @@
 public class MockResourceDeltaFactory
 {
     // private final MockWorkspaceContext _wsContext;
-    public MockResourceDeltaFactory(final MockWorkspaceContext wsContext)
+    public MockResourceDeltaFactory(final IWorkspaceContext wsContext)
     {
         // _wsContext = wsContext;
     }
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockWorkspaceContext.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockWorkspaceContext.java
index 5aa4dc8..249f8fe 100644
--- a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockWorkspaceContext.java
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockWorkspaceContext.java
@@ -15,7 +15,11 @@
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.NullProgressMonitor;
@@ -28,7 +32,7 @@
  * @author cbateman
  * 
  */
-public class MockWorkspaceContext
+public class MockWorkspaceContext implements IWorkspaceContextWithEvents
 {
     private final MockWorkspace _ws;
     private final Map<IPath, MockResource> _ownedResources;
@@ -37,7 +41,7 @@
     {
         _ws = ws;
         _ownedResources = new HashMap<IPath, MockResource>();
-        ((MockWorkspaceRoot)ws.getRoot()).setContext(this);
+        ((MockWorkspaceRoot) ws.getRoot()).setContext(this);
     }
 
     public MockWorkspaceContext()
@@ -45,11 +49,27 @@
         this(new MockWorkspace(new MockWorkspaceRoot()));
     }
 
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.eclipse.jst.jsf.test.util.mock.IWorkspaceContext#fireWorkspaceEvent
+     * (org.eclipse.core.resources.IResourceChangeEvent)
+     */
     public void fireWorkspaceEvent(final IResourceChangeEvent event)
     {
         _ws.fireResourceChangeEvent(event);
     }
 
+    public void init() throws Exception
+    {
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.eclipse.jst.jsf.test.util.mock.IWorkspaceContext#dispose()
+     */
     public void dispose() throws Exception
     {
         for (final Map.Entry<IPath, MockResource> entry : _ownedResources
@@ -61,27 +81,60 @@
         _ws.dispose();
     }
 
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.eclipse.jst.jsf.test.util.mock.IWorkspaceContext#getWorkspace()
+     */
     public MockWorkspace getWorkspace()
     {
         return _ws;
     }
 
-    public MockResource getResource(final IPath path)
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.eclipse.jst.jsf.test.util.mock.IWorkspaceContext#getResource(org.
+     * eclipse.core.runtime.IPath)
+     */
+    public IResource getResource(final IPath path)
     {
         return _ownedResources.get(path);
     }
 
-    public MockFile getFile(final IPath path)
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.eclipse.jst.jsf.test.util.mock.IWorkspaceContext#getFile(org.eclipse
+     * .core.runtime.IPath)
+     */
+    public IFile getFile(final IPath path)
     {
         return (MockFile) getResource(path);
     }
 
-    public MockProject getProject(final IPath path)
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.eclipse.jst.jsf.test.util.mock.IWorkspaceContext#getProject(org.eclipse
+     * .core.runtime.IPath)
+     */
+    public IProject getProject(final IPath path)
     {
         return (MockProject) _ownedResources.get(path);
     }
 
-    public MockProject createProject(final IPath path, final boolean replace)
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.eclipse.jst.jsf.test.util.mock.IWorkspaceContext#createProject(org
+     * .eclipse.core.runtime.IPath, boolean)
+     */
+    private IProject createProject(final IPath path, final boolean replace)
     {
         final MockProject project = new MockProject(path,
                 new MyMockResourceFactory());
@@ -89,16 +142,19 @@
         return project;
     }
 
-    /**
-     * @return a mock project with a generated name that is guaranteed not to
-     *         conflict with any that already exist in this context.
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.eclipse.jst.jsf.test.util.mock.IWorkspaceContext#createProject(java
+     * .lang.String)
      */
-    public MockProject createProject(final String baseId)
+    public IProject createProject(final String baseId)
     {
         int i = 0;
         while (_ownedResources.get(generateName(baseId, i)) != null)
         {
-            // keep looping until we get TestProject_i that doesn't exist
+            // keep looping until we get baseId_i that doesn't exist
             i++;
         }
         return createProject(generateName(baseId, i), false);
@@ -109,63 +165,86 @@
         return new Path(baseId + "_TestProject_" + i);
     }
 
-    public MockProject createProject(final IPath path)
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.eclipse.jst.jsf.test.util.mock.IWorkspaceContext#createProject(org
+     * .eclipse.core.runtime.IPath)
+     */
+    public IProject createProject(final IPath path)
     {
         return createProject(path, false);
     }
 
-    public void attachProject(final MockProject project, final boolean replace)
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.eclipse.jst.jsf.test.util.mock.IWorkspaceContext#attachProject(org
+     * .eclipse.jst.jsf.test.util.mock.MockProject, boolean)
+     */
+    private void attachProject(final IProject project, final boolean replace)
     {
         checkExists(project.getFullPath(), replace);
-        project.setWorkspace(_ws);
-        _ownedResources.put(project.getFullPath(), project);
+        ((MockProject) project).setWorkspace(_ws);
+        _ownedResources.put(project.getFullPath(), (MockProject) project);
     }
 
-    public MockProject loadProject(final IPath path, final ZipFile zip)
-            throws Exception
-    {
-        return loadProject(path, zip, "");
-    }
-
-    public MockProject loadProject(final IPath path, final ZipFile zip,
-            final String pathIntoZip) throws Exception
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.eclipse.jst.jsf.test.util.mock.IWorkspaceContext#loadProject(org.
+     * eclipse.core.runtime.IPath, java.util.zip.ZipFile, java.lang.String)
+     */
+    public IProject loadProject(final IPath path,
+            final ZipFileLoader zipFileLoader) throws Exception
     {
         checkExists(path, false);
         final MockProject project = new MockProject(path,
-                new MyMockResourceFactory(zip, pathIntoZip));
+                new MyMockResourceFactory(zipFileLoader.getZipFile(),
+                        zipFileLoader.getPathInZip()));
         attachProject(project, false);
         return project;
     }
 
-    public MockFile attachFile(MockProject project, IPath projectRelativePath,
-            File file)
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.eclipse.jst.jsf.test.util.mock.IWorkspaceContext#attachFile(org.eclipse
+     * .jst.jsf.test.util.mock.MockProject, org.eclipse.core.runtime.IPath,
+     * java.io.File)
+     */
+    public MockFile attachFile(final IProject project, final IPath projectRelativePath,
+            final File file)
     {
         assertEquals(checkExists(project.getFullPath(), true), project);
         // throw an exception if projectRelativePath already exists
         checkExists(project.getFullPath().append(projectRelativePath), false);
         assertTrue(file.exists());
-        MockFile iFile = (MockFile) project.getFile(projectRelativePath);
+        final MockFile iFile = (MockFile) project.getFile(projectRelativePath);
         InputStream inStream = null;
         try
         {
             inStream = new FileInputStream(file);
             iFile.setContents(inStream, 0, null);
             return iFile;
-        } catch (IOException e)
+        } catch (final IOException e)
         {
             throw new RuntimeException(e);
-        } catch (CoreException e)
+        } catch (final CoreException e)
         {
             throw new RuntimeException(e);
-        }
-        finally
+        } finally
         {
             if (inStream != null)
             {
                 try
                 {
                     inStream.close();
-                } catch (IOException e)
+                } catch (final IOException e)
                 {
                     throw new RuntimeException(e);
                 }
@@ -210,8 +289,8 @@
             if (resource == null)
             {
                 resource = new MockFile(newFileFullPath);
-                ((MockResource) resource).setWorkspace(_ws);
-                ((MockResource) resource).setProject(container.getProject());
+                (resource).setWorkspace(_ws);
+                (resource).setProject(container.getProject());
                 if (_zip != null)
                 {
                     final ZipEntry entry = _zip.getEntry(_pathIntoZip
@@ -241,8 +320,8 @@
             if (resource == null)
             {
                 resource = new MockFolder(newFileFullPath, this);
-                ((MockResource) resource).setWorkspace(_ws);
-                ((MockResource) resource).setProject(container.getProject());
+                (resource).setWorkspace(_ws);
+                (resource).setProject(container.getProject());
                 ensurePathToNewResource(container, path);
                 _ownedResources.put(newFileFullPath, resource);
             }
@@ -261,7 +340,7 @@
                 final String nextSegment = leadingPath.segments()[0];
                 curPath = curPath.append(nextSegment);
                 leadingPath = leadingPath.removeFirstSegments(1);
-                MockResource newContainer = checkExists(curPath, true);
+                final MockResource newContainer = checkExists(curPath, true);
                 if (newContainer == null)
                 {
                     newFolder(container, curPath);
@@ -269,7 +348,7 @@
             }
         }
 
-        protected void newFolder(MockContainer container, IPath curPath)
+        protected void newFolder(final MockContainer container, final IPath curPath)
         {
             MockResource newContainer;
             newContainer = new MockFolder(curPath, this);
@@ -326,4 +405,31 @@
             }
         }
     }
+
+    public List<IResourceChangeListener> getListeners()
+    {
+        return getWorkspace().getListeners();
+    }
+
+    public List<IResourceChangeListener> getListeners(final List<Class<? extends IResourceChangeListener>>  includeListeners)
+    {
+        final List<IResourceChangeListener> listeners = new ArrayList<IResourceChangeListener>();
+        for (final IResourceChangeListener listener : getListeners())
+        {
+            SEARCH_CLASSES: for (final Class<? extends IResourceChangeListener> clazz : includeListeners)
+            {
+                if (clazz.isAssignableFrom(listener.getClass()))
+                {
+                    listeners.add(listener);
+                    break SEARCH_CLASSES;
+                }
+            }
+        }
+        return listeners;
+    }
+
+    public void ensureAllMembers(final IProject project) throws Exception
+    {
+        ((MockProject) project).loadAllMembers();
+    }
 }
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/TestMockWorkspaceContext.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/TestMockWorkspaceContext.java
new file mode 100644
index 0000000..d13e95f
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/TestMockWorkspaceContext.java
@@ -0,0 +1,165 @@
+package org.eclipse.jst.jsf.test.util.mock;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.InputStream;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jst.jsf.test.util.JSFTestUtil;
+import org.eclipse.jst.jsf.test.util.junit4.TestDataBaseLocation;
+import org.eclipse.jst.jsf.test.util.junit4.WorkspaceContext;
+import org.eclipse.jst.jsf.test.util.junit4.WorkspaceRunner;
+import org.eclipse.jst.jsf.test.util.mock.IWorkspaceContext.ZipFileLoader;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(WorkspaceRunner.class)
+public class TestMockWorkspaceContext
+{
+    @WorkspaceContext
+    private IWorkspaceContext _wsContext;
+    @TestDataBaseLocation
+    private File _baseLoc;
+    private ZipFileLoader _testZipFileLoader;
+
+    @Before
+    public void setUp() throws Exception
+    {
+        System.out.println(_baseLoc);
+        IPath path = new Path(_baseLoc.getAbsolutePath());
+        path = path.append("/data/TestProject.zip");
+        final File file = path.toFile();
+        assertTrue(file.exists());
+        _testZipFileLoader = new FileSystemZipLoader(file, "TestProject/");
+    }
+
+//    @Test
+//    public void testFireWorkspaceEvent()
+//    {
+//        // TODO:
+//        _wsContext.fireWorkspaceEvent(null);
+//    }
+
+    @Test
+    public void testDispose() throws Exception
+    {
+        _wsContext.dispose();
+    }
+
+    @Test
+    public void testGetWorkspace()
+    {
+        final IWorkspace workspace = _wsContext.getWorkspace();
+        assertNotNull(workspace);
+        assertSame(workspace, _wsContext.getWorkspace());
+    }
+
+    @Test
+    public void testGetProject() throws Exception
+    {
+        final IPath path = new Path("TestProject");
+        IProject project = _wsContext.getProject(path);
+        assertNull(project);
+        // now load the resource
+        project = _wsContext.loadProject(path, _testZipFileLoader);
+        assertNotNull(project);
+    }
+
+    @Test
+    public void testGetResource() throws Exception
+    {
+        final IPath projPath = new Path("TestProject");
+        // if we haven't done anything special, then this res shouldn't exist.
+        final IPath path = new Path("/WebContent/test.xhtml");
+        final IPath fullPath = projPath.append(path);
+        IResource resource = _wsContext.getResource(path);
+        assertNull(resource);
+        // now load the resource; still won't have the resource until it is
+        // requested.
+        final IProject project = _wsContext.loadProject(projPath,
+                _testZipFileLoader);
+        assertNotNull(project);
+
+        // TODO: only true for non-plugin
+        //        resource = _wsContext.getResource(fullPath);
+//        assertNull(resource);
+        // now request the resource through the project interface. This should
+        // cause it to be known by the context.
+        final IFile file = project.getFile(path);
+        assertNotNull(file);
+        assertEquals(file, _wsContext.getResource(fullPath));
+    }
+
+    @Test
+    public void testGetFile() throws Exception
+    {
+        final IPath projPath = new Path("TestProject");
+        // if we haven't done anything special, then this res shouldn't exist.
+        final IPath path = new Path("/WebContent/test.xhtml");
+        final IPath fullPath = projPath.append(path);
+        IFile file = _wsContext.getFile(path);
+        assertNull(file);
+        // now load the resource; still won't have the resource until it is
+        // requested.
+        final IProject project = _wsContext.loadProject(projPath,
+                _testZipFileLoader);
+        assertNotNull(project);
+        // TODO:
+//        file = _wsContext.getFile(fullPath);
+//        assertNull(file);
+        // now request the resource through the project interface. This should
+        // cause it to be known by the context.
+        final IFile fileFromProject = project.getFile(path);
+        assertNotNull(fileFromProject);
+        assertEquals(fileFromProject, _wsContext.getFile(fullPath));
+    }
+
+    @Test
+    public void testCreateProjectString()
+    {
+        final IProject project = _wsContext.createProject("Foo");
+        assertNotNull(project);
+        final IProject project2 = _wsContext.createProject("Foo");
+        assertNotNull(project2);
+        // two projects created with the same baseId should have unique
+        // paths as taken care off by the context.
+        assertFalse(project.equals(project2));
+    }
+
+    @Test
+    public void testCreateProjectIPath()
+    {
+        final IProject project = _wsContext.createProject(new Path("Foo"));
+        assertNotNull(project);
+        assertEquals("Foo", project.getName());
+    }
+
+    @Test
+    public void testLoadProjectIPathZipFile() throws Exception
+    {
+        final IProject project = _wsContext.loadProject(
+                new Path("TestProject1"), _testZipFileLoader);
+        assertNotNull(project);
+        assertTrue(project.exists());
+        final IFile file = project.getFile(new Path("WebContent/test.xhtml"));
+        assertNotNull(file);
+        assertTrue(file.exists());
+        final InputStream contents = file.getContents();
+        final ByteArrayOutputStream data = JSFTestUtil
+                .loadFromInputStream(contents);
+        assertEquals(367, data.toByteArray().length);
+    }
+}
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/java/MockJDTWorkspaceContext.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/java/MockJDTWorkspaceContext.java
index 645e05b..5159b8c 100644
--- a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/java/MockJDTWorkspaceContext.java
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/java/MockJDTWorkspaceContext.java
@@ -19,20 +19,20 @@
 import org.eclipse.jdt.core.IElementChangedListener;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jst.jsf.test.util.mock.IWorkspaceContext;
 import org.eclipse.jst.jsf.test.util.mock.MockFile;
 import org.eclipse.jst.jsf.test.util.mock.MockProject;
-import org.eclipse.jst.jsf.test.util.mock.MockWorkspaceContext;
 
 public class MockJDTWorkspaceContext
 {
-    private final MockWorkspaceContext _wsContext;
-    private final Map<MockProject, List<IPackageFragmentRoot>> _cpEntriesByProject;
+    private final IWorkspaceContext _wsContext;
+    private final Map<IProject, List<IPackageFragmentRoot>> _cpEntriesByProject;
     private final CopyOnWriteArrayList<IElementChangedListener> _listeners = new CopyOnWriteArrayList<IElementChangedListener>();
 
-    public MockJDTWorkspaceContext(final MockWorkspaceContext wsContext)
+    public MockJDTWorkspaceContext(final IWorkspaceContext wsContext)
     {
         _wsContext = wsContext;
-        _cpEntriesByProject = new HashMap<MockProject, List<IPackageFragmentRoot>>();
+        _cpEntriesByProject = new HashMap<IProject, List<IPackageFragmentRoot>>();
     }
 
     @SuppressWarnings("unchecked")
@@ -77,18 +77,25 @@
      * @return a new mock classpath entry. This entry will automatically be
      *         added to project as a file and to any MockJavaProject created
      *         through this context for project.
+     * @throws Exception 
      */
     public IPackageFragmentRoot createCPELibraryInProject(
-            final MockProject project, final IPath projectRelativePath,
+            final IProject project, final IPath projectRelativePath,
             final File file)
     {
-        _wsContext.attachFile(project, projectRelativePath, file);
-        return createAndAddPackageFragmentRoot(project,
-                new Path(file.getAbsolutePath()));
+        try
+        {
+            _wsContext.attachFile(project, projectRelativePath, file);
+            return createAndAddPackageFragmentRoot(project,
+                    new Path(file.getAbsolutePath()));
+        } catch (Exception e)
+        {
+            throw new RuntimeException(e);
+        }
     }
 
     private IPackageFragmentRoot createAndAddPackageFragmentRoot(
-            final MockProject project, final IPath absPathToRoot)
+            final IProject project, final IPath absPathToRoot)
     {
         final IJavaProject javaProject = createJavaProject(project);
         final IPackageFragmentRoot fragRoot = new MockPackageFragmentRoot(
@@ -97,7 +104,7 @@
         return fragRoot;
     }
 
-    private void addCPEntry(final MockProject project,
+    private void addCPEntry(final IProject project,
             final IPackageFragmentRoot packageRoot)
     {
         List<IPackageFragmentRoot> entriesForProject = _cpEntriesByProject
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/java/MockJavaChangeEventFactory.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/java/MockJavaChangeEventFactory.java
index cf25ee5..3aa2e30 100644
--- a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/java/MockJavaChangeEventFactory.java
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/java/MockJavaChangeEventFactory.java
@@ -7,7 +7,6 @@
 import org.eclipse.jdt.core.IJavaElementDelta;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
-import org.eclipse.jst.jsf.test.util.mock.MockProject;
 
 public class MockJavaChangeEventFactory
 {
@@ -27,7 +26,7 @@
     }
 
     public ElementChangedEvent createSimpleJarRemoved(
-            final MockProject project, final IPackageFragmentRoot packageRoots)
+            final IProject project, final IPackageFragmentRoot packageRoots)
     {
         final IJavaElementDelta delta = createSimpleJarAddedDelta(project,
                 packageRoots, IJavaElementDelta.F_REMOVED_FROM_CLASSPATH);