Add JSF 2.0 Facet, install support and presets.
Refactor JSFUtils to make it more flexible, testable and eliminate duplicate code.
Add JSFUtils20 to handle specializations for 2.0 projects.
Add some test coverage of the JSFUtils classes.
diff --git a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/webxml/WebXmlUpdater.java b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/webxml/WebXmlUpdater.java
index 4febdb6..6296248 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/webxml/WebXmlUpdater.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/webxml/WebXmlUpdater.java
@@ -17,7 +17,7 @@
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jst.j2ee.model.IModelProvider;
 import org.eclipse.jst.j2ee.model.ModelProviderManager;
-import org.eclipse.jst.javaee.web.internal.impl.WebAppImpl;
+import org.eclipse.jst.javaee.web.WebApp;
 import org.eclipse.jst.jsf.common.webxml.internal.AbstractWebXmlUpdater;
 import org.eclipse.jst.jsf.common.webxml.internal.WebXmlUpdaterForJ2EE;
 import org.eclipse.jst.jsf.common.webxml.internal.WebXmlUpdaterForJavaEE;
@@ -177,9 +177,9 @@
 
         if (webAppObj != null)
         {
-            if (webAppObj instanceof WebAppImpl) // Java EE
+            if (webAppObj instanceof WebApp) // Java EE
                 return new WebXmlUpdaterForJavaEE(webAppObj, project, getProvider(), monitor);
-            else if (webAppObj instanceof org.eclipse.jst.j2ee.webapplication.internal.impl.WebAppImpl) // J2EE
+            else if (webAppObj instanceof org.eclipse.jst.j2ee.webapplication.WebApp) // J2EE
                 return new WebXmlUpdaterForJ2EE(webAppObj, project, getProvider(), monitor);
         }
 
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/plugin.properties b/jsf/plugins/org.eclipse.jst.jsf.core/plugin.properties
index acc4dce..c93ff90 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.core/plugin.properties
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/plugin.properties
@@ -16,6 +16,9 @@
 
 JSFv12Project=JavaServer Faces v1.2 Project
 JSFv12PresetDesc=Configures a Dynamic Web application to use JSF v1.2
+
+JSFv20Project=JavaServer Faces v2.0 Project
+JSFv20PresetDesc=Configures a Dynamic Web application to use JSF v2.0
 # ====================================================================
 
 pluginName = Constraints Model
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/plugin.xml b/jsf/plugins/org.eclipse.jst.jsf.core/plugin.xml
index c85bd62..cd33c67 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.core/plugin.xml
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/plugin.xml
@@ -122,6 +122,27 @@
         %JSFv12PresetDesc
      </description>
      </static-preset>
+     <static-preset
+           id="preset.jst.jsf.v2_0">
+        <label>
+           %JSFv20Project
+        </label>
+        <facet
+              id="jst.java"
+              version="5.0">
+        </facet>
+        <facet
+              id="jst.web"
+              version="2.5">
+        </facet>
+        <facet
+              id="jst.jsf"
+              version="2.0">
+        </facet>
+        <description>
+           %JSFv20PresetDesc
+        </description>
+     </static-preset>
   </extension>
 
   <extension point="org.eclipse.wst.common.project.facet.core.runtimes">
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/IJSFCoreConstants.java b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/IJSFCoreConstants.java
index 7e2d9c8..0e8ff1a 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/IJSFCoreConstants.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/IJSFCoreConstants.java
@@ -10,6 +10,8 @@
  *******************************************************************************/
 package org.eclipse.jst.jsf.core;
 
+import org.eclipse.wst.common.project.facet.core.IProjectFacet;
+
 /**
  * JSF Core framework constants
  * 
@@ -52,7 +54,25 @@
      * The constant id for a JSF 1.2 project
      */
     public final static String                  JSF_VERSION_1_2 = FACET_VERSION_1_2;
+
+    /**
+     * The facet version for a JSF 2.0 project
+     */
+    public static final String                  FACET_VERSION_2_0 = "2.0"; //$NON-NLS-1$
+    /**
+     * The version string for a JSF 2.0 project
+     */
+    public static final String JSF_VERSION_2_0 = FACET_VERSION_2_0;
     
