Common JUnit test environment plugin
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/.classpath b/jsf/tests/org.eclipse.jst.jsf.test.util/.classpath
new file mode 100644
index 0000000..751c8f2
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/.project b/jsf/tests/org.eclipse.jst.jsf.test.util/.project
new file mode 100644
index 0000000..00bf754
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.jst.jsf.test.util</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
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
new file mode 100644
index 0000000..394c48d
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/META-INF/MANIFEST.MF
@@ -0,0 +1,19 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Util Plug-in
+Bundle-SymbolicName: org.eclipse.jst.jsf.test.util
+Bundle-Version: 1.0.0
+Bundle-Activator: org.eclipse.jst.jsf.test.util.Activator
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.core.resources,
+ org.eclipse.jst.j2ee,
+ org.eclipse.jst.j2ee.core,
+ org.eclipse.jst.j2ee.web,
+ org.eclipse.wst.common.frameworks,
+ org.eclipse.jdt.core,
+ org.junit,
+ org.eclipse.wst.internet.proxy
+Export-Package: org.eclipse.jst.jsf.test.util
+Eclipse-LazyStart: true
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/build.properties b/jsf/tests/org.eclipse.jst.jsf.test.util/build.properties
new file mode 100644
index 0000000..34d2e4d
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/Activator.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/Activator.java
new file mode 100644
index 0000000..74fe7f4
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/Activator.java
@@ -0,0 +1,53 @@
+package org.eclipse.jst.jsf.test.util;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+	// The plug-in ID
+	/**
+	 * the plugin's unique id
+	 */
+	public static final String PLUGIN_ID = "org.eclipse.jst.jsf.test.util";
+
+	// The shared instance
+	private static Activator plugin;
+	
+	/**
+	 * The constructor
+	 */
+	public Activator() {
+		plugin = this;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+	 */
+	public void stop(BundleContext context) throws Exception {
+		plugin = null;
+		super.stop(context);
+	}
+
+	/**
+	 * Returns the shared instance
+	 *
+	 * @return the shared instance
+	 */
+	public static Activator getDefault() {
+		return plugin;
+	}
+
+}
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/JDTTestEnvironment.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/JDTTestEnvironment.java
new file mode 100644
index 0000000..900f28d
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/JDTTestEnvironment.java
@@ -0,0 +1,105 @@
+package org.eclipse.jst.jsf.test.util;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+
+/**
+ * Test environment for doing project tests involving JDT dependencies
+ * @author cbateman
+ *
+ */
+public class JDTTestEnvironment {
+	
+	private final ProjectTestEnvironment  _projectTestEnvironment;
+	
+	/**
+	 * @param projectTestEnvironment
+	 */
+	public JDTTestEnvironment(ProjectTestEnvironment projectTestEnvironment)
+	{
+		_projectTestEnvironment = projectTestEnvironment;
+	}
+
+	/**
+	 * @return the supporting IProject test environment
+	 */
+	public ProjectTestEnvironment getProjectEnvironment()
+	{
+		return _projectTestEnvironment;
+	}
+	
+	/**
+	 * @param name
+	 * @return the IFolder handle, creating it if it doesn't exist
+	 * @throws CoreException 
+	 */
+	public IFolder getSourceFolder(final String name) throws CoreException
+	{
+		IProject project = _projectTestEnvironment.getTestProject();
+		IFolder folder = project.getFolder(name);
+ 
+		if (!folder.exists())
+		{
+			folder.create(true, true, new NullProgressMonitor());
+		}
+		
+		return folder;
+	}
+	
+	/**
+	 * @param folderName
+	 * @return the package fragment root for the folder name; resource may or may not exist
+	 * @throws CoreException 
+	 */
+	public IPackageFragmentRoot getPackageFragmentRoot(final String folderName) throws CoreException
+	{
+		final IJavaProject javaProject = JavaCore.create(_projectTestEnvironment.getTestProject());
+		return javaProject.getPackageFragmentRoot(getSourceFolder(folderName));
+	}
+	
+	/**
+	 * Creates a new Java class file in the folder/package/file name specified with contents as the
+	 * the Java code.
+	 * 
+	 * @param folder
+	 * @param packageName
+	 * @param className
+	 * @param contents
+	 * @return the created compiliation unit
+	 * @throws CoreException 
+	 * @throws JavaModelException
+	 */
+	public ICompilationUnit addSourceFile(final String folder, final String packageName, final String className, final String contents) throws CoreException, JavaModelException
+	{
+		IPackageFragmentRoot root = getPackageFragmentRoot(folder);
+		
+		IPackageFragment packageFrag = root.getPackageFragment(packageName);
+		
+		if (!packageFrag.exists())
+		{
+	        packageFrag = 
+	            root.createPackageFragment(packageName, 
+	                                true, new NullProgressMonitor());
+		}
+
+		ICompilationUnit newCompUnit = 
+            packageFrag.createCompilationUnit(className+".java", contents, true, new NullProgressMonitor());
+        return newCompUnit;
+	}
+
+    /**
+     * @return the IJavaProject instance for this test environment object
+     */
+    public IJavaProject getJavaProject() 
+    {
+        return JavaCore.create(_projectTestEnvironment.getTestProject());
+    }
+}
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/JavaCodeResource.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/JavaCodeResource.java
new file mode 100644
index 0000000..3683b35
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/JavaCodeResource.java
@@ -0,0 +1,69 @@
+package org.eclipse.jst.jsf.test.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import org.osgi.framework.Bundle;
+
+/**
+ * Represents a piece of java code (usually a full compilation unit) that is loaded
+ * from a static test file somewhere.  
+ * 
+ * @author cbateman
+ *
+ */
+public class JavaCodeResource 
+{
+    private String      _code;
+    
+    /**
+     * Attempts to load the code from the path relative to bundle
+     * 
+     * @param bundle
+     * @param path
+     * @throws IOException
+     */
+    public void load(Bundle  bundle, String path) throws IOException
+    {
+        URL url = bundle.getEntry(path);
+        
+        if (url == null)
+        {
+            throw new IOException("Could not locate "+path+" in bundle "+bundle.getSymbolicName());
+        }
+        
+        InputStream stream = null;
+        
+        try
+        {
+            stream = url.openStream();
+            ByteArrayOutputStream bufferStream = new ByteArrayOutputStream();
+            byte[]  buffer = new byte[2048];
+            int bytesRead = 0;
+            
+            while ((bytesRead = stream.read(buffer)) != -1)
+            {
+                bufferStream.write(buffer, 0, bytesRead);
+            }
+            
+            _code = bufferStream.toString();
+        }
+        finally
+        {
+            if (stream != null)
+            {
+                stream.close();
+            }
+        }
+    }
+    
+    /**
+     * @return the code or null if failed to load
+     */
+    public String getCode()
+    {
+        return _code;
+    }
+}
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/ProjectTestEnvironment.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/ProjectTestEnvironment.java
new file mode 100644
index 0000000..41ac301
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/ProjectTestEnvironment.java
@@ -0,0 +1,160 @@
+/***************************************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others. 
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors: 
+ *   Oracle -- adapted WizardUtil class for EMF faces config model testing
+ *   IBM Corporation - initial API and implementation
+ **************************************************************************************************/
+package org.eclipse.jst.jsf.test.util;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jst.j2ee.internal.web.archive.operations.WebFacetProjectCreationDataModelProvider;
+import org.eclipse.wst.common.componentcore.datamodel.properties.IFacetProjectCreationDataModelProperties;
+import org.eclipse.wst.common.frameworks.datamodel.DataModelFactory;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
+
+/**
+ * Utility class for launching JSF-related wizard operations. 
+ *
+ * @author spaxton, cbateman
+ */
+public class ProjectTestEnvironment {
+	private boolean projectCreated = false;
+	private final String  _projectName;
+	private IProject		_project;
+
+	
+	/**
+	 * @param projectName
+	 */
+	public ProjectTestEnvironment(final String projectName)
+	{
+		_projectName = projectName;
+	}
+	
+	/**
+	 * @return true if the project is in a valid created state
+	 */
+	public boolean isProjectCreated() {
+		return projectCreated;
+	}
+	
+	/**
+	 * Construct the basic web project
+	 */
+	public void createProject() {
+		if(!isProjectCreated()) {
+			// first delete the projects of these names, if present
+			IWorkspace workspace = ResourcesPlugin.getWorkspace();
+			IResource oldWebProj = workspace.getRoot().getProject(_projectName);
+
+			try {			
+                if (oldWebProj != null && oldWebProj.isAccessible())
+                {
+                    workspace.delete(new IResource[] { oldWebProj }, true, null);
+                }
+			} catch (CoreException ce) {
+				ce.printStackTrace();
+			}
+			
+			try {
+				_project = createWebProject(_projectName);
+			} catch (Throwable t) {
+				t.printStackTrace();
+			}
+		
+			projectCreated = true;
+		}
+	}
+
+	/**
+	 * @param projectName
+	 * @return the web project
+	 * @throws Exception
+	 */
+	private IProject createWebProject(String projectName) throws Exception {
+		if(!isProjectCreated()) {
+			IDataModel dataModel = DataModelFactory.createDataModel(new WebFacetProjectCreationDataModelProvider());
+			dataModel.setProperty(IFacetProjectCreationDataModelProperties.FACET_PROJECT_NAME, projectName);
+			dataModel.getDefaultOperation().execute(new NullProgressMonitor(), null);
+		}
+		return ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
+	}
+
+	/**
+	 * Clears the projectCreated flag, allowing createProject to be called to reset
+	 * the web project back to it's initial state
+	 */
+	public void setProjectDirtied() {
+		projectCreated = false;
+	}
+
+	/**
+	 * Forces recreation of the test project - to be used after unit tests
+	 * that dirty the project state.  
+	 */
+	public void recreateProject() {
+		setProjectDirtied();
+		createProject();
+	}
+
+	/**
+	 * Should call createProject first. 
+	 * @return the IProject
+	 */
+	public IProject getTestProject() 
+	{
+		if (projectCreated)
+		{
+			return _project;
+		}
+		
+		return null;
+	}
+
+//	public void checkAndAddFacesConfig() {
+//		final IProject project = getTestProject();
+//		IContainer container = ComponentCore.createComponent(project).getRootFolder().getFolder("/WEB-INF").getUnderlyingFolder();
+//		IFile facesConfigFile  = ResourcesPlugin.getWorkspace().getRoot().getFile(container.getFullPath().append(new Path("faces-config.xml"))); //$NON-NLS-1$
+//		IFile facesConfigFile1  = ResourcesPlugin.getWorkspace().getRoot().getFile(container.getFullPath().append(new Path("faces-config1.xml"))); //$NON-NLS-1$
+//		IFile facesConfigFile2  = ResourcesPlugin.getWorkspace().getRoot().getFile(container.getFullPath().append(new Path("faces-config2.xml"))); //$NON-NLS-1$
+//		
+//		if(facesConfigFile.exists()) {
+//			return;
+//		} else {
+//			// there is no faces-config, so add our starting template
+//			try {
+//				String sourcePath = Platform.asLocalURL(Platform.find(Platform.getBundle("org.eclipse.jst.jsf.facesconfig.tests"), new Path("/template/faces-config.xml"))).getPath().toString(); //$NON-NLS-1$ //$NON-NLS-2$	
+//				File f = new File(sourcePath);
+//				FileInputStream sourceStream = new FileInputStream(f);
+//				facesConfigFile.create(sourceStream, true, null);
+//				sourceStream.close();
+//
+//				String sourcePath1 = Platform.asLocalURL(Platform.find(Platform.getBundle("org.eclipse.jst.jsf.facesconfig.tests"), new Path("/template/faces-config1.xml"))).getPath().toString(); //$NON-NLS-1$ //$NON-NLS-2$	
+//				File f1 = new File(sourcePath1);
+//				FileInputStream sourceStream1 = new FileInputStream(f1);
+//				facesConfigFile1.create(sourceStream1, true, null);
+//				sourceStream1.close();
+//
+//				String sourcePath2 = Platform.asLocalURL(Platform.find(Platform.getBundle("org.eclipse.jst.jsf.facesconfig.tests"), new Path("/template/faces-config2.xml"))).getPath().toString(); //$NON-NLS-1$ //$NON-NLS-2$	
+//				File f2 = new File(sourcePath2);
+//				FileInputStream sourceStream2 = new FileInputStream(f2);
+//				facesConfigFile2.create(sourceStream2, true, null);
+//				sourceStream2.close();
+//			} catch (IOException ioe) {
+//			} catch (CoreException ce) {
+//			}
+//
+//		}
+//		
+//	}
+}
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/sanity/TestJDTTestEnvironment.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/sanity/TestJDTTestEnvironment.java
new file mode 100644
index 0000000..680121f
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/sanity/TestJDTTestEnvironment.java
@@ -0,0 +1,66 @@
+package org.eclipse.jst.jsf.test.util.sanity;
+
+import junit.framework.TestCase;
+
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jst.jsf.test.util.Activator;
+import org.eclipse.jst.jsf.test.util.JDTTestEnvironment;
+import org.eclipse.jst.jsf.test.util.JavaCodeResource;
+import org.eclipse.jst.jsf.test.util.ProjectTestEnvironment;
+
+/**
+ * @author cbateman
+ *
+ */
+public class TestJDTTestEnvironment extends TestCase 
+{
+	private  ProjectTestEnvironment  		_projectTestEnvironment;
+	private  String 			     		_testClass1;
+	
+	protected void setUp() throws Exception {
+		super.setUp();
+		_projectTestEnvironment = new ProjectTestEnvironment("JDTTestProject");
+		_projectTestEnvironment.createProject();
+        JavaCodeResource codeRes = new JavaCodeResource();
+        codeRes.load(Activator.getDefault().getBundle(), "/testdata/TestClass1.java.data");
+        _testClass1 = codeRes.getCode();
+	}
+
+	/**
+	 * Test basic java class file creation
+	 */
+	public void testCreateJavaClassFile()
+	{
+		JDTTestEnvironment  jdtTestEnvironment = new JDTTestEnvironment(_projectTestEnvironment);
+		
+		ICompilationUnit compUnit = null;
+		try
+		{
+			compUnit =
+				jdtTestEnvironment.
+					addSourceFile("src", "com.test", "TestClass1", _testClass1.toString());
+
+		}
+		catch (Exception e)
+		{
+			fail(e.getLocalizedMessage());
+		}
+		
+		assertNotNull(compUnit);
+		assertTrue(compUnit.getResource().isAccessible());
+        
+        try
+        {
+            IType type = jdtTestEnvironment.getJavaProject().findType("com.test.TestClass1");
+            assertNotNull(type);
+            assertTrue(type.getMethods().length == 1);
+            assertTrue(type.getMethods()[0].getElementName().equals("amethod"));
+        }
+        catch (JavaModelException jme)
+        {
+            fail(jme.getLocalizedMessage());
+        }
+	}
+}
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/sanity/TestProjectTestEnvironment.java b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/sanity/TestProjectTestEnvironment.java
new file mode 100644
index 0000000..7113546
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/src/org/eclipse/jst/jsf/test/util/sanity/TestProjectTestEnvironment.java
@@ -0,0 +1,33 @@
+package org.eclipse.jst.jsf.test.util.sanity;
+
+import junit.framework.TestCase;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jst.jsf.test.util.ProjectTestEnvironment;
+
+/**
+ * Test the base Project Test Environment
+ * 
+ * @author cbateman
+ *
+ */
+public class TestProjectTestEnvironment extends TestCase 
+{
+	/**
+	 * Test creating a basic test project environment
+	 */
+	public void testCreateProject()
+	{
+//		InternetPlugin iPlugin = InternetPlugin.getInstance();
+//		IPreferenceStore store = iPlugin.getPreferenceStore();
+		
+		ProjectTestEnvironment testEnv = new ProjectTestEnvironment("TestProject1");
+		testEnv.createProject();
+		assertTrue(testEnv.isProjectCreated());
+		
+		IProject project = testEnv.getTestProject();
+		
+		assertNotNull(project);
+		assertTrue(project.isAccessible());
+	}
+}
diff --git a/jsf/tests/org.eclipse.jst.jsf.test.util/testdata/TestClass1.java.data b/jsf/tests/org.eclipse.jst.jsf.test.util/testdata/TestClass1.java.data
new file mode 100644
index 0000000..8c4518b
--- /dev/null
+++ b/jsf/tests/org.eclipse.jst.jsf.test.util/testdata/TestClass1.java.data
@@ -0,0 +1,9 @@
+package com.test;
+
+public class TestClass1
+{
+	public java.lang.String amethod()
+	{
+		return "A string";
+	}
+}
\ No newline at end of file