Additions to help support creating IStructuredModel instances in mock workspaces.
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/META-INF/MANIFEST.MF b/jsf/tests/org.eclipse.jst.jsf.test.util/META-INF/MANIFEST.MF
index 1132212..bbbb85d 100644
--- a/jsf/tests/org.eclipse.jst.jsf.test.util/META-INF/MANIFEST.MF
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/META-INF/MANIFEST.MF
@@ -34,7 +34,9 @@
 Export-Package: org.eclipse.jst.jsf.test.util,
  org.eclipse.jst.jsf.test.util.junit4,
  org.eclipse.jst.jsf.test.util.mock,
- org.eclipse.jst.jsf.test.util.mock.java
+ org.eclipse.jst.jsf.test.util.mock.java,
+ org.eclipse.jst.jsf.test.util.mock.osgi,
+ org.eclipse.jst.jsf.test.util.mock.smodel
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
 Bundle-Vendor: %Bundle-Vendor.0
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 a3e744a..25edfc0 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
@@ -18,16 +18,20 @@
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.QualifiedName;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.core.runtime.content.IContentTypeSettings;
+import org.eclipse.core.runtime.preferences.IScopeContext;
 import org.eclipse.jst.jsf.test.util.Activator;
 import org.eclipse.jst.jsf.test.util.JSFTestUtil;
 
 public class MockFile extends MockResource implements IFile
 {
 
-    private byte[]  _contents;
-    private File    _concreteFile;
+    private byte[] _contents;
+    private File _concreteFile;
 
     public MockFile(final IPath path)
     {
@@ -83,8 +87,7 @@
 
     public String getCharset() throws CoreException
     {
-        throw new UnsupportedOperationException();
-
+        return "UTF-8";
     }
 
     public String getCharset(final boolean checkImplicit) throws CoreException
@@ -101,8 +104,121 @@
 
     public IContentDescription getContentDescription() throws CoreException
     {
-        throw new UnsupportedOperationException();
+        return new IContentDescription()
+        {
 
+            public void setProperty(QualifiedName key, Object value)
+            {
+                throw new UnsupportedOperationException();
+
+            }
+
+            public boolean isRequested(QualifiedName key)
+            {
+                throw new UnsupportedOperationException();
+            }
+
+            public Object getProperty(QualifiedName key)
+            {
+                return null;
+            }
+
+            public IContentType getContentType()
+            {
+                return new IContentType()
+                {
+
+                    public void addFileSpec(String fileSpec, int type)
+                            throws CoreException
+                    {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public void removeFileSpec(String fileSpec, int type)
+                            throws CoreException
+                    {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public void setDefaultCharset(String userCharset)
+                            throws CoreException
+                    {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public IContentType getBaseType()
+                    {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public IContentDescription getDefaultDescription()
+                    {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public IContentDescription getDescriptionFor(
+                            InputStream contents, QualifiedName[] options)
+                            throws IOException
+                    {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public IContentDescription getDescriptionFor(
+                            Reader contents, QualifiedName[] options)
+                            throws IOException
+                    {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public String getDefaultCharset()
+                    {
+                        return "UTF-8";
+                    }
+
+                    public String[] getFileSpecs(int type)
+                    {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public String getId()
+                    {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public String getName()
+                    {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public boolean isAssociatedWith(String fileName)
+                    {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public boolean isAssociatedWith(String fileName,
+                            IScopeContext context)
+                    {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public boolean isKindOf(IContentType another)
+                    {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public IContentTypeSettings getSettings(
+                            IScopeContext context) throws CoreException
+                    {
+                        throw new UnsupportedOperationException();
+                    }
+                };
+            }
+
+            public String getCharset()
+            {
+                return "UTF-8";
+            }
+        };
     }
 
     public InputStream getContents() throws CoreException
@@ -154,7 +270,9 @@
     {
         if (_contents != null && !force)
         {
-            throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Attempt to reset contents without force"));
+            throw new CoreException(new Status(IStatus.ERROR,
+                    Activator.PLUGIN_ID,
+                    "Attempt to reset contents without force"));
         }
         ByteArrayOutputStream captureBytes;
         try
@@ -163,14 +281,18 @@
             // keep concrete file in sync if we have one.
             if (_concreteFile != null && _concreteFile.exists())
             {
-                JSFTestUtil.saveToFileSystem(captureBytes.toByteArray(), _concreteFile.toURI());
+                JSFTestUtil.saveToFileSystem(captureBytes.toByteArray(),
+                        _concreteFile.toURI());
             }
-        } catch (IOException e)
+        }
+        catch (IOException e)
         {
-            throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Failed loading mock contents from stream"));
+            throw new CoreException(new Status(IStatus.ERROR,
+                    Activator.PLUGIN_ID,
+                    "Failed loading mock contents from stream"));
         }
         _contents = captureBytes.toByteArray();
-        
+
     }
 
     public void setContents(final IFileState source, final boolean force,
@@ -183,13 +305,15 @@
     public void setContents(final InputStream source, final int updateFlags,
             final IProgressMonitor monitor) throws CoreException
     {
-        setContents(source, (updateFlags | IResource.FORCE)!= 0, (updateFlags | IResource.KEEP_HISTORY) != 0, monitor);
+        setContents(source, (updateFlags | IResource.FORCE) != 0,
+                (updateFlags | IResource.KEEP_HISTORY) != 0, monitor);
     }
 
     public void setContents(final IFileState source, final int updateFlags,
             final IProgressMonitor monitor) throws CoreException
     {
-        setContents(source, (updateFlags | IResource.FORCE)!= 0, (updateFlags | IResource.KEEP_HISTORY) != 0, monitor);
+        setContents(source, (updateFlags | IResource.FORCE) != 0,
+                (updateFlags | IResource.KEEP_HISTORY) != 0, monitor);
     }
 
     @Override
@@ -206,14 +330,17 @@
             String tempFileName = getFullPath().toString().replace('/', '_');
             try
             {
-                _concreteFile = File.createTempFile(tempFileName, "."+getFullPath().getFileExtension());
+                _concreteFile = File.createTempFile(tempFileName, "."
+                        + getFullPath().getFileExtension());
                 _concreteFile.deleteOnExit();
                 assertTrue(_concreteFile.exists());
                 if (_contents != null)
                 {
-                    JSFTestUtil.saveToFileSystem(_contents, _concreteFile.toURI());
+                    JSFTestUtil.saveToFileSystem(_contents,
+                            _concreteFile.toURI());
                 }
-            } catch (IOException e)
+            }
+            catch (IOException e)
             {
                 throw new RuntimeException(e);
             }
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockMarker.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockMarker.java
new file mode 100644
index 0000000..005b6d8
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockMarker.java
@@ -0,0 +1,142 @@
+package org.eclipse.jst.jsf.test.util.mock;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+
+public class MockMarker implements IMarker
+{
+    private final Map<String, Object> _attributes = new HashMap<String, Object>();
+    private final IResource _resource;
+
+    public MockMarker(final IResource resource)
+    {
+        _resource = resource;
+    }
+
+    public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter)
+    {
+        throw new UnsupportedOperationException();
+
+    }
+
+    public void delete() throws CoreException
+    {
+        throw new UnsupportedOperationException();
+
+    }
+
+    public boolean exists()
+    {
+        return true;
+    }
+
+    public Object getAttribute(String attributeName) throws CoreException
+    {
+        return _attributes.get(attributeName);
+    }
+
+    public int getAttribute(String attributeName, int defaultValue)
+    {
+        Object object = _attributes.get(attributeName);
+        if (object instanceof Integer)
+        {
+            return ((Integer)object).intValue();
+        }
+        return defaultValue;
+    }
+
+    public String getAttribute(String attributeName, String defaultValue)
+    {
+        Object object = _attributes.get(attributeName);
+        if (object instanceof String)
+        {
+            return ((String)object);
+        }
+        return defaultValue;
+    }
+
+    public boolean getAttribute(String attributeName, boolean defaultValue)
+    {
+        Object object = _attributes.get(attributeName);
+        if (object instanceof Boolean)
+        {
+            return ((Boolean)object).booleanValue();
+        }
+        return defaultValue;
+    }
+
+    public Map<?, ?> getAttributes() throws CoreException
+    {
+        return Collections.unmodifiableMap(_attributes);
+    }
+
+    public Object[] getAttributes(String[] attributeNames) throws CoreException
+    {
+        throw new UnsupportedOperationException();
+
+    }
+
+    public long getCreationTime() throws CoreException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public long getId()
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public IResource getResource()
+    {
+        return _resource;
+    }
+
+    public String getType() throws CoreException
+    {
+        throw new UnsupportedOperationException();
+
+    }
+
+    public boolean isSubtypeOf(String superType) throws CoreException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public void setAttribute(String attributeName, int value)
+            throws CoreException
+    {
+        setAttribute(attributeName, Integer.valueOf(value));
+    }
+
+    public void setAttribute(String attributeName, Object value)
+            throws CoreException
+    {
+        _attributes.put(attributeName, value);
+    }
+
+    public void setAttribute(String attributeName, boolean value)
+            throws CoreException
+    {
+        setAttribute(attributeName, Boolean.valueOf(value));
+    }
+
+    public void setAttributes(String[] attributeNames, Object[] values)
+            throws CoreException
+    {
+        throw new UnsupportedOperationException();
+
+    }
+
+    @SuppressWarnings("unchecked")
+    public void setAttributes(@SuppressWarnings("rawtypes") Map attributes)
+            throws CoreException
+    {
+        _attributes.putAll(attributes);
+    }
+
+}
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockVirtualFile.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockVirtualFile.java
index 1406059..4c76931 100644
--- a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockVirtualFile.java
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/MockVirtualFile.java
@@ -101,8 +101,7 @@
 
     public IResource getUnderlyingResource()
     {
-        throw new UnsupportedOperationException();
-
+        return getUnderlyingFile();
     }
 
     public IResource[] getUnderlyingResources()
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/osgi/BundleHacker.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/osgi/BundleHacker.java
new file mode 100644
index 0000000..474973f
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/osgi/BundleHacker.java
@@ -0,0 +1,33 @@
+package org.eclipse.jst.jsf.test.util.mock.osgi;
+
+import java.lang.reflect.Field;
+
+import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
+import org.eclipse.osgi.framework.internal.core.BundleContextImpl;
+import org.eclipse.osgi.framework.internal.core.BundleHost;
+import org.eclipse.osgi.framework.internal.core.Framework;
+import org.osgi.framework.BundleException;
+
+/**
+ * Utility methods for hacking OSGI bundle dependencies.
+ * 
+ * @author cbateman
+ * 
+ */
+public class BundleHacker
+{
+
+    public void mockBundleContext(Class<?> clazz) throws NoSuchFieldException,
+            BundleException, IllegalAccessException
+    {
+        final Field declaredField = clazz.getDeclaredField("context");
+        declaredField.setAccessible(true);
+
+        final FrameworkAdaptor adaptor = new MockFrameworkAdaptor();
+        final Framework framework = new Framework(adaptor);
+        final BundleHost host = new BundleHost(null, framework);
+        declaredField.set(null, new BundleContextImpl(host)
+        {
+        });
+    }
+}
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/osgi/MockFrameworkAdaptor.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/osgi/MockFrameworkAdaptor.java
new file mode 100644
index 0000000..83471b5
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/osgi/MockFrameworkAdaptor.java
@@ -0,0 +1,399 @@
+package org.eclipse.jst.jsf.test.util.mock.osgi;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Writer;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Properties;
+
+import org.eclipse.osgi.framework.adaptor.BundleClassLoader;
+import org.eclipse.osgi.framework.adaptor.BundleData;
+import org.eclipse.osgi.framework.adaptor.BundleOperation;
+import org.eclipse.osgi.framework.adaptor.BundleProtectionDomain;
+import org.eclipse.osgi.framework.adaptor.BundleWatcher;
+import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate;
+import org.eclipse.osgi.framework.adaptor.EventPublisher;
+import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
+import org.eclipse.osgi.framework.adaptor.PermissionStorage;
+import org.eclipse.osgi.framework.log.FrameworkLog;
+import org.eclipse.osgi.framework.log.FrameworkLogEntry;
+import org.eclipse.osgi.service.resolver.PlatformAdmin;
+import org.eclipse.osgi.service.resolver.State;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.Version;
+
+public class MockFrameworkAdaptor implements FrameworkAdaptor
+{
+    public void initialize(final EventPublisher eventPublisher)
+    {
+        // throw new UnsupportedOperationException();
+    }
+
+    public void initializeStorage() throws IOException
+    {
+        // throw new UnsupportedOperationException();
+    }
+
+    public void compactStorage() throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public Properties getProperties()
+    {
+        return new Properties();
+    }
+
+    public BundleData[] getInstalledBundles()
+    {
+        return null;
+    }
+
+    public URLConnection mapLocationToURLConnection(final String location)
+            throws BundleException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public BundleOperation installBundle(final String location,
+            final URLConnection source)
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public BundleOperation updateBundle(final BundleData bundledata,
+            final URLConnection source)
+    {
+        throw new UnsupportedOperationException();
+
+    }
+
+    public BundleOperation uninstallBundle(final BundleData bundledata)
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public long getTotalFreeSpace() throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public PermissionStorage getPermissionStorage() throws IOException
+    {
+        return new PermissionStorage()
+        {
+
+            public void setPermissionData(final String location,
+                    final String[] data) throws IOException
+            {
+                throw new UnsupportedOperationException();
+
+            }
+
+            public void saveConditionalPermissionInfos(final String[] infos)
+                    throws IOException
+            {
+                throw new UnsupportedOperationException();
+
+            }
+
+            public String[] getPermissionData(final String location)
+                    throws IOException
+            {
+                return null;
+            }
+
+            public String[] getLocations() throws IOException
+            {
+                return null;
+            }
+
+            public String[] getConditionalPermissionInfos()
+                    throws IOException
+            {
+                return null;
+            }
+        };
+    }
+
+    public void frameworkStart(final BundleContext context)
+            throws BundleException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public void frameworkStop(final BundleContext context)
+            throws BundleException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public void frameworkStopping(final BundleContext context)
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public int getInitialBundleStartLevel()
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public void setInitialBundleStartLevel(final int value)
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public FrameworkLog getFrameworkLog()
+    {
+        return new FrameworkLog()
+        {
+
+            public void log(final FrameworkEvent frameworkEvent)
+            {
+                log(new FrameworkLogEntry(
+                        frameworkEvent.getBundle().getSymbolicName() == null ? frameworkEvent
+                                .getBundle().getLocation() : frameworkEvent
+                                .getBundle().getSymbolicName(),
+                        FrameworkLogEntry.ERROR,
+                        0,
+                        "FrameworkEvent.ERROR", 0, frameworkEvent.getThrowable(), null)); //$NON-NLS-1$
+            }
+
+            public void log(final FrameworkLogEntry logEntry)
+            {
+                System.err.print(logEntry.getEntry() + " "); //$NON-NLS-1$
+                System.err.println(logEntry.getMessage());
+                if (logEntry.getThrowable() != null)
+                {
+                    logEntry.getThrowable().printStackTrace(System.err);
+                }
+            }
+
+            public void setWriter(final Writer newWriter,
+                    final boolean append)
+            {
+                // do nothing
+            }
+
+            public void setFile(final File newFile, final boolean append)
+                    throws IOException
+            {
+                // do nothing
+            }
+
+            public File getFile()
+            {
+                // do nothing
+                return null;
+            }
+
+            public void setConsoleLog(final boolean consoleLog)
+            {
+                // do nothing
+            }
+
+            public void close()
+            {
+                // do nothing
+            }
+        };
+    }
+
+    public BundleData createSystemBundleData() throws BundleException
+    {
+        return new BundleData()
+        {
+
+            public void setStatus(final int value)
+            {
+                // TODO Auto-generated method stub
+
+            }
+
+            public void setStartLevel(final int value)
+            {
+                // TODO Auto-generated method stub
+
+            }
+
+            public void setBundle(final Bundle bundle)
+            {
+                // TODO Auto-generated method stub
+
+            }
+
+            public void save() throws IOException
+            {
+                // TODO Auto-generated method stub
+
+            }
+
+            public void open() throws IOException
+            {
+                // TODO Auto-generated method stub
+
+            }
+
+            public void installNativeCode(final String[] nativepaths)
+                    throws BundleException
+            {
+                // TODO Auto-generated method stub
+
+            }
+
+            public Version getVersion()
+            {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public int getType()
+            {
+                // TODO Auto-generated method stub
+                return 0;
+            }
+
+            public String getSymbolicName()
+            {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public int getStatus()
+            {
+                // TODO Auto-generated method stub
+                return 0;
+            }
+
+            public int getStartLevel()
+            {
+                // TODO Auto-generated method stub
+                return 0;
+            }
+
+            @SuppressWarnings("rawtypes")
+            public Dictionary getManifest() throws BundleException
+            {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public String getLocation()
+            {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public long getLastModified()
+            {
+                // TODO Auto-generated method stub
+                return 0;
+            }
+
+            public String getExecutionEnvironment()
+            {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            @SuppressWarnings("rawtypes")
+            public Enumeration getEntryPaths(final String path)
+            {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public URL getEntry(final String path)
+            {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public String getDynamicImports()
+            {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public File getDataFile(final String path)
+            {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public String[] getClassPath() throws BundleException
+            {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public long getBundleID()
+            {
+                // TODO Auto-generated method stub
+                return 0;
+            }
+
+            public String getActivator()
+            {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public String findLibrary(final String libname)
+            {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public BundleClassLoader createClassLoader(
+                    final ClassLoaderDelegate delegate,
+                    final BundleProtectionDomain domain,
+                    final String[] bundleclasspath)
+            {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public void close() throws IOException
+            {
+                // TODO Auto-generated method stub
+
+            }
+        };
+    }
+
+    public BundleWatcher getBundleWatcher()
+    {
+        throw new UnsupportedOperationException();
+
+    }
+
+    public PlatformAdmin getPlatformAdmin()
+    {
+        throw new UnsupportedOperationException();
+
+    }
+
+    public State getState()
+    {
+        throw new UnsupportedOperationException();
+
+    }
+
+    public ClassLoader getBundleClassLoaderParent()
+    {
+        throw new UnsupportedOperationException();
+
+    }
+
+    public void handleRuntimeError(final Throwable error)
+    {
+        throw new UnsupportedOperationException();
+    }
+}
\ 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/smodel/TestableStructuredModelFactory.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/smodel/TestableStructuredModelFactory.java
new file mode 100644
index 0000000..817ca51
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/mock/smodel/TestableStructuredModelFactory.java
@@ -0,0 +1,322 @@
+package org.eclipse.jst.jsf.test.util.mock.smodel;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.IllegalCharsetNameException;
+
+import org.eclipse.core.internal.runtime.PlatformActivator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.IDocumentExtension3;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jst.jsf.test.util.mock.osgi.BundleHacker;
+import org.eclipse.wst.sse.core.internal.document.IDocumentLoader;
+import org.eclipse.wst.sse.core.internal.encoding.CodedIO;
+import org.eclipse.wst.sse.core.internal.encoding.CodedReaderCreator;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+import org.eclipse.wst.sse.core.internal.encoding.util.Logger;
+import org.eclipse.wst.sse.core.internal.encoding.util.NullInputStream;
+import org.eclipse.wst.sse.core.internal.provisional.IModelLoader;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.document.IEncodedDocument;
+import org.eclipse.wst.sse.core.internal.provisional.exceptions.ResourceInUse;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredPartitioning;
+import org.eclipse.wst.sse.core.internal.util.ProjectResolver;
+import org.eclipse.wst.sse.core.internal.util.URIResolver;
+import org.eclipse.wst.xml.core.internal.encoding.XMLDocumentLoader;
+import org.eclipse.wst.xml.core.internal.modelhandler.ModelHandlerForXML;
+import org.eclipse.wst.xml.core.internal.modelhandler.XMLModelLoader;
+import org.osgi.framework.BundleException;
+
+@SuppressWarnings("deprecation")
+public class TestableStructuredModelFactory
+{
+    public static void hackStatics() throws SecurityException,
+            NoSuchFieldException, BundleException, IllegalArgumentException,
+            IllegalAccessException
+    {
+        new BundleHacker().mockBundleContext(PlatformActivator.class);
+    }
+
+    public IStructuredModel createUnManagedModelFor(final IFile file)
+            throws CoreException, ResourceInUse, IOException
+    {
+        IStructuredModel model = createUnManagedEmptyModelFor(file);
+        final IDocumentLoader loader = model.getModelHandler()
+                .getDocumentLoader();
+        final IEncodedDocument document = loader
+                .createNewStructuredDocument(file);
+
+        model.getStructuredDocument().setText(this, document.get());
+        return model;
+    }
+
+    /**
+     * @param iFile
+     * @param result
+     * @return
+     * @throws CoreException
+     * @throws ResourceInUse
+     */
+    protected IStructuredModel createUnManagedEmptyModelFor(final IFile iFile)
+            throws CoreException, ResourceInUse
+    {
+        final ModelHandlerForXML handler = new ModelHandlerForXML()
+        {
+
+            public IDocumentLoader getDocumentLoader()
+            {
+                return new TestableXMLModelLoader();
+            }
+        };
+        final String id = iFile.getFullPath().toString();
+        final URIResolver resolver = calculateURIResolver(iFile);
+
+        return _commonCreateModel(id, handler, resolver);
+    }
+
+    /**
+     *
+     */
+    private URIResolver calculateURIResolver(final IFile file)
+    {
+        // Note: see comment in plugin.xml for potentially
+        // breaking change in behavior.
+
+        final IProject project = file.getProject();
+        final URIResolver resolver = new ProjectResolver(project);
+        Object location = file.getLocation();
+        if (location == null)
+        {
+            location = file.getLocationURI();
+        }
+        if (location != null)
+        {
+            resolver.setFileBaseLocation(location.toString());
+        }
+        return resolver;
+    }
+
+    private IStructuredModel _commonCreateModel(final String id,
+            final ModelHandlerForXML handler, final URIResolver resolver)
+            throws ResourceInUse
+    {
+        final IModelLoader loader = new XMLModelLoader()
+        {
+
+            public IDocumentLoader getDocumentLoader()
+            {
+                return new TestableXMLModelLoader();
+            }
+        };
+
+        // handler.getModelLoader();
+        final IStructuredModel result = loader.createModel();
+        // in the past, id was null for "unmanaged" case, so we won't
+        // try and set it
+        if (id != null)
+        {
+            // result.setId(id);
+        }
+        result.setModelHandler(handler);
+        result.setResolver(resolver);
+        // some obvious redunancy here that maybe could be improved
+        // in future, but is necessary for now
+        result.setBaseLocation(id);
+        if (resolver != null)
+        {
+            resolver.setFileBaseLocation(id);
+        }
+        // addFactories(result, handler);
+        return result;
+    }
+
+    public static final String NO_SPEC_DEFAULT = "NoSpecDefault"; //$NON-NLS-1$
+
+    /**
+     * Note: once this instance is created, trace info still needs to be
+     * appended by caller, depending on the context its created.
+     */
+    public static EncodingMemento createEncodingMemento(
+            final String detectedCharsetName, final String reason,
+            final String specDefaultEncoding)
+    {
+        EncodingMemento result = new EncodingMemento();
+        result = new EncodingMemento();
+        final String javaCharset = "UTF-8";
+        result.setJavaCharsetName(javaCharset);
+        result.setDetectedCharsetName(detectedCharsetName);
+        // TODO: if detectedCharset and spec default is
+        // null, need to use "work
+        // bench based" defaults.
+        if (specDefaultEncoding == null)
+        {
+            result.setAppropriateDefault(NO_SPEC_DEFAULT);
+        }
+        else
+        {
+            result.setAppropriateDefault(specDefaultEncoding);
+        }
+        // check if valid
+        try
+        {
+            Charset.isSupported(javaCharset);
+        }
+        catch (final IllegalCharsetNameException e)
+        {
+            result.setInvalidEncoding(javaCharset);
+        }
+
+        return result;
+    }
+
+    private static final class TestableXMLModelLoader extends XMLDocumentLoader
+    {
+
+        public IEncodedDocument createNewStructuredDocument()
+        {
+            final IEncodedDocument structuredDocument = newEncodedDocument();
+            // Make sure every structuredDocument has an Encoding Memento,
+            // which is the default one for "empty" structuredDocuments
+            final String charset = "UTF-8";
+            final String specDefaultCharset = getDocumentEncodingDetector()
+                    .getSpecDefaultEncoding();
+            structuredDocument.setEncodingMemento(createEncodingMemento(
+                    charset, EncodingMemento.DEFAULTS_ASSUMED_FOR_EMPTY_INPUT,
+                    specDefaultCharset));
+
+            // String lineDelimiter = null;
+            // if (lineDelimiter != null)
+            // structuredDocument.setPreferredLineDelimiter(lineDelimiter);
+
+            final IDocumentPartitioner defaultPartitioner = getDefaultDocumentPartitioner();
+            if (structuredDocument instanceof IDocumentExtension3)
+            {
+                ((IDocumentExtension3) structuredDocument)
+                        .setDocumentPartitioner(
+                                IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING,
+                                defaultPartitioner);
+            }
+            else
+            {
+                structuredDocument.setDocumentPartitioner(defaultPartitioner);
+            }
+            defaultPartitioner.connect(structuredDocument);
+
+            return structuredDocument;
+        }
+
+        /**
+         * This abstract version should handle most cases, but won't if
+         * contentType is sensitive to encoding, and/or embedded types
+         */
+
+        public IEncodedDocument createNewStructuredDocument(final IFile iFile)
+                throws IOException, CoreException
+        {
+            final IEncodedDocument structuredDocument = createNewStructuredDocument();
+
+            // String lineDelimiter = getPreferredNewLineDelimiter(iFile);
+            // if (lineDelimiter != null)
+            // structuredDocument.setPreferredLineDelimiter(lineDelimiter);
+
+            try
+            {
+                // final CodedReaderCreator creator = getCodedReaderCreator();
+                // creator.set(iFile);
+                // fEncodingMemento = new
+                // EncodingMemento();//creator.getEncodingMemento();
+                // structuredDocument.setEncodingMemento(fEncodingMemento);
+                // fFullPreparedReader =
+                // getCodedReaderCreator().getCodedReader();
+                InputStream streamToReturn = getResettableStream(iFile);
+                streamToReturn.reset();
+                Charset charset = Charset.forName("UTF-8");
+                CharsetDecoder charsetDecoder = charset.newDecoder();
+
+                fFullPreparedReader = new BufferedReader(new InputStreamReader(
+                        streamToReturn, charsetDecoder), CodedIO.MAX_BUF_SIZE);
+                fFullPreparedReader.mark(CodedIO.MAX_BUF_SIZE);
+
+                setDocumentContentsFromReader(structuredDocument,
+                        fFullPreparedReader);
+            }
+            finally
+            {
+                if (fFullPreparedReader != null)
+                {
+                    fFullPreparedReader.close();
+                }
+            }
+            return structuredDocument;
+        }
+
+        private InputStream getResettableStream(IFile fIFile)
+                throws CoreException, IOException
+        {
+
+            InputStream resettableStream = null;
+
+            if (fIFile != null)
+            {
+                InputStream inputStream = null;
+                try
+                {
+                    // note we always get contents, even if out of synch
+                    inputStream = fIFile.getContents(true);
+                }
+                catch (CoreException e)
+                {
+                    // SHOULD actually check for existence of
+                    // fIStorage, but
+                    // for now will just assume core exception
+                    // means it
+                    // doesn't exist on file system, yet.
+                    // and we'll log, just in case its a noteable error
+                    Logger.logException(e);
+                    inputStream = new NullInputStream();
+                }
+                resettableStream = new BufferedInputStream(inputStream,
+                        CodedIO.MAX_BUF_SIZE);
+            }
+            // else
+            // {
+            // if (fInputStream != null)
+            // {
+            // if (fInputStream.markSupported())
+            // {
+            // resettableStream = fInputStream;
+            // // try {
+            // resettableStream.reset();
+            // // }
+            // // catch (IOException e) {
+            // // // assumed just hasn't been marked yet, so ignore
+            // // }
+            // }
+            // else
+            // {
+            // resettableStream = new BufferedInputStream(
+            // fInputStream, CodedIO.MAX_BUF_SIZE);
+            // }
+            // }
+            // }
+
+            if (resettableStream == null)
+            {
+                resettableStream = new NullInputStream();
+            }
+
+            // mark this once, stream at "zero" position
+            resettableStream.mark(CodedReaderCreator.MAX_MARK_SIZE);
+            return resettableStream;
+        }
+
+    }
+
+}