+    /**
+     * @param facet
+     * @return true if the facet is a jsf facet.
+     * 
+     */
+    public static boolean isJSFFacet(final IProjectFacet facet)
+    {
+        return JSF_CORE_FACET_ID.equals(facet.getId());
+    }
     private IJSFCoreConstants()
     {
         // no instantiation
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/JSFVersion.java b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/JSFVersion.java
index 322894e..f7337b3 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/JSFVersion.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/JSFVersion.java
@@ -10,6 +10,13 @@
  *******************************************************************************/
 package org.eclipse.jst.jsf.core;
 
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.wst.common.project.facet.core.FacetedProjectFramework;
+import org.eclipse.wst.common.project.facet.core.IFacetedProject;
+import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
+import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager;
+
 /**
  * @author gekessle
  *
@@ -31,7 +38,11 @@
 	/**
 	 * Supports JSF Version 1.1
 	 */
-	V1_2;
+	V1_2,
+	/**
+	 * Supports JSF Version 2.0
+	 */
+	V2_0;
 	
     @Override
     public String toString() {
@@ -43,6 +54,8 @@
                 return IJSFCoreConstants.JSF_VERSION_1_1;
             case V1_2:
                 return IJSFCoreConstants.JSF_VERSION_1_2;
+            case V2_0:
+                return IJSFCoreConstants.JSF_VERSION_2_0;
             case UNKNOWN:
                 return "unknown"; //$NON-NLS-1$
             default:
@@ -68,6 +81,10 @@
         {
             return V1_2;
         }
+        else if (IJSFCoreConstants.FACET_VERSION_2_0.equals(valueAsString))
+        {
+            return V2_0;
+        }
         else if ("unknown".equals(valueAsString)) //$NON-NLS-1$
         {
             return UNKNOWN;
@@ -77,4 +94,55 @@
             return null;
         }
     }
+    
+    /**
+     * @param facetVersion
+     * @return the jsf version for the facet version
+     * @throw IllegalArgumentException if the underlying facet is not a JSF facet.
+     */
+    public static JSFVersion valueOfFacetVersion(final IProjectFacetVersion facetVersion)
+    {
+        if (!IJSFCoreConstants.isJSFFacet(facetVersion.getProjectFacet()))
+        {
+            throw new IllegalArgumentException("Not a JSF facet: "+facetVersion.getProjectFacet().toString()); //$NON-NLS-1$
+        }
+        
+        String versionString = facetVersion.getVersionString();
+        if (versionString != null)
+        {
+            return valueOfString(versionString);
+        }
+        return null;
+    }
+    
+    /**
+     * @param project
+     * @return the project version of the project.
+     */
+    public static JSFVersion valueOfProject(final IProject project)
+    {
+        try
+        {
+            if (project != null && FacetedProjectFramework.isFacetedProject(project))
+            {
+                IFacetedProject fProj = ProjectFacetsManager.create(project);
+                if (fProj != null)
+                {
+                    IProjectFacetVersion projectFacetVersion = fProj.getProjectFacetVersion(
+                            ProjectFacetsManager.getProjectFacet(IJSFCoreConstants.JSF_CORE_FACET_ID));
+                    if (projectFacetVersion != null)
+                    {
+                        return valueOfFacetVersion(projectFacetVersion);
+                    }
+                }
+            }
+        }
+        catch(final CoreException ce)
+        {
+            // ignore and fall-through
+            // TODO: is this worth logging?
+        }
+        return null;
+    }
+
 }
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/Messages.java b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/Messages.java
index bd04d43..9f92eec 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/Messages.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/Messages.java
@@ -21,6 +21,11 @@
 public class Messages extends NLS {
 	private static final String BUNDLE_NAME = "org.eclipse.jst.jsf.core.internal.messages"; //$NON-NLS-1$
 
+    /**
+     * see messages.properties
+     */
+    public static String Could_Not_GetJSFVersion;
+
 	/**
 	 * see messages.properties
 	 */
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/launch/JSFFileURL.java b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/launch/JSFFileURL.java
index bb3192d..3bfc32e 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/launch/JSFFileURL.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/launch/JSFFileURL.java
@@ -11,19 +11,13 @@
 
 package org.eclipse.jst.jsf.core.internal.launch;
 
-import java.util.Iterator;
-
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
 import org.eclipse.jst.j2ee.internal.web.jfaces.extension.FileURL;
 import org.eclipse.jst.j2ee.model.IModelProvider;
 import org.eclipse.jst.j2ee.model.ModelProviderManager;
-import org.eclipse.jst.j2ee.webapplication.Servlet;
-import org.eclipse.jst.j2ee.webapplication.ServletMapping;
-import org.eclipse.jst.j2ee.webapplication.WebApp;
-import org.eclipse.jst.jsf.core.internal.project.facet.JSFUtils11;
-import org.eclipse.jst.jsf.core.internal.project.facet.JSFUtils12;
+import org.eclipse.jst.jsf.core.internal.project.facet.JSFUtilFactory;
+import org.eclipse.jst.jsf.core.internal.project.facet.JSFUtils;
 
 /**
  * Extends the FileURL extension-point so that a JSF JSP page
@@ -33,7 +27,8 @@
  * @author Gerry Kessler - Oracle
  *
  */
-public class JSFFileURL implements FileURL {
+public class JSFFileURL implements FileURL 
+{
 
 	/**
 	 * If this is a JSP page, this will return a URL using the first valid servlet-mapping to the Faces Servlet
@@ -58,133 +53,11 @@
 		//if servlet is present, we will change the url based on first mapping found 
 		IModelProvider provider = ModelProviderManager.getModelProvider(resource.getProject());
 		Object webAppObj = provider.getModelObject();
-		if (webAppObj != null){
+		final JSFUtils jsfUtil = new JSFUtilFactory().create(resource.getProject());
+		if (webAppObj != null && jsfUtil != null){
 			//methods below returning the path are identical except for the APIs required
-			if (JSFUtils12.isWebApp25(webAppObj)){
-				return getJavaEEFileURLPath(webAppObj, resource, existingURL);
-			} 
-			else if (JSFUtils11.isWebApp24(webAppObj) || JSFUtils11.isWebApp23(webAppObj)) {
-				return getJ2EEFileURLPath(webAppObj, resource, existingURL);
-			}
-		}
-		return null;			
-	}
-	
-	private IPath getJ2EEFileURLPath(Object webAppObj, IResource resource,
-			IPath existingURL) {
-		WebApp webApp = (WebApp)webAppObj;
-		if (webApp != null){
-			Servlet servlet = JSFUtils11.findJSFServlet(webApp);
-			if (servlet == null)//if no faces servlet, do nothing
-				return null;
-			
-			//if not a JSF page, do nothing
-			if (!isJSFPage(resource))
-				return null;
-			
-			String defaultSuffix = JSFUtils11.getDefaultSuffix(webApp);
-			//is the resource using default_suffix
-			boolean canUseExtensionMapping = resource.getFileExtension().equalsIgnoreCase(defaultSuffix);
-			
-			//if not using default extension and is not a known file extension, then we will abort
-			if (! canUseExtensionMapping && ! isValidKnownExtension(resource.getFileExtension()))
-				return null;
-			
-			Iterator mappings = servlet.getMappings().iterator();
-			ServletMapping map = null;
-			String foundFileExtension = null;
-			String foundPrefixMapping = null;
-			while (mappings.hasNext()){
-				map = (ServletMapping)mappings.next();
-				
-				foundFileExtension = JSFUtils11.getFileExtensionFromMap(map);
-				if (foundFileExtension != null && canUseExtensionMapping) {
-					return existingURL.removeFileExtension().addFileExtension(foundFileExtension);
-				}
-				
-				if (foundPrefixMapping == null){
-					foundPrefixMapping = JSFUtils11.getPrefixMapping(map);				
-				}
-				
-			}
-			if (foundPrefixMapping != null)				
-				return new Path(foundPrefixMapping).append(existingURL); 
-				
-			if (! canUseExtensionMapping && foundFileExtension != null){
-				//we could prompt user that this may not work...
-				//for now we will return the extension mapping
-				return existingURL.removeFileExtension().addFileExtension(foundFileExtension);
-			}
-			
-			//we could, at this point, add a url mapping to the faces servlet, or prompt user that it may be a good idea to add one... ;-
+		    return jsfUtil.getFileUrlPath(webAppObj, resource, existingURL);
 		}
 		return null;
 	}
-
-	private IPath getJavaEEFileURLPath(Object webAppObj, IResource resource,
-			IPath existingURL) {
-		org.eclipse.jst.javaee.web.WebApp webApp = (org.eclipse.jst.javaee.web.WebApp )webAppObj;
-		if (webApp != null){
-			org.eclipse.jst.javaee.web.Servlet servlet = JSFUtils12.findJSFServlet(webApp);
-			if (servlet == null)//if no faces servlet, do nothing
-				return null;
-			
-			//if not a JSF page, do nothing
-			if (!isJSFPage(resource))
-				return null;
-			
-			String defaultSuffix = JSFUtils12.getDefaultSuffix(webApp);
-			//is the resource using default_suffix
-			boolean canUseExtensionMapping = resource.getFileExtension().equalsIgnoreCase(defaultSuffix);
-			
-			//if not using default extension and is not a known file extension, then we will abort
-			if (! canUseExtensionMapping && ! isValidKnownExtension(resource.getFileExtension()))
-				return null;
-			
-			Iterator mappings = webApp.getServletMappings().iterator();
-			org.eclipse.jst.javaee.web.ServletMapping map = null;
-			String foundFileExtension = null;
-			while (mappings.hasNext()){
-				map = (org.eclipse.jst.javaee.web.ServletMapping)mappings.next();
-				if (map.getServletName().equals(servlet.getServletName())){
-					foundFileExtension = JSFUtils12.getFileExtensionFromMap(map);
-					if (foundFileExtension != null && canUseExtensionMapping) {
-						return existingURL.removeFileExtension().addFileExtension(foundFileExtension);
-					}
-						
-					String foundPrefixMapping = JSFUtils12.getPrefixMapping(map);
-					if (foundPrefixMapping != null){						
-						return new Path(foundPrefixMapping).append(existingURL); 
-					}
-				}
-			}
-			
-			if (! canUseExtensionMapping && foundFileExtension != null){
-				//we could prompt user that this may not work...
-				//for now we will return the extension mapping
-				return existingURL.removeFileExtension().addFileExtension(foundFileExtension);
-			}
-			
-			//we could, at this point, add a url mapping to the faces servlet, or prompt user that it may be a good idea to add one... ;-
-		}
-
-		return null;
-	}
-
-	private boolean isValidKnownExtension(String fileExtension) {
-		if ((	fileExtension.equalsIgnoreCase("jsp") ||  //$NON-NLS-1$
-				fileExtension.equalsIgnoreCase("jspx") ||  //$NON-NLS-1$
-				fileExtension.equalsIgnoreCase("jsf") || //$NON-NLS-1$
-				fileExtension.equalsIgnoreCase("xhtml"))) //$NON-NLS-1$
-			return true;
-
-		return false;
-	}
-
-	
-	private boolean isJSFPage(IResource resource) {
-		// currently always return true.
-		// need to find quick way of determining whether this is a JSF JSP Page
-		return true;
-	}
 }
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/messages.properties b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/messages.properties
index 2019bcf..57bad76 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/messages.properties
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/messages.properties
@@ -60,6 +60,7 @@
 
 JARFileJSFAppConfigProvider_ErrorLoadingModel=Error loading model for file "{0}"
 JSFUtils_MissingJAR= Missing JSF Library Jar: {0} in {1}
+Could_Not_GetJSFVersion=Could not get valid JSF version from facet {0}
 
 J2EEModuleDependencyDelegate_UpdatingJ2EEModuleDependencies=Updating J2EE Module Dependencies
 J2EEModuleDependencyDelegate_UpdatingJ2EEModuleDependenciesForProject=Updating J2EE Module Dependencies for project "{0}"
@@ -90,3 +91,4 @@
 
 JSFFacet11_presetLabel = JavaServer Faces v1.1 Project
 JSFFacet11_presetDescription = Configures a Dynamic Web application to use JSF v1.1
+
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFFacetInstallDelegate.java b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFFacetInstallDelegate.java
index 5ed0306..b23a0e6 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFFacetInstallDelegate.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFFacetInstallDelegate.java
@@ -14,9 +14,6 @@
 
 package org.eclipse.jst.jsf.core.internal.project.facet;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IWorkspaceRunnable;
@@ -28,14 +25,11 @@
 import org.eclipse.jst.common.project.facet.core.libprov.LibraryInstallDelegate;
 import org.eclipse.jst.common.project.facet.core.libprov.LibraryProviderOperationConfig;
 import org.eclipse.jst.common.project.facet.core.libprov.user.UserLibraryProviderInstallOperationConfig;
-import org.eclipse.jst.j2ee.internal.J2EEVersionConstants;
 import org.eclipse.jst.j2ee.model.IModelProvider;
 import org.eclipse.jst.j2ee.model.ModelProviderManager;
-import org.eclipse.jst.javaee.web.Servlet;
 import org.eclipse.jst.javaee.web.WebApp;
 import org.eclipse.jst.jsf.common.facet.libraryprovider.jsf.JsfLibraryUtil;
 import org.eclipse.jst.jsf.common.webxml.WebXmlUpdater;
-import org.eclipse.jst.jsf.core.IJSFCoreConstants;
 import org.eclipse.jst.jsf.core.internal.JSFCorePlugin;
 import org.eclipse.jst.jsf.core.internal.Messages;
 import org.eclipse.osgi.util.NLS;
@@ -83,18 +77,36 @@
 								Messages.JSFFacetInstallDelegate_InternalErr);
 			}
 
-			if (jsfFacetConfigurationEnabled)
-			{
-    			//Before we do any configuration, verify that web.xml is available for update
-    			final IModelProvider provider = JSFUtils.getModelProvider(project);
-    			if (provider == null ) {				
-    				throw new JSFFacetException( NLS.bind(Messages.JSFFacetInstallDelegate_ConfigErr, project.getName())); 
-    			} else if (!(provider.validateEdit(null, null).isOK())){				
-    				if (!(provider.validateEdit(null, null).isOK())) {//checks for web.xml file being read-only and allows user to set writeable		
-    					throw new JSFFacetException(NLS.bind(Messages.JSFFacetInstallDelegate_NonUpdateableWebXML,  project.getName()));
-    				}
-    			}
-			}
+            final JSFUtils jsfUtil = new JSFUtilFactory().create(fv, ModelProviderManager.getModelProvider(project));
+            if (jsfUtil == null)
+            {
+                throw new JSFFacetException(NLS.bind(
+                        Messages.Could_Not_GetJSFVersion, fv.toString()));
+            }
+
+            if (jsfFacetConfigurationEnabled)
+            {
+                // Before we do any configuration, verify that web.xml is                    // available for update
+                final IModelProvider provider = jsfUtil
+                        .getModelProvider();
+                if (provider == null)
+                {
+                    throw new JSFFacetException(NLS.bind(
+                            Messages.JSFFacetInstallDelegate_ConfigErr,
+                            project.getName()));
+                } 
+                else if (!(provider.validateEdit(null, null).isOK()))
+                {
+                    if (!(provider.validateEdit(null, null).isOK()))
+                    {// checks for web.xml file being read-only and allows
+                     // user to set writeable
+                        throw new JSFFacetException(
+                                NLS.bind(
+                                        Messages.JSFFacetInstallDelegate_NonUpdateableWebXML,
+                                        project.getName()));
+                    }
+                }
+            }
 			
 //			// Create JSF Libs as classpath containers and set WTP dependencies
 //			// as required
@@ -109,10 +121,10 @@
 			if (jsfFacetConfigurationEnabled)
             {
     			// Create config file
-    			createConfigFile(project, fv, config, monitor);
+    			createConfigFile(project, fv, config, monitor, jsfUtil);
 
     			// Update web model
-    			createServletAndModifyWebXML(project, config, monitor);
+    			createServletAndModifyWebXML(project, config, monitor, jsfUtil);
                 updateWebXmlByJsfVendor(libConfig, project, monitor);
             }
             
@@ -272,21 +284,6 @@
 //	}		
 
 
-    /**
-	 * @param config
-	 * @return list of URL patterns from the datamodel
-	 */
-	private List getServletMappings(final IDataModel config) {
-		final List mappings = new ArrayList();
-		final String[] patterns = (String[])config.getProperty(IJSFFacetInstallDataModelProperties.SERVLET_URL_PATTERNS);
-		for (final String pattern : patterns)
-        {
-			mappings.add(pattern);
-		}
-
-		return mappings;
-	}
-
 	/**
 	 * @param project
 	 * @param jsfConfigPath
@@ -308,7 +305,7 @@
 	 */
 	private void createConfigFile(final IProject project,
 			final IProjectFacetVersion fv, final IDataModel config,
-			final IProgressMonitor monitor) {
+			final IProgressMonitor monitor, final JSFUtils jsfUtil) {
 
 
 		final IPath configPath = resolveConfigPath(project, config.getStringProperty(IJSFFacetInstallDataModelProperties.CONFIG_PATH));
@@ -316,24 +313,10 @@
 			// do not overwrite if the file exists
 			if (!configPath.toFile().exists()) {
 				final IWorkspaceRunnable op = new IWorkspaceRunnable(){
-					public void run(final IProgressMonitor monitor_inner) throws CoreException{ 
-						if (shouldUseJ2EEConfig(fv)){
-							JSFUtils11.createConfigFile(fv.getVersionString(),
-									configPath);
-						} else {
-							JSFUtils12.createConfigFile(fv.getVersionString(),
-									configPath);
-						}
+					public void run(final IProgressMonitor monitor_inner) throws CoreException{
+						    jsfUtil.createConfigFile(configPath);
 						project.refreshLocal(IResource.DEPTH_INFINITE, monitor_inner);
 					}
-
-					private boolean shouldUseJ2EEConfig(final IProjectFacetVersion facetVersion) {
-						if (IJSFCoreConstants.FACET_VERSION_1_1.equals(facetVersion.getVersionString()))
-						{
-							return true;
-						}
-						return false;
-					}
 				};
 				op.run(monitor);
 			}
@@ -342,29 +325,34 @@
 		}
 
 	}
-	
-	/**
-	 * Create servlet and URL mappings and update the webapp
-	 * @param project
-	 * @param config
-	 * @param monitor
-	 */
-	private void createServletAndModifyWebXML(final IProject project,
-			final IDataModel config, final IProgressMonitor monitor) {
-		
-		final IModelProvider provider = JSFUtils.getModelProvider(project);
-		final IPath webXMLPath = new Path("WEB-INF").append("web.xml"); //$NON-NLS-1$ //$NON-NLS-2$
-		if (JSFUtils12.isWebApp25(provider.getModelObject())) {			
-			provider.modify(new UpdateWebXMLForJavaEE(project, config), doesDDFileExist(project, webXMLPath) ? webXMLPath : IModelProvider.FORCESAVE); 
-		}
-		else {//must be 2.3 or 2.4			
-			provider.modify(new UpdateWebXMLForJ2EE(project, config), webXMLPath);
-		}
 
-		
-		// Check if runtime is MyFaces or Sun-RI
-		
-	}
+    /**
+     * Create servlet and URL mappings and update the webapp
+     * 
+     * @param project
+     * @param config
+     * @param monitor
+     */
+    private void createServletAndModifyWebXML(final IProject project,
+            final IDataModel config, final IProgressMonitor monitor,
+            final JSFUtils jsfUtil)
+    {
+
+        final IModelProvider provider = jsfUtil.getModelProvider();
+        final IPath webXMLPath = new Path("WEB-INF").append("web.xml"); //$NON-NLS-1$ //$NON-NLS-2$
+        if (jsfUtil.isJavaEE(provider.getModelObject()))
+        {
+            provider.modify(new UpdateWebXMLForJavaEE(project, config, jsfUtil),
+                    doesDDFileExist(project, webXMLPath) ? webXMLPath
+                            : IModelProvider.FORCESAVE);
+        } else
+        {// must be 2.3 or 2.4
+            provider.modify(new UpdateWebXMLForJ2EE(project, config, jsfUtil),
+                    webXMLPath);
+        }
+        // TODO: is the MyFaces check a todo?
+        // Check if runtime is MyFaces or Sun-RI
+    }
 
 	private boolean doesDDFileExist(final IProject project, final IPath webXMLPath) {
 		return project.getProjectRelativePath().append(webXMLPath).toFile().exists();		
@@ -373,74 +361,36 @@
 	private class UpdateWebXMLForJavaEE implements Runnable {
 		private final IProject project;
 		private final IDataModel config;
+        private final JSFUtils jsfUtil;
 		
-		UpdateWebXMLForJavaEE(final IProject project, final IDataModel config){
+		UpdateWebXMLForJavaEE(final IProject project, final IDataModel config, final JSFUtils jsfUtil){
 			this.project = project;
 			this.config = config;
+			this.jsfUtil = jsfUtil;
 		}
 		
 		public void run() {
 			final WebApp webApp = (WebApp) ModelProviderManager.getModelProvider(project).getModelObject();
-			// create or update servlet ref
-			Servlet servlet = JSFUtils12.findJSFServlet(webApp);// check to see
-																// if already
-// No longer removing any old mappings on install - see 194919 															// present
-//			if (servlet != null) {
-//				// remove old mappings
-//				JSFUtils12.removeURLMappings(webApp, servlet);
-//			}
-			
-			servlet = JSFUtils12
-					.createOrUpdateServletRef(webApp, config, servlet);
-	
-			// init mappings
-			final List listOfMappings = getServletMappings(config);
-			JSFUtils12.setUpURLMappings(webApp, listOfMappings, servlet);
-	
-			// setup context params
-			JSFUtils12.setupConfigFileContextParamForV2_5(webApp, config);
+			jsfUtil.updateWebApp(webApp, config);
 		}
 	}
 	
 	private class UpdateWebXMLForJ2EE implements Runnable {		
 		private final IProject project;
 		private final IDataModel config;
+        private final JSFUtils jsfUtil;
 		
-		UpdateWebXMLForJ2EE(final IProject project, final IDataModel config){
+		UpdateWebXMLForJ2EE(final IProject project, final IDataModel config, final JSFUtils jsfUtil){
 			this.project = project ;
 			this.config = config;
+			this.jsfUtil = jsfUtil;
 		}
 		
 		public void run() {
 			final org.eclipse.jst.j2ee.webapplication.WebApp webApp = (org.eclipse.jst.j2ee.webapplication.WebApp)ModelProviderManager.getModelProvider(project).getModelObject();
-			// create or update servlet ref
-			org.eclipse.jst.j2ee.webapplication.Servlet servlet = JSFUtils11.findJSFServlet(webApp);// check to see
-																// if already
-																// present
-			
-// No longer removing any old mappings on install - see 194919 
-//			if (servlet != null) {
-//				// remove old mappings
-//				JSFUtils11.removeURLMappings(webApp, servlet);
-//			}
-			
-			servlet = JSFUtils11
-					.createOrUpdateServletRef(webApp, config, servlet);
-	
-			// init mappings
-			final List listOfMappings = getServletMappings(config);
-			JSFUtils11.setUpURLMappings(webApp, listOfMappings, servlet);
-	
-			// setup context params
-			setupContextParams(webApp, config);
+			jsfUtil.updateWebApp(webApp, config);
 		}
 		
-		private void setupContextParams(final org.eclipse.jst.j2ee.webapplication.WebApp webApp, final IDataModel config) {
-			if (webApp.getVersionID() == J2EEVersionConstants.WEB_2_3_ID)//shouldn't have to do it this way, but that's the way it goes 119442
-				JSFUtils11.setupConfigFileContextParamForV2_3(webApp, config);
-			else 
-				JSFUtils11.setupConfigFileContextParamForV2_4(webApp, config);
-		}
 	}
 
 
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFFacetUninstallDelegate.java b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFFacetUninstallDelegate.java
index e5ebacd..29406fb 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFFacetUninstallDelegate.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFFacetUninstallDelegate.java
@@ -12,8 +12,6 @@
  *******************************************************************************/ 
 package org.eclipse.jst.jsf.core.internal.project.facet;
 
-import java.util.Iterator;
-
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
@@ -21,8 +19,6 @@
 import org.eclipse.core.runtime.Path;
 import org.eclipse.jst.j2ee.model.IModelProvider;
 import org.eclipse.jst.j2ee.model.ModelProviderManager;
-import org.eclipse.jst.javaee.core.ParamValue;
-import org.eclipse.jst.javaee.web.Servlet;
 import org.eclipse.jst.javaee.web.WebApp;
 import org.eclipse.jst.jsf.core.internal.Messages;
 import org.eclipse.osgi.util.NLS;
@@ -52,11 +48,19 @@
 				monitor.beginTask("", 1); //$NON-NLS-1$
 			}
 
-			try {
+			try 
+			{
+	            final JSFUtils jsfUtil = new JSFUtilFactory().create(fv, ModelProviderManager.getModelProvider(project));
+	            if (jsfUtil == null)
+	            {
+	                throw new JSFFacetException(NLS.bind(
+	                        Messages.Could_Not_GetJSFVersion, fv.toString()));
+	            }
+
 			    if (jsfFacetConfigurationEnabled)
 			    {
     				//Before we do any de-configuration, verify that web.xml is available for update
-    				IModelProvider provider = JSFUtils.getModelProvider(project);
+    				IModelProvider provider = jsfUtil.getModelProvider();
     				if (provider == null ) {				
     					throw new JSFFacetException(NLS.bind(Messages.JSFFacetUninstallDelegate_ConfigErr, project.getName())); 
     				} else if (!(provider.validateEdit(null, null).isOK())){					
@@ -70,7 +74,7 @@
                 if (jsfFacetConfigurationEnabled)
                 {
     				// remove servlet stuff from web.xml
-    				uninstallJSFReferencesFromWebApp(project, monitor);
+    				uninstallJSFReferencesFromWebApp(project, monitor, jsfUtil);
                 }
 				if (monitor != null) {
 					monitor.worked(1);
@@ -85,28 +89,23 @@
 	}
 	
 	private void uninstallJSFReferencesFromWebApp(final IProject project,
-			final IProgressMonitor monitor) {
+			final IProgressMonitor monitor, final JSFUtils jsfUtil) {
 		
-		IModelProvider provider = JSFUtils.getModelProvider(project);
+		IModelProvider provider = jsfUtil.getModelProvider();
 		Object webAppObj = provider.getModelObject();
-		if (webAppObj != null) {
-			IPath ddPath = new Path("WEB-INF").append("web.xml"); //$NON-NLS-1$ //$NON-NLS-2$
-			if (isJavaEEWebApp(webAppObj)){		
-				WebApp webApp = (WebApp)webAppObj;
-				Servlet servlet = JSFUtils12.findJSFServlet(webApp);
-				if (servlet == null)
-					return;
-
-				provider.modify(new RemoveJSFFromJavaEEWebAppOperation(project), ddPath);
-			} else {//2.3 or 2.4 web app
-				org.eclipse.jst.j2ee.webapplication.WebApp webApp = (org.eclipse.jst.j2ee.webapplication.WebApp)webAppObj;
-				org.eclipse.jst.j2ee.webapplication.Servlet servlet = JSFUtils11.findJSFServlet(webApp);
-				if (servlet == null)
-					return;
-
-				provider.modify(new RemoveJSFFromJ2EEWebAppOperation(project), ddPath);			
-			}
-		}
+        if (webAppObj != null)
+        {
+            IPath ddPath = new Path("WEB-INF").append("web.xml"); //$NON-NLS-1$ //$NON-NLS-2$
+            if (isJavaEEWebApp(webAppObj))
+            {
+                provider.modify(new RemoveJSFFromJavaEEWebAppOperation(project,
+                        jsfUtil), ddPath);
+            } else
+            {// 2.3 or 2.4 web app
+                provider.modify(new RemoveJSFFromJ2EEWebAppOperation(project,
+                        jsfUtil), ddPath);
+            }
+        }
 	}
 
 	private boolean isJavaEEWebApp(final Object webAppObj) {
@@ -119,74 +118,35 @@
 
 	static class RemoveJSFFromJavaEEWebAppOperation implements Runnable {
 		private IProject _project;
+        private JSFUtils _jsfUtil;
 		
-		RemoveJSFFromJavaEEWebAppOperation(final IProject project){
-			this._project = project;			
+		RemoveJSFFromJavaEEWebAppOperation(final IProject project, JSFUtils jsfUtil){
+			this._project = project;
+			this._jsfUtil = jsfUtil;
 		}
 		
-		public void run() {
-			WebApp webApp = (WebApp) ModelProviderManager.getModelProvider(_project).getModelObject();
-			Servlet servlet = JSFUtils12.findJSFServlet(webApp);
-			
-			// remove faces url mappings
-			JSFUtils12.removeURLMappings(webApp, servlet);
-			// remove context params
-			removeJSFContextParams(webApp, servlet);
-			// remove servlet
-			removeJSFServlet(webApp, servlet);
-			
-		}
-		private void removeJSFContextParams(final WebApp webApp, final Servlet servlet) {
-			Iterator it = webApp.getContextParams().iterator();
-			while (it.hasNext()) {
-				ParamValue cp = (ParamValue) it.next();
-				if (cp.getParamName().equals(JSFUtils.JSF_CONFIG_CONTEXT_PARAM)) {
-					webApp.getContextParams().remove(cp);
-					break;
-				}
-			}
-		}
-
-		private void removeJSFServlet(final WebApp webApp, final Servlet servlet) {		
-			webApp.getServlets().remove(servlet);
-		}
+        public void run()
+        {
+            WebApp webApp = (WebApp) ModelProviderManager.getModelProvider(
+                    _project).getModelObject();
+            _jsfUtil.rollbackWebApp(webApp);
+        }
 		
 	}
 	
 	static class RemoveJSFFromJ2EEWebAppOperation implements Runnable {
-		private IProject _project;		
+		private IProject _project;
+        private JSFUtils _jsfUtil;		
 		
-		RemoveJSFFromJ2EEWebAppOperation(final IProject project){
+		RemoveJSFFromJ2EEWebAppOperation(final IProject project, JSFUtils jsfUtil){
 			this._project = project;
+			this._jsfUtil = jsfUtil;
 		}
 		
 		public void run() {
 			org.eclipse.jst.j2ee.webapplication.WebApp webApp = (org.eclipse.jst.j2ee.webapplication.WebApp) ModelProviderManager.getModelProvider(_project).getModelObject();
-			org.eclipse.jst.j2ee.webapplication.Servlet servlet = JSFUtils11.findJSFServlet(webApp);
-
-			// remove faces url mappings
-			JSFUtils11.removeURLMappings(webApp, servlet);
-			// remove context params
-			removeJSFContextParams(webApp, servlet);
-			// remove servlet
-			removeJSFServlet(webApp, servlet);
-			
+			_jsfUtil.rollbackWebApp(webApp);
 		}
-		private void removeJSFContextParams(final org.eclipse.jst.j2ee.webapplication.WebApp webApp, final org.eclipse.jst.j2ee.webapplication.Servlet servlet) {
-			Iterator it = webApp.getContextParams().iterator();
-			while (it.hasNext()) {
-				org.eclipse.jst.j2ee.common.ParamValue cp = (org.eclipse.jst.j2ee.common.ParamValue) it.next();
-				if (cp.getName().equals(JSFUtils.JSF_CONFIG_CONTEXT_PARAM)) {
-					webApp.getContextParams().remove(cp);
-					break;
-				}
-			}
-		}
-
-		private void removeJSFServlet(final org.eclipse.jst.j2ee.webapplication.WebApp webApp, final org.eclipse.jst.j2ee.webapplication.Servlet servlet) {
-			webApp.getServlets().remove(servlet);
-		}
-		
 	}
 
 }
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFUtilFactory.java b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFUtilFactory.java
new file mode 100644
index 0000000..7e9bcd2
--- /dev/null
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFUtilFactory.java
@@ -0,0 +1,68 @@
+package org.eclipse.jst.jsf.core.internal.project.facet;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jst.j2ee.model.IModelProvider;
+import org.eclipse.jst.j2ee.model.ModelProviderManager;
+import org.eclipse.jst.jsf.core.JSFVersion;
+import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
+
+/**
+ * Creates a new JSFUtil for a particular JSF project version.
+ * 
+ * @author cbateman
+ *
+ */
+public class JSFUtilFactory
+{
+    /**
+     * @param project
+     * @return the jsf version of the project if it is valid JSF faceted
+     * project or null otherwise.
+     */
+    public JSFUtils create(final IProject project)
+    {
+        final JSFVersion jsfVersion = JSFVersion.valueOfProject(project);
+        if (jsfVersion != null)
+        {
+            return create(jsfVersion, ModelProviderManager.getModelProvider(project));
+        }
+        return null;
+    }
+    /**
+     * @param version
+     * @param modelProvider 
+     * @return the JSF utils object for the version or null if none.
+     * @throw {@link IllegalArgumentException} if version is not related
+     * to a JSF facet.
+     */
+    public JSFUtils create(final IProjectFacetVersion version, final IModelProvider modelProvider)
+    {
+        final JSFVersion jsfVersion = JSFVersion.valueOfFacetVersion(version);
+        if (jsfVersion != null)
+        {
+            return create(jsfVersion, modelProvider);
+        }
+        return null;
+    }
+
+    /**
+     * @param version
+     * @param modelProvider 
+     * @return the JSF utils object for the version or null if none.
+     */
+    public JSFUtils create(final JSFVersion version, final IModelProvider modelProvider)
+    {
+        switch (version)
+        {
+        case V1_0:
+        case V1_1:
+            return new JSFUtils11(modelProvider);
+        case V1_2:
+            return new JSFUtils12(modelProvider);
+        case V2_0:
+            return new JSFUtils20(modelProvider);
+        default:
+            throw new IllegalArgumentException("Unknown version: "+version); //$NON-NLS-1$
+        }
+    }
+}
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFUtils.java b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFUtils.java
index cc616d1..97c74a2 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFUtils.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFUtils.java
@@ -11,16 +11,24 @@
 
 package org.eclipse.jst.jsf.core.internal.project.facet;
 
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
-import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.emf.common.util.EList;
 import org.eclipse.jst.j2ee.model.IModelProvider;
-import org.eclipse.jst.j2ee.model.ModelProviderManager;
+import org.eclipse.jst.javaee.web.WebAppVersionType;
+import org.eclipse.jst.jsf.core.JSFVersion;
 import org.eclipse.jst.jsf.core.internal.JSFCorePlugin;
 import org.eclipse.jst.jsf.core.internal.Messages;
 import org.eclipse.jst.jsf.core.internal.jsflibraryregistry.ArchiveFile;
@@ -34,7 +42,7 @@
  */
 @SuppressWarnings("deprecation")
 public abstract class JSFUtils {
-	/**
+    /**
 	 * The default name for the Faces servlet
 	 */
 	public static final String JSF_DEFAULT_SERVLET_NAME = "Faces Servlet"; //$NON-NLS-1$
@@ -64,97 +72,47 @@
 
 	/**
 	 * the key for implementation libraries in persistent properties
-     * TODO: should encapsulate the property somewhere and hide the constant
 	 */
 	public static final String PP_JSF_IMPLEMENTATION_LIBRARIES = "jsf.implementation.libraries"; //$NON-NLS-1$
 	/**
 	 * the key for component libraries in persistent properties
-     * TODO: should encapsulate the property somewhere and hide the constant
 	 */
 	public static final String PP_JSF_COMPONENT_LIBRARIES = "jsf.component.libraries"; //$NON-NLS-1$
 	/**
 	 * the key for implementation type in persistent properties
-     * TODO: should encapsulate the property somewhere and hide the constant
 	 */
 	public static final String PP_JSF_IMPLEMENTATION_TYPE = "jsf.implementation.type"; //$NON-NLS-1$
+
+	private static final String DEFAULT_DEFAULT_MAPPING_SUFFIX = "jsp"; //$NON-NLS-1$
+	
+	private final JSFVersion  _version;
+    private final IModelProvider _modelProvider;
+	
 	/**
-	 * Construct an array that hold paths for all JARs in a JSF library. 
-	 * However, archive files that no longer exist are filtered out.  
-	 * 
-	 * @param jsfLib
-	 * @param logMissingJar true to log an error for each invalid JAR.
-	 * @return elements
+	 * @param version
+	 * @param modelProvider 
 	 */
-	public static IPath[] getJARPathforJSFLibwFilterMissingJars(JSFLibrary jsfLib, boolean logMissingJar) {
-		EList archiveFiles = jsfLib.getArchiveFiles();
-		int numJars = numberofValidJar(archiveFiles);
-		IPath[] elements = new IPath[numJars];
-		ArchiveFile ar = null;
-		int idxValidJar = 0;
-		for (int i= 0; i < archiveFiles.size(); i++) {
-			ar = (ArchiveFile)archiveFiles.get(i); 
-			if ( !ar.exists() ) {
-				if (logMissingJar) {
-					logErroronMissingJAR(jsfLib, ar);
-				}
-			} else {
-				elements[idxValidJar] = new Path(((ArchiveFile)archiveFiles.get(i)).getResolvedSourceLocation()).makeAbsolute();
-				idxValidJar++;
-			}
-		}
-		return elements;		
+	protected JSFUtils(final JSFVersion version, final IModelProvider modelProvider)
+	{
+	    _version = version;
+	    _modelProvider = modelProvider;
 	}
 	
 	/**
-	 * Construct an array that hold paths for all JARs in a JSF library. 
-	 * 
-	 * @param jsfLib
-	 * @param logMissingJar true to log an error for each invalid JAR.
-	 * @return elements
+	 * @return the jsf version that this instance is for.
 	 */
-	public static IPath[] getJARPathforJSFLib(JSFLibrary jsfLib, boolean logMissingJar) {		
-		EList archiveFiles = jsfLib.getArchiveFiles();
-		int numJars = archiveFiles.size();
-		IPath[] elements = new IPath[numJars];
-		ArchiveFile ar = null;
-		for (int i= 0; i < numJars; i++) {
-			ar = (ArchiveFile)archiveFiles.get(i); 
-			if ( !ar.exists() && logMissingJar ) {
-				logErroronMissingJAR(jsfLib, ar);
-			}
-			elements[i] = new Path(((ArchiveFile)archiveFiles.get(i)).getResolvedSourceLocation()).makeAbsolute();
-		}
-		return elements;
-	}	
-	
-	private static int numberofValidJar(EList archiveFiles) {
-		int total = 0;
-		final Iterator it = archiveFiles.iterator();
-		ArchiveFile ar = null;
-		while(it.hasNext()) {
-			ar = (ArchiveFile) it.next();
-			if (ar.exists()) {
-				total++;
-			}
-		}
-		return total;
-	}
-	
-	private static void logErroronMissingJAR(JSFLibrary jsfLib, ArchiveFile ar) {
-		String msg = NLS.bind(Messages.JSFUtils_MissingJAR, 
-						ar.getName(),
-						jsfLib.getLabel());
-		JSFCorePlugin.log(IStatus.ERROR, msg);
-	}
-	
+	public final JSFVersion getVersion()
+    {
+        return _version;
+    }
 
 	/**
 	 * @param config
 	 * @return servlet display name to use from wizard data model
 	 */
-	protected static String getDisplayName(IDataModel config) {
+	protected final String getDisplayName(IDataModel config) {
 		String displayName = config.getStringProperty(IJSFFacetInstallDataModelProperties.SERVLET_NAME);
-		if (displayName == null || displayName.trim().equals("")) //$NON-NLS-1$
+		if (displayName == null || displayName.trim().length() == 0)
 			displayName = JSF_DEFAULT_SERVLET_NAME;
 		return displayName.trim();
 	}
@@ -163,166 +121,276 @@
 	 * @param config
 	 * @return servlet display name to use from wizard data model
 	 */
-	protected static String getServletClassname(IDataModel config) {
+	protected final String getServletClassname(IDataModel config) {
 		String className = config.getStringProperty(IJSFFacetInstallDataModelProperties.SERVLET_CLASSNAME);
 		if (className == null || className.trim().equals("")) //$NON-NLS-1$
 			className = JSF_SERVLET_CLASS;
 		return className.trim();
 	}
-	
-	/**
-	 * Servlet 2.3_SRV.11.2: a string that begins with a "/" and ends
-	 * with "/*" is a prefix mapping
-	 * 
-	 * @param mapping
-	 * @return true if the mapping string represents a prefix mapping
-	 */
-	public static boolean isPrefixMapping(final String mapping)
-	{
-	    if (mapping == null || mapping.length() < 4)
-	    {
-	        return false;
-	    }
-	    
-	    return mapping.charAt(0) == '/' && mapping.endsWith("/*"); //$NON-NLS-1$
-	}
-	
-	/**
-	 * Servlet 2.3_SRV.11.2: a string that begins with "*." 
-	 * is an extension mapping
-     * 
-	 * @param mapping
-	 * @return true if mapping is an extension mapping
-	 */
-	public static boolean isExtensionMapping(final String mapping)
-	{
-	    if (mapping == null)
-	    {
-	        return false;
-	    }
-	    
-	    return mapping.startsWith("*."); //$NON-NLS-1$
-	}	
 
 	/**
-	 * @param webProject
 	 * @return IModelProvider
 	 */
-	public static IModelProvider getModelProvider(IProject webProject) {
-		IModelProvider provider = ModelProviderManager.getModelProvider(webProject); 
-		Object webAppObj = provider.getModelObject();
-		if (webAppObj == null){			
+	public final IModelProvider getModelProvider() {
+		Object webAppObj = _modelProvider.getModelObject();
+		if (webAppObj == null)
+		{
 			return null;
-		}			
-		return provider;
+		}
+		return _modelProvider;
 	}
-	
-	/**
-	 * Search the list of servlet-mappings for the first extension and prefix mappings.  The contents
-	 * of mappings is assumed to be all url-pattern's.  
-	 * 
-	 * If prefExtMapping is not null, it is an extension mapping and
-     * it is in mappings, then it is returned.  Otherwise, the first extension
-     * mapping in mappings is returned.  Returns null if mappings does not
-     * contain an extension mapping.  The same algorithm holds for prefPrefixMapping and
-     * corresponding prefix mapping.
-     * 
-     * See isExtensionMapping and isPrefixMapping for more information on url patterns.
-	 * 
-	 * @param mappings
-	 * @param prefExtMapping
-	 * @param prefPrefixMapping
-	 * @return the result
-	 */
-	public static MappingSearchResult searchServletMappings(
-			final List<String> mappings, String prefExtMapping,
-			String prefPrefixMapping) {
-		String firstExtFound = null;
-		String firstPrefixFound = null;
-		boolean foundExtMapping = false;
-		boolean foundPrefixMapping = false;
 
-		// if the caller has no preferredMapping, then
-		// set it to something guaranteed to be non-null
-		// and which is guaranteed not to match anything
-		// that pass isExtensionMapping
-		if (prefExtMapping == null) {
-			prefExtMapping = "NOTANEXTENSIONMAPPING"; //$NON-NLS-1$
-		}
-
-		// similarly, guarantee that if the caller has no
-		// preferred prefix mapping, that we set a non-null
-		// comp mapping
-		if (prefPrefixMapping == null) {
-			prefPrefixMapping = "NOTAPREFIXMAPPING"; //$NON-NLS-1$
-		}
-
-		SEARCH_LOOP: for (String mapping : mappings) {
-			if (isExtensionMapping(mapping)) {
-				// can assum that mapping is non-null since
-				// it is an ext mapping
-				if (prefExtMapping.equals(mapping.trim())) {
-					firstExtFound = prefExtMapping;
-					continue;
-				}
-
-				if (firstExtFound == null) {
-					firstExtFound = mapping.trim();
-				}
-			} else if (isPrefixMapping(mapping)) {
-				if (prefPrefixMapping.equals(mapping.trim())) {
-					firstPrefixFound = prefPrefixMapping;
-					continue;
-				}
-
-				if (firstPrefixFound == null) {
-					firstPrefixFound = mapping.trim();
-				}
-			}
-
-			if (foundExtMapping && foundPrefixMapping) {
-				break SEARCH_LOOP;
-			}
-		}
-
-		return new MappingSearchResult(firstExtFound, firstPrefixFound);
-	}
-	
+   /**
+     * @param configPath
+     */
+    public final void createConfigFile(IPath configPath)
+    {
+        FileOutputStream os = null;
+//        final String QUOTE = new String(new char[] { '"' });
+        try {
+            IPath dirPath = configPath.removeLastSegments(1);
+            dirPath.toFile().mkdirs();
+            File file = configPath.toFile();
+            file.createNewFile();
+            os = new FileOutputStream(file);
+            printConfigFile(os);
+        } catch (FileNotFoundException e) {
+            JSFCorePlugin.log(IStatus.ERROR, Messages.JSFUtils_ErrorCreatingConfigFile, e);
+        } catch (IOException e) {
+            JSFCorePlugin.log(IStatus.ERROR, Messages.JSFUtils_ErrorCreatingConfigFile, e);
+        } finally {
+            if (os != null) {
+                try {
+                    os.close();
+                } catch (IOException e) {
+                    JSFCorePlugin.log(IStatus.ERROR, Messages.JSFUtils_ErrorClosingConfigFile, e);
+                }
+            }
+        }
+    }
+    
     /**
-	 * The result of a servlet mapping search
-	 * 
-	 */
-	public static class MappingSearchResult {
-		private final String _extensionMapping; // may be null;
-		private final String _prefixMapping; // may be null
+     * @param out
+     */
+    protected final void printConfigFile(final OutputStream out)
+    {
+        PrintWriter pw = null;
+        try
+        {
+            pw = new PrintWriter(out);
+            doVersionSpecificConfigFile(pw);
+        }
+        finally
+        {
+            if (pw != null)
+            {
+                pw.close();
+            }
+        }
+    }
+    
+    /**
+     * @param pw
+     */
+    protected abstract void doVersionSpecificConfigFile(final PrintWriter pw);
+    
+    
+    /**
+     * @param webAppObj 
+     * @return true if this going into a JavaEE (1.5 and later) or a J2EE (1.4 and earlier)
+     * configured application.
+     */
+    public boolean isJavaEE(final Object webAppObj)
+    {
+      if (webAppObj instanceof org.eclipse.jst.javaee.web.WebApp)
+      {
+          org.eclipse.jst.javaee.web.WebApp webApp = (org.eclipse.jst.javaee.web.WebApp)webAppObj;
+          return WebAppVersionType.VALUES.contains(webApp.getVersion());
+      }
+      return false;
+    }
 
-		MappingSearchResult(final String extensionMapping,
-				final String prefixMapping) {
-			_extensionMapping = extensionMapping;
-			_prefixMapping = prefixMapping;
-		}
+    /**
+     * @param config
+     * @return list of URL patterns from the datamodel
+     */
+    protected final List<String> getServletMappings(final IDataModel config) {
+        final List<String> mappings = new ArrayList<String>();
+        final String[] patterns = (String[])config.getProperty(IJSFFacetInstallDataModelProperties.SERVLET_URL_PATTERNS);
+        if (patterns != null)
+        {
+            for (final String pattern : patterns)
+            {
+                mappings.add(pattern);
+            }
+        }
+        return mappings;
+    }
+    /**
+     * Does an update of the web application's config file.
+     * 
+     * @param webApp must be WebApp of the appropriate type.
+     * @param config
+     * @throws ClassCastException if webApp is not the appropriate type.
+     */
+    public abstract void updateWebApp(Object webApp, IDataModel config);
 
-		/**
-		 * @return true if the search yielded a valid result
-		 */
-		public boolean isResult() {
-			return _extensionMapping != null || _prefixMapping != null;
-		}
 
-		/**
-		 * @return the first extension mapping matching search criteria or null
-		 * if none
-		 */
-		public final String getExtensionMapping() {
-			return _extensionMapping;
-		}
+    /**
+     * Called on a facet uninstall to remove JSF related changes.
+     * @param webApp
+     */
+    public abstract void rollbackWebApp(Object webApp);
 
-		/**
-		 * @return the first prefix mapping matching search criteria or null
-		 * if none
-		 */
-		public final String getPrefixMapping() {
-			return _prefixMapping;
-		}
+
+    /**
+     * @param webAppObj
+     * @param resource
+     * @param existingURL
+     * @return the modified url path for the (possibly) jsf resource.
+     */
+    public abstract IPath getFileUrlPath(Object webAppObj, IResource resource,
+            IPath existingURL);
+    
+    /**
+     * @param fileExtension
+     * @return true if the file extension is deemed to be for a JSF.
+     */
+    protected boolean isValidKnownExtension(String fileExtension) {
+        if (fileExtension != null &&
+                (   fileExtension.equalsIgnoreCase(DEFAULT_DEFAULT_MAPPING_SUFFIX) ||  
+                fileExtension.equalsIgnoreCase("jspx") ||  //$NON-NLS-1$
+                fileExtension.equalsIgnoreCase("jsf") || //$NON-NLS-1$
+                fileExtension.equalsIgnoreCase("xhtml"))) //$NON-NLS-1$
+            return true;
+
+        return false;
+    }
+
+    
+    /**
+     * @param resource
+     * @return true if the resource is deemed to be a JSF page.
+     */
+    protected boolean isJSFPage(IResource resource) {
+        // currently always return true.
+        // need to find quick way of determining whether this is a JSF JSP Page
+        return true;
+    }
+    
+    /**
+     * @return the default value for the default mapping suffix
+     */
+    protected String getDefaultDefaultSuffix()
+    {
+        return DEFAULT_DEFAULT_MAPPING_SUFFIX;
+    }
+
+    /**
+     * @param name 
+     * @param value 
+     * @return the 
+     */
+    protected final String calculateSuffix(final String name, final String value)
+    {
+        if (name != null
+                && JSF_DEFAULT_SUFFIX_CONTEXT_PARAM.equals(name
+                        .trim()))
+        {
+            return normalizeSuffix(value != null ? value.trim() : null);
+        }
+        return null;
+    }
+
+    /**
+     * @param defSuffix
+     * @return the suffix value with any leading dot removed
+     */
+    protected final String normalizeSuffix(String defSuffix)
+    {
+        if (defSuffix != null && defSuffix.startsWith(".")) //$NON-NLS-1$
+        {
+            defSuffix = defSuffix.substring(1);
+        }
+        return defSuffix;
+    }
+
+    /**
+     * Holds all the obsolete JSF Library stuff.  This will go away post-Helios.
+     * @author cbateman
+     *
+     */
+    public static class JSFLibraryHandler
+    {
+        /**
+         * Construct an array that hold paths for all JARs in a JSF library. 
+         * 
+         * @param jsfLib
+         * @param logMissingJar true to log an error for each invalid JAR.
+         * @return elements
+         */
+        public final IPath[] getJARPathforJSFLib(JSFLibrary jsfLib, boolean logMissingJar) {        
+            EList archiveFiles = jsfLib.getArchiveFiles();
+            int numJars = archiveFiles.size();
+            IPath[] elements = new IPath[numJars];
+            ArchiveFile ar = null;
+            for (int i= 0; i < numJars; i++) {
+                ar = (ArchiveFile)archiveFiles.get(i); 
+                if ( !ar.exists() && logMissingJar ) {
+                    logErroronMissingJAR(jsfLib, ar);
+                }
+                elements[i] = new Path(((ArchiveFile)archiveFiles.get(i)).getResolvedSourceLocation()).makeAbsolute();
+            }
+            return elements;
+        }   
+        
+        private int numberofValidJar(EList archiveFiles) {
+            int total = 0;
+            final Iterator it = archiveFiles.iterator();
+            ArchiveFile ar = null;
+            while(it.hasNext()) {
+                ar = (ArchiveFile) it.next();
+                if (ar.exists()) {
+                    total++;
+                }
+            }
+            return total;
+        }
+        
+        private void logErroronMissingJAR(JSFLibrary jsfLib, ArchiveFile ar) {
+            String msg = NLS.bind(Messages.JSFUtils_MissingJAR, 
+                            ar.getName(),
+                            jsfLib.getLabel());
+            JSFCorePlugin.log(IStatus.ERROR, msg);
+        }
+        
+        /**
+         * Construct an array that hold paths for all JARs in a JSF library. 
+         * However, archive files that no longer exist are filtered out.  
+         * 
+         * @param jsfLib
+         * @param logMissingJar true to log an error for each invalid JAR.
+         * @return elements
+         */
+        public final IPath[] getJARPathforJSFLibwFilterMissingJars(JSFLibrary jsfLib, boolean logMissingJar) {
+            EList archiveFiles = jsfLib.getArchiveFiles();
+            int numJars = numberofValidJar(archiveFiles);
+            IPath[] elements = new IPath[numJars];
+            ArchiveFile ar = null;
+            int idxValidJar = 0;
+            for (int i= 0; i < archiveFiles.size(); i++) {
+                ar = (ArchiveFile)archiveFiles.get(i); 
+                if ( !ar.exists() ) {
+                    if (logMissingJar) {
+                        logErroronMissingJAR(jsfLib, ar);
+                    }
+                } else {
+                    elements[idxValidJar] = new Path(((ArchiveFile)archiveFiles.get(i)).getResolvedSourceLocation()).makeAbsolute();
+                    idxValidJar++;
+                }
+            }
+            return elements;        
+        }
+
     }
 }
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFUtils11.java b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFUtils11.java
index 8fa212f..9de1ec8 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFUtils11.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFUtils11.java
@@ -11,32 +11,25 @@
 
 package org.eclipse.jst.jsf.core.internal.project.facet;
 
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
-import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.jst.j2ee.common.CommonFactory;
 import org.eclipse.jst.j2ee.common.ParamValue;
-import org.eclipse.jst.j2ee.web.componentcore.util.WebArtifactEdit;
+import org.eclipse.jst.j2ee.internal.J2EEVersionConstants;
+import org.eclipse.jst.j2ee.model.IModelProvider;
 import org.eclipse.jst.j2ee.webapplication.ContextParam;
-import org.eclipse.jst.j2ee.webapplication.JSPType;
 import org.eclipse.jst.j2ee.webapplication.Servlet;
 import org.eclipse.jst.j2ee.webapplication.ServletMapping;
 import org.eclipse.jst.j2ee.webapplication.ServletType;
 import org.eclipse.jst.j2ee.webapplication.WebApp;
 import org.eclipse.jst.j2ee.webapplication.WebapplicationFactory;
-import org.eclipse.jst.jsf.core.IJSFCoreConstants;
-import org.eclipse.jst.jsf.core.internal.JSFCorePlugin;
-import org.eclipse.jst.jsf.core.internal.Messages;
+import org.eclipse.jst.jsf.core.JSFVersion;
 import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
 
 /**
@@ -44,172 +37,137 @@
  * 
  * @author Gerry Kessler - Oracle
  */
-public class JSFUtils11 extends JSFUtils {	
+/*package use JSFUtilFactory*/ class JSFUtils11 extends JSFUtils {	
 	
 	/**
-	 * Convenience method for getting writeable WebApp model
-	 * @param project
-	 * @return WebArtifactEdit
-	 * @deprecated - must use IModelProviders
+	 * @param modelProvider 
 	 */
-	public static WebArtifactEdit getWebArtifactEditForWrite(final IProject project) {
-		return WebArtifactEdit.getWebArtifactEditForWrite(project);
-	}
+	protected JSFUtils11(final IModelProvider modelProvider)
+    {
+        super(JSFVersion.V1_1, modelProvider);
+    }
 
-	/**
-	 * Convenience method for getting read-only WebApp model
-	 * @param project
-	 * @return WebArtifactEdit
-	 * @deprecated - must use IModelProviders
-	 */
-	public static WebArtifactEdit getWebArtifactEditForRead(final IProject project) {
-		return WebArtifactEdit.getWebArtifactEditForRead(project);
-	}
+    /**
+     * @param webApp
+     *            as Object
+     * @return Servlet - the JSF Servlet for the specified WebApp or null if not
+     *         present
+     */
+    private Servlet findJSFServlet(final WebApp webApp)
+    {
+        if (webApp == null)
+        {
+            return null;
+        }
 
-	/**
-	 * @param webApp as Object
-	 * @return Servlet - the JSF Servlet for the specified WebApp or null if not present
-	 */
-	public static Servlet findJSFServlet(final Object webApp) {
-		Iterator it = null;
-		if (webApp == null)
-			return null;
-		else if (webApp instanceof WebApp)
-			it = ((WebApp)webApp).getServlets().iterator();
-		else if (webApp instanceof org.eclipse.jst.javaee.web.WebApp)
-			it = ((org.eclipse.jst.javaee.web.WebApp)webApp).getServlets().iterator();
-		else
-			return null;
-		
-		while (it.hasNext()) {
-            Servlet servlet = (Servlet) it.next();
-			if (servlet != null && servlet.getWebType() != null) {
-				
-				if(	servlet.getWebType().isServletType()) {
-					if (((ServletType) servlet.getWebType()).getClassName() != null && 
-							((ServletType) servlet.getWebType()).getClassName().trim().equals(
-							JSF_SERVLET_CLASS)) {
-						return servlet;
-					}
-				} else if (servlet.getWebType().isJspType()) {
-					if (((JSPType) servlet.getWebType()).getJspFile() != null && 
-							((JSPType) servlet.getWebType()).getJspFile().trim().equals(
-							JSF_SERVLET_CLASS)) {
-						return servlet;
-					}
-				}
-			}
-		}
-        
+        final Iterator it = webApp.getServlets().iterator();
+
+        while (it.hasNext())
+        {
+            final Servlet servlet = (Servlet) it.next();
+            if (servlet != null && servlet.getWebType() != null)
+            {
+                if (servlet.getWebType().isServletType())
+                {
+                    if (((ServletType) servlet.getWebType()).getClassName() != null
+                            && ((ServletType) servlet.getWebType())
+                                    .getClassName().trim().equals(
+                                            JSF_SERVLET_CLASS))
+                    {
+                        return servlet;
+                    }
+                } 
+            }
+        }
+
         // if we get to here then we have finished the loop
         // without finding the servlet we're looking for
-		return null;
-	}
+        return null;
+    }
 
-	/**
-	 * Creates a stubbed JSF configuration file for specified JSF version and path
-	 * @param jsfVersion
-	 * @param configPath
-	 */
-	public static void createConfigFile(final String jsfVersion, final IPath configPath) {
-		FileOutputStream os = null;
-		PrintWriter pw = null;
-		final String QUOTE = new String(new char[] { '"' });
-		try {
-			IPath dirPath = configPath.removeLastSegments(1);
-			dirPath.toFile().mkdirs();
-			File file = configPath.toFile();
-			file.createNewFile();
-			os = new FileOutputStream(file);
-			pw = new PrintWriter(os);
-			pw.write("<?xml version=" + QUOTE + "1.0" + QUOTE + " encoding=" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-					+ QUOTE + "UTF-8" + QUOTE + "?>\n\n"); //$NON-NLS-1$ //$NON-NLS-2$
+    /**
+     * Creates a stubbed JSF configuration file for specified JSF version and
+     * path
+     */
+    @Override
+    protected void doVersionSpecificConfigFile(final PrintWriter pw)
+    {
+        final String QUOTE = new String(new char[]
+        { '"' });
+        pw.write("<?xml version=" + QUOTE + "1.0" + QUOTE + " encoding=" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+                + QUOTE + "UTF-8" + QUOTE + "?>\n\n"); //$NON-NLS-1$ //$NON-NLS-2$
 
-			if (jsfVersion.equals(IJSFCoreConstants.FACET_VERSION_1_1)) 
-            { 
-				pw.write("<!DOCTYPE faces-config PUBLIC\n"); //$NON-NLS-1$
-				pw
-						.write("    " //$NON-NLS-1$
-								+ QUOTE
-								+ "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" //$NON-NLS-1$
-								+ QUOTE + "\n"); //$NON-NLS-1$
-				pw.write("    " + QUOTE //$NON-NLS-1$
-						+ "http://java.sun.com/dtd/web-facesconfig_1_1.dtd" //$NON-NLS-1$
-						+ QUOTE + ">\n\n"); //$NON-NLS-1$
+        pw.write("<!DOCTYPE faces-config PUBLIC\n"); //$NON-NLS-1$
+        pw.write("    " //$NON-NLS-1$
+                + QUOTE
+                + "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" //$NON-NLS-1$
+                + QUOTE + "\n"); //$NON-NLS-1$
+        pw.write("    " + QUOTE //$NON-NLS-1$
+                + "http://java.sun.com/dtd/web-facesconfig_1_1.dtd" //$NON-NLS-1$
+                + QUOTE + ">\n\n"); //$NON-NLS-1$
 
-				pw.write("<faces-config>\n\n"); //$NON-NLS-1$
-				pw.write("</faces-config>\n"); //$NON-NLS-1$
-			} 
+        pw.write("<faces-config>\n\n"); //$NON-NLS-1$
+        pw.write("</faces-config>\n"); //$NON-NLS-1$
+    }
 
-			pw.close();
-			pw = null;
-		} catch (FileNotFoundException e) {
-			JSFCorePlugin.log(IStatus.ERROR, Messages.JSFUtils_ErrorCreatingConfigFile, e);
-		} catch (IOException e) {
-			JSFCorePlugin.log(IStatus.ERROR, Messages.JSFUtils_ErrorCreatingConfigFile, e);
-		} finally {
-			if (pw != null)
-				pw.close();
-			if (os != null) {
-				try {
-					os.close();
-				} catch (IOException e) {
-					JSFCorePlugin.log(IStatus.ERROR, Messages.JSFUtils_ErrorClosingConfigFile, e);
-				}
-			}
-		}
-	}
+    /**
+     * Creates servlet reference in WebApp if not present or updates servlet
+     * name if found using the passed configuration.
+     * 
+     * @param webApp
+     * @param config
+     * @param servlet
+     * @return Servlet servlet - if passed servlet was null, will return created
+     *         servlet
+     */
+    private Servlet createOrUpdateServletRef(final WebApp webApp,
+            final IDataModel config, Servlet servlet)
+    {
+ 
+        String displayName = getDisplayName(config);
+        String className = getServletClassname(config);
 
-	/**
-	 * Creates servlet reference in WebApp if not present or updates servlet name if found
-	 * using the passed configuration.
-	 * 
-	 * @param webApp
-	 * @param config
-	 * @param servlet
-	 * @return Servlet servlet - if passed servlet was null, will return created servlet
-	 */
-	public static Servlet createOrUpdateServletRef(final WebApp webApp,
-			final IDataModel config, Servlet servlet) {
-		
-		String displayName 	= getDisplayName(config);
-		String className 	= getServletClassname(config);
-		
-		if (servlet == null){			
-			// Create the servlet instance and set up the parameters from data
-			// model
-			servlet = WebapplicationFactory.eINSTANCE.createServlet();
-			servlet.setServletName(displayName);
+        if (servlet == null)
+        {
+            // Create the servlet instance and set up the parameters from data
+            // model
+            servlet = WebapplicationFactory.eINSTANCE.createServlet();
+            servlet.setServletName(displayName);
 
-			ServletType servletType = WebapplicationFactory.eINSTANCE
-					.createServletType();
-			servletType.setClassName(className);
-			servlet.setWebType(servletType);
-			servlet.setLoadOnStartup(Integer.valueOf(1));
-			// Add the servlet to the web application model
-			webApp.getServlets().add(servlet);			
-		} else {
-			// update
-			updateServletMappings(webApp, servlet, servlet.getServletName().trim(), displayName);
-			servlet.setServletName(displayName);
-			servlet.setLoadOnStartup(Integer.valueOf(1));
-		}
-		return servlet;
-	}
+            ServletType servletType = WebapplicationFactory.eINSTANCE
+                    .createServletType();
+            servletType.setClassName(className);
+            servlet.setWebType(servletType);
+            servlet.setLoadOnStartup(Integer.valueOf(1));
+            // Add the servlet to the web application model
+            webApp.getServlets().add(servlet);
+        } 
+        else
+        {
+            // update
+            updateServletMappings(webApp, servlet, displayName);
+            servlet.setServletName(displayName);
+            servlet.setLoadOnStartup(Integer.valueOf(1));
+        }
+        return servlet;
+    }
 
-	private static void updateServletMappings(final WebApp webApp, final Servlet servlet,
-			final String servletName, final String newServletName) {
-		List<ServletMapping> mappings = findServletMappings(webApp, servlet, servletName);
-		for (ServletMapping map : mappings){
-			map.setName(newServletName);
-		}
-		
-	}
+    private void updateServletMappings(final WebApp webApp,
+            final Servlet servlet, final String displayName)
+    {
+        List<ServletMapping> mappings = findServletMappings(webApp, servlet);
+        for (ServletMapping map : mappings)
+        {
+            map.setName(displayName);
+        }
 
-	
-	private static List<ServletMapping> findServletMappings(final WebApp webApp, final Servlet servlet, final String servletName) {			
-		List<ServletMapping> mappings = new ArrayList<ServletMapping>();
-		List<ServletMapping> allMappings = webApp.getServletMappings();			
+    }
+
+	private List<ServletMapping> findServletMappings(final WebApp webApp, final Servlet servlet) {
+	    String servletName = servlet.getServletName();
+	    servletName = servletName != null ? servletName.trim() : servletName;
+	    final List<ServletMapping> mappings = new ArrayList<ServletMapping>();
+		final List<ServletMapping> allMappings = webApp.getServletMappings();
 		for (int i=allMappings.size()-1;i>=0;--i){
 			ServletMapping mapping = allMappings.get(i);
 			if (mapping != null && 
@@ -217,18 +175,8 @@
 					mapping.getServlet().getServletName() != null &&
 					mapping.getServlet().getServletName().trim().equals(servletName))
 				mappings.add(mapping);
-		}		
-		return mappings;		
-	}
-
-	/**
-	 * @param webApp as Object
-	 * @return true if webApp instanceof org.eclipse.jst.javaee.web.WebApp
-	 */
-	public static boolean isWebApp25(final Object webApp) {
-		if (webApp instanceof org.eclipse.jst.javaee.web.WebApp)
-			return true;
-		return false;
+		}
+		return mappings;
 	}
 
 	/**
@@ -238,7 +186,7 @@
 	 * @param urlMappingList - list of string values to  be used in url-pattern for servlet-mapping
 	 * @param servlet
 	 */
-	public static void setUpURLMappings(final WebApp webApp, final List urlMappingList,
+	private void setUpURLMappings(final WebApp webApp, final List urlMappingList,
 			final Servlet servlet) {
 		// Add mappings
 		Iterator it = urlMappingList.iterator();
@@ -256,7 +204,7 @@
 	}
 	
 
-	private static boolean doesServletMappingExist(final WebApp webApp, final Servlet servlet,
+	private boolean doesServletMappingExist(final WebApp webApp, final Servlet servlet,
 			final String pattern) {	
 		
 		List mappings = webApp.getServletMappings();
@@ -282,7 +230,7 @@
 	 * @param webApp
 	 * @param servlet
 	 */
-	public static void removeURLMappings(final WebApp webApp, final Servlet servlet) {
+	private void removeURLMappings(final WebApp webApp, final Servlet servlet) {
 		List mappings = webApp.getServletMappings();
 		String servletName = servlet.getServletName();
 		if (servletName != null) {
@@ -304,13 +252,16 @@
 	 * @param webApp
 	 * @param config
 	 */
-	public static void setupConfigFileContextParamForV2_3(final WebApp webApp,
+	private void setupConfigFileContextParamForV2_3(final WebApp webApp,
 			final IDataModel config) {
 		// if not default name and location, then add context param
 		ContextParam cp = null;
 		ContextParam foundCP = null;
 		boolean found = false;
-		if (!config.getStringProperty(IJSFFacetInstallDataModelProperties.CONFIG_PATH).equals(JSF_DEFAULT_CONFIG_PATH)) {
+        final String stringProperty = 
+            config.getStringProperty(IJSFFacetInstallDataModelProperties.CONFIG_PATH);
+        if (stringProperty != null &&
+                !stringProperty.equals(JSF_DEFAULT_CONFIG_PATH)) {
 			// check to see if present
 			Iterator it = webApp.getContexts().iterator();
 			while (it.hasNext()) {
@@ -325,13 +276,13 @@
 			if (!found) {
 				cp = WebapplicationFactory.eINSTANCE.createContextParam();
 				cp.setParamName(JSF_CONFIG_CONTEXT_PARAM);
-				cp.setParamValue(config.getStringProperty(IJSFFacetInstallDataModelProperties.CONFIG_PATH));
+				cp.setParamValue(stringProperty);
 				webApp.getContexts().add(cp);
 			} else {
 				cp = foundCP;
-				if (cp.getParamValue().indexOf(config.getStringProperty(IJSFFacetInstallDataModelProperties.CONFIG_PATH)) < 0) {
+				if (cp.getParamValue().indexOf(stringProperty) < 0) {
 					String curVal = cp.getParamValue();
-					String val = config.getStringProperty(IJSFFacetInstallDataModelProperties.CONFIG_PATH);
+					String val = stringProperty;
 					if (curVal != null && !"".equals(curVal.trim())) { //$NON-NLS-1$
 						val = curVal + ",\n" + val; //$NON-NLS-1$
 					}
@@ -345,13 +296,16 @@
 	 * @param webApp
 	 * @param config
 	 */
-	public static void setupConfigFileContextParamForV2_4(final WebApp webApp,
+	private void setupConfigFileContextParamForV2_4(final WebApp webApp,
 			final IDataModel config) {
 		// if not default name and location, then add context param
 		ParamValue foundCP = null;
 		ParamValue cp = null;
 		boolean found = false;
-		if (!config.getStringProperty(IJSFFacetInstallDataModelProperties.CONFIG_PATH).equals(JSF_DEFAULT_CONFIG_PATH)) {
+		final String stringProperty = 
+		    config.getStringProperty(IJSFFacetInstallDataModelProperties.CONFIG_PATH);
+        if (stringProperty != null &&
+                !stringProperty.equals(JSF_DEFAULT_CONFIG_PATH)) {
 			// check to see if present
 			Iterator it = webApp.getContextParams().iterator();
 			while (it.hasNext()) {
@@ -366,13 +320,13 @@
 			if (!found) {
 				ParamValue pv = CommonFactory.eINSTANCE.createParamValue();
 				pv.setName(JSF_CONFIG_CONTEXT_PARAM);
-				pv.setValue(config.getStringProperty(IJSFFacetInstallDataModelProperties.CONFIG_PATH));
+				pv.setValue(stringProperty);
 				webApp.getContextParams().add(pv);
 			} else {
 				cp = foundCP;
-				if (cp.getValue().indexOf(config.getStringProperty(IJSFFacetInstallDataModelProperties.CONFIG_PATH)) < 0) {
+				if (cp.getValue().indexOf(stringProperty) < 0) {
 					String curVal = cp.getValue();
-					String val = config.getStringProperty(IJSFFacetInstallDataModelProperties.CONFIG_PATH);
+					String val = stringProperty;
 					if (curVal != null && !"".equals(curVal.trim())) { //$NON-NLS-1$
 						val = curVal + ",\n" + val; //$NON-NLS-1$
 					}
@@ -382,83 +336,210 @@
 		}
 	}
 
-	/**
-	 * @param webAppObj as Object
-	 * @return true if webApp instanceof org.eclipse.jst.j2ee.web.WebApp and versionID == 24
-	 */
-	public static boolean isWebApp24(final Object webAppObj) {
-		if (webAppObj instanceof WebApp &&
-				((WebApp)webAppObj).getVersionID() == 24)
-			return true;
-		return false;
-	}
-	
-	/**
-	 * @param webAppObj as Object
-	 * @return true if webApp instanceof org.eclipse.jst.j2ee.web.WebApp and versionID == 23
-	 */
-	public static boolean isWebApp23(final Object webAppObj) {
-		if (webAppObj instanceof WebApp &&
-				((WebApp)webAppObj).getVersionID() == 23)
-			return true;
-		return false;
-	}
-	
-	/**
-	 * @param webApp
-	 * @return the default file extension from the context param.  Default is "jsp" if no context param.
-	 */
-	public static String getDefaultSuffix(final WebApp webApp) {
-		String defaultSuffix = "jsp"; //$NON-NLS-1$
-		for (Iterator it = webApp.getContexts().iterator();it.hasNext();) {		
-			ContextParam cp = (ContextParam) it.next();		
-			if (cp != null &&
-					cp.getParamName() != null && 
-					cp.getParamName().trim().equals(JSF_DEFAULT_SUFFIX_CONTEXT_PARAM)){				
-				String defSuffix = cp.getParamValue();
-				if (defSuffix.startsWith(".")) //$NON-NLS-1$
-					defSuffix = defSuffix.substring(1);
-								
-				return defSuffix;
-			}
-		}
-		return defaultSuffix;
-	}
-	
-	/**
-	 * @param map
-	 * @return prefix mapping.  may return null.
-	 */
-	public static String getPrefixMapping(final ServletMapping map) {
-		IPath extPath = new Path(map.getUrlPattern());
-		if (extPath != null){
-			String ext = extPath.getFileExtension();
-			if (ext == null){
-				String lastSeg = extPath.lastSegment();
-				if (lastSeg != null && 
-						lastSeg.equals("*")) //$NON-NLS-1$
-				{
-					return extPath.removeLastSegments(1).toString();
-				}
-				
-				return extPath.toString();				
-			}
-		}
-		return null;
-	}
-	
-	/**
-	 * @param map
-	 * @return extension from map.  Will return null if file extension not found in url patterns.
-	 */
-	public static String getFileExtensionFromMap(final ServletMapping map) {
-		IPath extPath = new Path(map.getUrlPattern());
-		if (extPath != null){
-			String ext = extPath.getFileExtension();
-			if (ext != null && !ext.equals("")) //$NON-NLS-1$
-				return ext;
-		}
-		return null;
-	}
+    /**
+     * @param webApp
+     * @return the default file extension from the context param. Default is
+     *         "jsp" if no context param.
+     */
+    private String getDefaultSuffix(final WebApp webApp)
+    {
+        String defaultSuffix = getDefaultDefaultSuffix();
+        for (Iterator it = webApp.getContexts().iterator(); it.hasNext();)
+        {
+            ContextParam cp = (ContextParam) it.next();
+            if (cp != null)
+            {
+                final String paramName = cp.getParamName();
+                final String suffix = calculateSuffix(paramName, cp.getParamValue());
+                if (suffix != null)
+                {
+                    return suffix;
+                }
+            }
+        }
+        return defaultSuffix;
+    }
 
+    /**
+     * @param map
+     * @return prefix mapping. may return null.
+     */
+    private String getPrefixMapping(final ServletMapping map)
+    {
+        final String urlPattern = map.getUrlPattern();
+        if (urlPattern != null && urlPattern.trim().length() != 0)
+        {
+            IPath extPath = new Path(urlPattern);
+            if (extPath != null)
+            {
+                String ext = extPath.getFileExtension();
+                if (ext == null)
+                {
+                    String lastSeg = extPath.lastSegment();
+                    if (lastSeg != null && lastSeg.equals("*")) //$NON-NLS-1$
+                    {
+                        return extPath.removeLastSegments(1).toString();
+                    }
+
+                    return extPath.toString();
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * @param map
+     * @return extension from map. Will return null if file extension not found
+     *         in url patterns.
+     */
+    private String getFileExtensionFromMap(final ServletMapping map)
+    {
+        final String urlPattern = map.getUrlPattern();
+        if (urlPattern != null
+                && urlPattern.trim().length() != 0)
+        {
+            IPath extPath = new Path(map.getUrlPattern());
+            if (extPath != null)
+            {
+                String ext = extPath.getFileExtension();
+                if (ext != null && ext.trim().length() != 0)
+                {
+                    return ext;
+                }
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public void updateWebApp(Object webApp, IDataModel config)
+    {
+        // create or update servlet ref
+        Servlet servlet = findJSFServlet((WebApp) webApp);// check to see
+                                                            // if already
+                                                            // present
+        
+        
+        servlet = createOrUpdateServletRef((WebApp) webApp, config, servlet);
+
+        // init mappings
+        final List listOfMappings = getServletMappings(config);
+        setUpURLMappings((WebApp) webApp, listOfMappings, servlet);
+
+        // setup context params
+        setupContextParams((WebApp) webApp, config);
+    }
+
+    private void setupContextParams(WebApp webApp, final IDataModel config) {
+        if (webApp.getVersionID() == J2EEVersionConstants.WEB_2_3_ID)//shouldn't have to do it this way, but that's the way it goes 119442
+        {
+            setupConfigFileContextParamForV2_3(webApp, config);
+        }
+        else if (webApp.getVersionID() == J2EEVersionConstants.WEB_2_4_ID)
+        {
+            setupConfigFileContextParamForV2_4(webApp, config);
+        }
+        else
+        {
+            throw new IllegalArgumentException("Invalid argument: "+webApp.getVersionID()); //$NON-NLS-1$
+        }
+    }
+
+    @Override
+    public void rollbackWebApp(Object webApp)
+    {
+        org.eclipse.jst.j2ee.webapplication.Servlet servlet = findJSFServlet((WebApp) webApp);
+        if (servlet == null)
+        {
+            return;
+        }
+        // remove faces url mappings
+        removeURLMappings((WebApp) webApp, servlet);
+        // remove context params
+        removeJSFContextParams((WebApp) webApp, servlet);
+        // remove servlet
+        removeJSFServlet((WebApp) webApp, servlet);
+    }
+
+    private void removeJSFContextParams(final org.eclipse.jst.j2ee.webapplication.WebApp webApp, final org.eclipse.jst.j2ee.webapplication.Servlet servlet) {
+        Iterator it = webApp.getContextParams().iterator();
+        while (it.hasNext()) {
+            org.eclipse.jst.j2ee.common.ParamValue cp = (org.eclipse.jst.j2ee.common.ParamValue) it.next();
+            if (cp.getName().equals(JSFUtils.JSF_CONFIG_CONTEXT_PARAM)) {
+                webApp.getContextParams().remove(cp);
+                break;
+            }
+        }
+    }
+
+    private void removeJSFServlet(final org.eclipse.jst.j2ee.webapplication.WebApp webApp, final org.eclipse.jst.j2ee.webapplication.Servlet servlet) {
+        webApp.getServlets().remove(servlet);
+    }
+
+    @Override
+    public IPath getFileUrlPath(Object webAppObj, IResource resource,
+            IPath existingURL)
+    {
+        if (webAppObj instanceof WebApp)
+        {
+            final WebApp webApp = (WebApp)webAppObj;
+            final Servlet servlet = findJSFServlet(webApp);
+            // if no faces servlet, do nothing
+            if (servlet == null)
+            {
+                return null;
+            }
+
+            //if not a JSF page, do nothing
+            if (!isJSFPage(resource))
+            {
+                return null;
+            }
+
+            final String defaultSuffix = getDefaultSuffix(webApp);
+            //is the resource using default_suffix
+            final String fileExtension = resource.getFileExtension();
+            final boolean canUseExtensionMapping = 
+                fileExtension != null && fileExtension.equalsIgnoreCase(defaultSuffix);
+
+            //if not using default extension and is not a known file extension, then we will abort
+            if (! canUseExtensionMapping && ! isValidKnownExtension(fileExtension))
+            {
+                return null;
+            }
+
+            Iterator mappings = servlet.getMappings().iterator();
+            ServletMapping map = null;
+            String foundFileExtension = null;
+            String foundPrefixMapping = null;
+            while (mappings.hasNext())
+            {
+                map = (ServletMapping)mappings.next();
+
+                foundFileExtension = getFileExtensionFromMap(map);
+                if (foundFileExtension != null && canUseExtensionMapping) 
+                {
+                    return existingURL.removeFileExtension().addFileExtension(foundFileExtension);
+                }
+                
+                if (foundPrefixMapping == null)
+                {
+                    foundPrefixMapping = getPrefixMapping(map);
+                }
+            }
+            if (foundPrefixMapping != null)
+            {
+                return new Path(foundPrefixMapping).append(existingURL); 
+            }
+            if (! canUseExtensionMapping && foundFileExtension != null){
+                //we could prompt user that this may not work...
+                //for now we will return the extension mapping
+                return existingURL.removeFileExtension().addFileExtension(foundFileExtension);
+            }
+            
+            //we could, at this point, add a url mapping to the faces servlet, or prompt user that it may be a good idea to add one... ;-
+        }
+        return null;
+    }
 }
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFUtils12.java b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFUtils12.java
index 71a2b2b..e8e8049 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFUtils12.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFUtils12.java
@@ -11,28 +11,22 @@
 
 package org.eclipse.jst.jsf.core.internal.project.facet;
 
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.Iterator;
 import java.util.List;
 
+import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Path;
+import org.eclipse.jst.j2ee.model.IModelProvider;
 import org.eclipse.jst.javaee.core.JavaeeFactory;
 import org.eclipse.jst.javaee.core.ParamValue;
 import org.eclipse.jst.javaee.core.UrlPatternType;
 import org.eclipse.jst.javaee.web.Servlet;
 import org.eclipse.jst.javaee.web.ServletMapping;
 import org.eclipse.jst.javaee.web.WebApp;
-import org.eclipse.jst.javaee.web.WebAppVersionType;
 import org.eclipse.jst.javaee.web.WebFactory;
-import org.eclipse.jst.jsf.core.IJSFCoreConstants;
-import org.eclipse.jst.jsf.core.internal.JSFCorePlugin;
-import org.eclipse.jst.jsf.core.internal.Messages;
+import org.eclipse.jst.jsf.core.JSFVersion;
 import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
 
 /**
@@ -40,85 +34,83 @@
  * 
  * @author Gerry Kessler - Oracle
  */
-public class JSFUtils12 extends JSFUtils {
+/*package: use JSFUtilFactory*/ class JSFUtils12 extends JSFUtils {
 
 	/**
-	 * @param webApp
-	 * @return Servlet - the JSF Servlet for the specified WebApp or null if not present
+	 * @param modelProvider 
+	 * 
 	 */
-	public static Servlet findJSFServlet(final WebApp webApp) {
+	protected JSFUtils12(final IModelProvider modelProvider)
+    {
+        this(JSFVersion.V1_2, modelProvider);
+    }
 
-		Iterator it = webApp.getServlets().iterator();
-		
-		while (it.hasNext()) {
-            Servlet servlet = (Servlet) it.next();
-			if (servlet.getServletClass() != null &&
-					servlet.getServletClass().trim().equals (JSF_SERVLET_CLASS)) {
-				return servlet;
-			}
-		}
-        
+    /**
+     * @param jsfVersion
+     * @param modelProvider 
+     */
+    protected JSFUtils12(final JSFVersion jsfVersion, final IModelProvider modelProvider)
+    {
+        super(jsfVersion, modelProvider);
+        if (jsfVersion.compareTo(JSFVersion.V1_2) < 0)
+        {
+            throw new IllegalArgumentException(
+                    "JsfVersion must be at least 1.2"); //$NON-NLS-1$
+        }
+    }
+
+    /**
+     * @param webApp
+     * @return Servlet - the JSF Servlet for the specified WebApp or null if not
+     *         present
+     */
+    private Servlet findJSFServlet(final WebApp webApp)
+    {
+        if (webApp == null)
+        {
+            return null;
+        }
+
+        for (final Servlet servlet : webApp.getServlets())
+        {
+            if (servlet != null &&
+                    servlet.getServletClass() != null
+                    && servlet.getServletClass().trim().equals(
+                            JSF_SERVLET_CLASS))
+            {
+                return servlet;
+            }
+        }
+
         // if we get to here then we have finished the loop
         // without finding the servlet we're looking for
-		return null;
-	}
+        return null;
+    }
 
 	/**
 	 * Creates a stubbed JSF v1.2 configuration file for specified JSF version and path
-	 * @param jsfVersion
-	 * @param configPath
 	 */
-	public static void createConfigFile(final String jsfVersion, final IPath configPath) {
-		FileOutputStream os = null;
-		PrintWriter pw = null;
-		final String QUOTE = new String(new char[] { '"' });
-		try {
-			IPath dirPath = configPath.removeLastSegments(1);
-			dirPath.toFile().mkdirs();
-			File file = configPath.toFile();
-			file.createNewFile();
-			os = new FileOutputStream(file);
-			pw = new PrintWriter(os);
-			pw.write("<?xml version=" + QUOTE + "1.0" + QUOTE + " encoding=" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-					+ QUOTE + "UTF-8" + QUOTE + "?>\n\n"); //$NON-NLS-1$ //$NON-NLS-2$
-
-			if (jsfVersion.equals(IJSFCoreConstants.FACET_VERSION_1_2)) 
-            {
-				pw.write("<faces-config\n"); //$NON-NLS-1$
-				pw.write("    " + "xmlns=" + QUOTE //$NON-NLS-1$ //$NON-NLS-2$
-						+ "http://java.sun.com/xml/ns/javaee" + QUOTE + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
-				pw.write("    " + "xmlns:xsi=" + QUOTE //$NON-NLS-1$ //$NON-NLS-2$
-						+ "http://www.w3.org/2001/XMLSchema-instance" + QUOTE //$NON-NLS-1$
-						+ "\n"); //$NON-NLS-1$
-				pw
-						.write("    " //$NON-NLS-1$
-								+ "xsi:schemaLocation=" //$NON-NLS-1$
-								+ QUOTE
-								+ "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd" //$NON-NLS-1$
-								+ QUOTE + "\n"); //$NON-NLS-1$
-				pw.write("    " + "version=" + QUOTE + "1.2" + QUOTE + ">\n\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-				pw.write("</faces-config>\n"); //$NON-NLS-1$
-			}
-
-			pw.close();
-			pw = null;
-		} catch (FileNotFoundException e) {
-			JSFCorePlugin.log(IStatus.ERROR, Messages.JSFUtils_ErrorCreatingConfigFile, e);
-		} catch (IOException e) {
-			JSFCorePlugin.log(IStatus.ERROR, Messages.JSFUtils_ErrorCreatingConfigFile, e);
-		} finally {
-			if (pw != null)
-				pw.close();
-			if (os != null) {
-				try {
-					os.close();
-				} catch (IOException e) {
-					JSFCorePlugin.log(IStatus.ERROR, Messages.JSFUtils_ErrorClosingConfigFile, e);
-				}
-			}
-		}
-	}
-
+	@Override
+    public void doVersionSpecificConfigFile(final PrintWriter pw)
+    {
+        final String QUOTE = new String(new char[]
+        { '"' });
+        pw.write("<?xml version=" + QUOTE + "1.0" + QUOTE + " encoding=" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+                + QUOTE + "UTF-8" + QUOTE + "?>\n\n"); //$NON-NLS-1$ //$NON-NLS-2$
+        pw.write("<faces-config\n"); //$NON-NLS-1$
+        pw.write("    " + "xmlns=" + QUOTE //$NON-NLS-1$ //$NON-NLS-2$
+                + "http://java.sun.com/xml/ns/javaee" + QUOTE + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+        pw.write("    " + "xmlns:xsi=" + QUOTE //$NON-NLS-1$ //$NON-NLS-2$
+                + "http://www.w3.org/2001/XMLSchema-instance" + QUOTE //$NON-NLS-1$
+                + "\n"); //$NON-NLS-1$
+        pw.write("    " //$NON-NLS-1$
+                + "xsi:schemaLocation=" //$NON-NLS-1$
+                + QUOTE
+                + "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd" //$NON-NLS-1$
+                + QUOTE + "\n"); //$NON-NLS-1$
+        pw.write("    " + "version=" + QUOTE + "1.2" + QUOTE + ">\n\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+        pw.write("</faces-config>\n"); //$NON-NLS-1$
+    }
 
 	/**
 	 * Creates servlet reference in WebApp if not present or updates servlet name if found
@@ -129,8 +121,8 @@
 	 * @param servlet
 	 * @return Servlet servlet - if passed servlet was null, will return created servlet
 	 */
-	public static Servlet createOrUpdateServletRef(final WebApp webApp,
-			final IDataModel config, org.eclipse.jst.javaee.web.Servlet servlet) {
+	private Servlet createOrUpdateServletRef(final WebApp webApp,
+			final IDataModel config, Servlet servlet) {
 		
 		String displayName = getDisplayName(config);		
 		String className = getServletClassname(config);
@@ -153,86 +145,99 @@
 		return servlet;
 	}
 
-	private static void updateServletMappings(final WebApp webApp, final Servlet servlet,
-			final String displayName) {
-		// update mappings for new name
-		ServletMapping mapping = findServletMapping(webApp, servlet);
-		if (mapping != null) {
-			mapping.setServletName(displayName);
-		}
-		
-	}
+    private void updateServletMappings(final WebApp webApp,
+            final Servlet servlet, final String displayName)
+    {
+        // update mappings for new name
+        ServletMapping mapping = findServletMapping(webApp, servlet);
+        if (mapping != null)
+        {
+            mapping.setServletName(displayName);
+        }
+    }
 
-	/**
-	 * @param webAppObj as Object
-	 * @return true if webApp instanceof org.eclipse.jst.javaee.web.WebApp and WebAppVersionType._25
-	 */
-	public static boolean isWebApp25(final Object webAppObj) {
-		if (webAppObj instanceof WebApp &&
-				((WebApp)webAppObj).getVersion() == WebAppVersionType._25_LITERAL) 
-			return true;
-		return false;
-	}
-	
-	/**
-	 * Creates servlet-mappings for the servlet for 2.5 WebModules or greated
-	 * 
-	 * @param webApp
-	 * @param urlMappingList - list of string values to  be used in url-pattern for servlet-mapping
-	 * @param servlet
-	 */
-	public static void setUpURLMappings(final WebApp webApp, final List urlMappingList,
-			final Servlet servlet) {
-		
-		if (urlMappingList.size() > 0) {
-			ServletMapping mapping = findServletMapping(webApp, servlet);
-			if (mapping == null){
-				mapping = WebFactory.eINSTANCE.createServletMapping();
-				mapping.setServletName(servlet.getServletName());
-				webApp.getServletMappings().add(mapping);
-			}
-			// Add patterns
-			Iterator it = urlMappingList.iterator();
-			while (it.hasNext()) {
-				String pattern = (String) it.next();
-				if (!(doesServletMappingPatternExist(webApp, mapping, pattern))){
-					UrlPatternType urlPattern = JavaeeFactory.eINSTANCE.createUrlPatternType();
-					urlPattern.setValue(pattern);				
-					mapping.getUrlPatterns().add(urlPattern);
-				}
-			}
-		}
-	}
-	
-	private static ServletMapping findServletMapping(final WebApp webApp, final Servlet servlet) {
+    /**
+     * Creates servlet-mappings for the servlet for 2.5 WebModules or greated
+     * 
+     * @param webApp
+     * @param urlMappingList
+     *            - list of string values to be used in url-pattern for
+     *            servlet-mapping
+     * @param servlet
+     */
+    private void setUpURLMappings(final WebApp webApp,
+            final List<String> urlMappingList, final Servlet servlet)
+    {
+
+        if (urlMappingList.size() > 0)
+        {
+            ServletMapping mapping = findServletMapping(webApp, servlet);
+            if (mapping == null)
+            {
+                mapping = WebFactory.eINSTANCE
+                        .createServletMapping();
+                mapping.setServletName(servlet.getServletName());
+                webApp.getServletMappings().add(mapping);
+            }
+            // Add patterns
+            for (final String pattern : urlMappingList)
+            {
+                if (!(doesServletMappingPatternExist(webApp, servlet, pattern)))
+                {
+                    UrlPatternType urlPattern = JavaeeFactory.eINSTANCE
+                            .createUrlPatternType();
+                    urlPattern.setValue(pattern);
+                    mapping.getUrlPatterns().add(urlPattern);
+                }
+            }
+        }
+    }
+
+	private ServletMapping findServletMapping(final WebApp webApp, final Servlet servlet) {
 		for (Iterator it=webApp.getServletMappings().iterator();it.hasNext();){
 			ServletMapping mapping = (ServletMapping)it.next();
 			if (mapping.getServletName() != null && 
 					servlet.getServletName() != null &&
 					mapping.getServletName().trim().equals(servlet.getServletName().trim()))
 				return mapping;
-		}
+        }
 		return null;
-	}
+    }
 
-	private static boolean doesServletMappingPatternExist(final WebApp webApp, final ServletMapping mapping,
-			final String pattern) {	
-		for (Iterator it=mapping.getUrlPatterns().iterator();it.hasNext();){
-			String patternTypeValue = ((UrlPatternType)it.next()).getValue();
-			if( patternTypeValue != null && 
-					pattern.equals(patternTypeValue.trim()))
-				return true;
-		}
-		return false;
-	}
+    private boolean doesServletMappingPatternExist(final WebApp webApp,
+            final Servlet servlet, final String pattern)
+    {
+        List<ServletMapping> mappings = webApp.getServletMappings();
+        String servletName = servlet.getServletName();
+        if (servletName != null)
+        {
+            servletName = servletName.trim();
+            for (final ServletMapping mapping : mappings)
+            {
+                if (mapping != null && 
+                        mapping.getServletName() != null && 
+                        servletName.equals(mapping.getServletName().trim()))
+                {
+                    for (final UrlPatternType urlPattern : mapping.getUrlPatterns())
+                    {
+                        String patternTypeValue = urlPattern.getValue();
+                        if (patternTypeValue != null
+                                && pattern.equals(patternTypeValue.trim()))
+                            return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
 	
 	/**
 	 * Removes servlet-mappings for servlet using servlet-name for >= 2.5 WebModules.
 	 * @param webApp
 	 * @param servlet
 	 */
-	public static void removeURLMappings(final WebApp webApp, final Servlet servlet) {
-		List mappings = webApp.getServletMappings();					
+	private void removeURLMappings(final  WebApp webApp, final Servlet servlet) {
+		List mappings = webApp.getServletMappings();
 		String servletName = servlet.getServletName();
 		if (servletName != null) {
 			servletName = servletName.trim();
@@ -253,7 +258,7 @@
 	 * @param webApp
 	 * @param config
 	 */
-	public static void setupConfigFileContextParamForV2_5(final org.eclipse.jst.javaee.web.WebApp webApp,
+	private void setupConfigFileContextParamForV2_5(final org.eclipse.jst.javaee.web.WebApp webApp,
 			final IDataModel config) {
 		// if not default name and location, then add context param
 		ParamValue foundCP = null;
@@ -290,32 +295,37 @@
 		}
 	}
 
-	/**
-	 * @param webApp
-	 * @return the default file extension from the context param.  Default is "jsp" if no context param
-	 */
-	public static String getDefaultSuffix(final WebApp webApp) {
-		String defaultSuffix = "jsp"; //$NON-NLS-1$
-		for (Iterator it = webApp.getContextParams().iterator();it.hasNext();) {		
-			ParamValue cp = (ParamValue) it.next();		
-			if (cp != null && 
-					cp.getParamName() != null && 
-					cp.getParamName().trim().equals(JSF_DEFAULT_SUFFIX_CONTEXT_PARAM)){				
-				String defSuffix = cp.getParamValue();
-				if (defSuffix.startsWith(".")) //$NON-NLS-1$
-					defSuffix = defSuffix.substring(1);
-								
-				return defSuffix;
-			}
-		}
-		return defaultSuffix;
-	}
-	
+    /**
+     * @param webApp
+     * @return the default file extension from the context param. Default is
+     *         "jsp" if no context param
+     */
+    private String getDefaultSuffix(final WebApp webApp)
+    {
+        String defaultSuffix = getDefaultDefaultSuffix();
+        for (Iterator it = webApp.getContextParams().iterator(); it.hasNext();)
+        {
+            ParamValue cp = (ParamValue) it.next();
+            if (cp != null)
+            {
+                final String paramName = cp.getParamName();
+                final String suffix = calculateSuffix(paramName, cp
+                        .getParamValue());
+                if (suffix != null)
+                {
+                    return suffix;
+                }
+            }
+        }
+        return defaultSuffix;
+    }
+
+    
 	/**
 	 * @param map
 	 * @return prefix mapping 
 	 */
-	public static String getPrefixMapping(final ServletMapping map) {
+	private String getPrefixMapping(final ServletMapping map) {
 		List urls = map.getUrlPatterns();
 		for (Iterator it=urls.iterator();it.hasNext();){
 			IPath extPath = new Path(((UrlPatternType)it.next()).getValue());
@@ -339,7 +349,7 @@
 	 * @param map
 	 * @return extension from map.  Will return null if file extension not found in url patterns.
 	 */
-	public static String getFileExtensionFromMap(final ServletMapping map) {
+	private String getFileExtensionFromMap(final ServletMapping map) {
 		List urls = map.getUrlPatterns();
 		for (Iterator it=urls.iterator();it.hasNext();){
 			IPath extPath = new Path(((UrlPatternType)it.next()).getValue());
@@ -351,4 +361,124 @@
 		}
 		return null;
 	}
+
+    @Override
+    public void updateWebApp(Object webApp, IDataModel config)
+    {
+        // create or update servlet ref
+        Servlet servlet = findJSFServlet((WebApp)webApp);// check to see
+                                                            // if already
+        
+        servlet = createOrUpdateServletRef((WebApp) webApp, config, servlet);
+
+        // init mappings
+        final List listOfMappings = getServletMappings(config);
+        setUpURLMappings((WebApp)webApp, listOfMappings, servlet);
+
+        // setup context params
+        setupConfigFileContextParamForV2_5((WebApp)webApp, config);
+
+    }
+
+    
+    @Override
+    public void rollbackWebApp(Object webApp)
+    {
+        Servlet servlet = findJSFServlet((WebApp) webApp);
+        if (servlet == null)
+        {
+            return;
+        }
+        // remove faces url mappings
+        removeURLMappings((WebApp)webApp, servlet);
+        // remove context params
+        removeJSFContextParams((WebApp)webApp, servlet);
+        // remove servlet
+        removeJSFServlet((WebApp)webApp, servlet);
+    }
+    
+    private void removeJSFContextParams(final WebApp webApp, final Servlet servlet) {
+        Iterator it = webApp.getContextParams().iterator();
+        while (it.hasNext()) {
+            ParamValue cp = (ParamValue) it.next();
+            if (cp.getParamName().equals(JSFUtils.JSF_CONFIG_CONTEXT_PARAM)) {
+                webApp.getContextParams().remove(cp);
+                break;
+            }
+        }
+    }
+
+    private void removeJSFServlet(final WebApp webApp, final Servlet servlet) {     
+        webApp.getServlets().remove(servlet);
+    }
+
+    @Override
+    public IPath getFileUrlPath(Object webAppObj, IResource resource,
+            IPath existingURL)
+    {
+        if (webAppObj instanceof WebApp)
+        {
+            WebApp webApp =  (WebApp) webAppObj;
+            Servlet servlet = findJSFServlet(webApp);
+            if (servlet == null)
+            {// if no faces servlet, do nothing
+                return null;
+            }
+
+            final String servletName = servlet.getServletName();
+
+            // if not a JSF page, do nothing
+            if (!isJSFPage(resource))
+            {
+                return null;
+            }
+
+            String defaultSuffix = getDefaultSuffix(webApp);
+            // is the resource using default_suffix
+            String fileExtension = resource.getFileExtension();
+            boolean canUseExtensionMapping = fileExtension != null && fileExtension.equalsIgnoreCase(defaultSuffix);
+
+            // if not using default extension and is not a known file extension,
+            // then we will abort
+            if (!canUseExtensionMapping
+                    && !isValidKnownExtension(resource.getFileExtension()))
+                return null;
+
+            String foundFileExtension = null;
+            for (final ServletMapping map : webApp.getServletMappings())
+            {
+                if (map != null &&
+                        map.getServletName() != null &&
+                        map.getServletName().trim().equals(servletName.trim()))
+                {
+                    foundFileExtension = getFileExtensionFromMap(map);
+                    if (foundFileExtension != null && canUseExtensionMapping)
+                    {
+                        return existingURL.removeFileExtension()
+                                .addFileExtension(foundFileExtension);
+                    }
+
+                    String foundPrefixMapping = getPrefixMapping(map);
+                    if (foundPrefixMapping != null)
+                    {
+                        return new Path(foundPrefixMapping).append(existingURL);
+                    }
+                }
+            }
+
+            if (!canUseExtensionMapping && foundFileExtension != null)
+            {
+                // we could prompt user that this may not work...
+                // for now we will return the extension mapping
+                return existingURL.removeFileExtension().addFileExtension(
+                        foundFileExtension);
+            }
+
+            // we could, at this point, add a url mapping to the faces servlet,
+            // or prompt user that it may be a good idea to add one... ;-
+        }
+        return null;
+    }
+    
+    
 }
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFUtils20.java b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFUtils20.java
new file mode 100644
index 0000000..332c14d
--- /dev/null
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/internal/project/facet/JSFUtils20.java
@@ -0,0 +1,54 @@
+package org.eclipse.jst.jsf.core.internal.project.facet;
+
+import java.io.PrintWriter;
+
+import org.eclipse.jst.j2ee.model.IModelProvider;
+import org.eclipse.jst.jsf.core.JSFVersion;
+
+/**
+ * JSF Utils instance for JSF 2.0.
+ * 
+ * @author cbateman
+ * 
+ */
+/* package: use JSFUtilFactory */class JSFUtils20 extends JSFUtils12
+{
+    private static final String DEFAULT_DEFAULT_MAPPING_SUFFIX = "xhtml"; //$NON-NLS-1$
+
+    /**
+     * @param modelProvider
+     */
+    protected JSFUtils20(final IModelProvider modelProvider)
+    {
+        super(JSFVersion.V2_0, modelProvider);
+    }
+
+    @Override
+    protected String getDefaultDefaultSuffix()
+    {
+        return DEFAULT_DEFAULT_MAPPING_SUFFIX;
+    }
+
+    @Override
+    public void doVersionSpecificConfigFile(PrintWriter pw)
+    {
+        final String QUOTE = new String(new char[]
+        { '"' });
+        pw.write("<?xml version=" + QUOTE + "1.0" + QUOTE + " encoding=" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+                + QUOTE + "UTF-8" + QUOTE + "?>\n\n"); //$NON-NLS-1$ //$NON-NLS-2$
+        pw.write("<faces-config\n"); //$NON-NLS-1$
+        pw.write("    " + "xmlns=" + QUOTE //$NON-NLS-1$ //$NON-NLS-2$
+                + "http://java.sun.com/xml/ns/javaee" + QUOTE + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+        pw.write("    " + "xmlns:xsi=" + QUOTE //$NON-NLS-1$ //$NON-NLS-2$
+                + "http://www.w3.org/2001/XMLSchema-instance" + QUOTE //$NON-NLS-1$
+                + "\n"); //$NON-NLS-1$
+        pw.write("    " //$NON-NLS-1$
+                + "xsi:schemaLocation=" //$NON-NLS-1$
+                + QUOTE
+                + "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd" //$NON-NLS-1$
+                + QUOTE + "\n"); //$NON-NLS-1$
+        pw.write("    " + "version=" + QUOTE + "2.0" + QUOTE + ">\n\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+        pw.write("</faces-config>\n"); //$NON-NLS-1$
+    }
+
+}
diff --git a/jsf/plugins/org.eclipse.jst.jsf.ui/plugin.xml b/jsf/plugins/org.eclipse.jst.jsf.ui/plugin.xml
index ff6fa97..6105f36 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.ui/plugin.xml
+++ b/jsf/plugins/org.eclipse.jst.jsf.ui/plugin.xml
@@ -56,6 +56,12 @@
      <wizard-pages action="jst.jsf.v12.install">
         <page class="org.eclipse.jst.jsf.ui.internal.project.facet.JSFFacetInstallPage"/>
      </wizard-pages>
+     <wizard-pages
+           action="jst.jsf.v20.install">
+        <page
+              class="org.eclipse.jst.jsf.ui.internal.project.facet.JSFFacetInstallPage">
+        </page>
+     </wizard-pages>
   </extension>  
   
   <extension point="org.eclipse.wst.sse.ui.editorConfiguration">