[199105] Servlet Filter wizard added
diff --git a/plugins/org.eclipse.jst.j2ee.navigator.ui/plugin.xml b/plugins/org.eclipse.jst.j2ee.navigator.ui/plugin.xml
index 76c5bf2..b81f280 100644
--- a/plugins/org.eclipse.jst.j2ee.navigator.ui/plugin.xml
+++ b/plugins/org.eclipse.jst.j2ee.navigator.ui/plugin.xml
@@ -624,6 +624,22 @@
 				</or>
 			</enablement>
 		</commonWizard>
+		<!-- New Filter -->
+		<commonWizard
+        menuGroupId="org.eclipse.wst.web.ui"
+        type="new"
+        wizardId="org.eclipse.jst.servlet.ui.internal.wizard.AddFilterWizard">
+			<enablement>
+				<or>
+					<instanceof
+						value="org.eclipse.jst.j2ee.webapplication.WebApp">
+					</instanceof>
+					<instanceof
+						value="org.eclipse.jst.j2ee.internal.war.ui.util.WebFiltersGroupItemProvider">
+					</instanceof>
+				</or>
+			</enablement>
+		</commonWizard>
 		<!-- New Listener -->
 		<commonWizard
         menuGroupId="org.eclipse.wst.web.ui"
diff --git a/plugins/org.eclipse.jst.j2ee.web/property_files/web.properties b/plugins/org.eclipse.jst.j2ee.web/property_files/web.properties
index 0232cee..8b008a9 100644
--- a/plugins/org.eclipse.jst.j2ee.web/property_files/web.properties
+++ b/plugins/org.eclipse.jst.j2ee.web/property_files/web.properties
@@ -15,13 +15,10 @@
 ERR_DUPLICATED_INIT_PARAMETER=Duplicated init parameters.
 ERR_DUPLICATED_URL_MAPPING=Duplicated URL mappings.
 
-ERR_SERVLET_MAPPING_URL_PATTERN_EMPTY=The servlet mapping url pattern cannot be empty.
-ERR_SERVLET_MAPPING_URL_PATTERN_EXIST=The servlet mapping url pattern "{0}" already exists.
+ERR_SERVLET_MAPPING_URL_PATTERN_EMPTY=The servlet mapping URL pattern cannot be empty.
+ERR_SERVLET_MAPPING_URL_PATTERN_EXIST=The servlet mapping URL pattern "{0}" already exists.
 ERR_SERVLET_MAPPING_URL_PATTERN_INVALID="{0}" is unresolvable URL mapping. URL mappings should start with "/" or "*.".
-KEY_3=The filter mapping url pattern cannot be empty.
-KEY_4=The filter mapping url pattern "{0}" already exists.
-KEY_5=The filter mapping servlet cannot be empty.
-KEY_6=The filter init param name cannot be empty.
+ERR_FILTER_MAPPING_EMPTY=The filter mappings cannot be empty. You need at least one URL pattern or Servlet class. 
 ERR_FILTER_PARAMETER_NAME_EXIST=The filter initialization parameter name already exists.
 ERR_FILTER_MAPPING_SERVLET_EXIST=The filter mapping servlet "{0}" already exists.
 ERR_FILTER_MAPPING_SERVLET_DISPATCHER_TYPES_EMPTY=The dispatcher types cannot be empty.
@@ -29,7 +26,7 @@
 ERR_SERVLET_NAME_EXIST=The servlet name already exists.
 ERR_SERVLET_DISPLAY_NAME_EXIST=The servlet display name already exists.
 ERR_SERVLET_CLASS_NAME_USED=The class is already associated with other servlet.
-ERR_SERVLET_MAPPING_URL_PATTERN_EMPTY=The servlet mapping url pattern cannot be empty.
+ERR_SERVLET_MAPPING_URL_PATTERN_EMPTY=The servlet mapping URL pattern cannot be empty.
 ERR_SERVLET_MAPPING_URL_PATTERN_EXIST=The servlet URL mapping pattern already exists.
 ERR_SERVLET_MAPPING_SERVLET_NOT_EXIST=The servlet does not exist.
 ERR_SERVLET_PARAMETER_NAME_EMPTY=The servlet initialization parameter name cannot be empty.
diff --git a/plugins/org.eclipse.jst.j2ee.web/property_files/webedit.properties b/plugins/org.eclipse.jst.j2ee.web/property_files/webedit.properties
index 1859b15..831fe7e 100644
--- a/plugins/org.eclipse.jst.j2ee.web/property_files/webedit.properties
+++ b/plugins/org.eclipse.jst.j2ee.web/property_files/webedit.properties
@@ -692,6 +692,8 @@
 Define_Authorization_Constraint_1=Define Authorization Constraint
 Choose_a_servlet__1=Choose a servlet:
 Matching_servlets__2=Matching servlets:
+Choose_a_filter__1=Choose a filter:
+Matching_filters__2=Matching filters:
 Qualifier__3=Qualifier:
 Add_or_Remove_EJB_Local_Reference_1=Add or Remove EJB Local Reference
 Add_or_Remove_Markup_Language_2=Add or Remove Markup Language
diff --git a/plugins/org.eclipse.jst.j2ee.web/templates/filter.javajet b/plugins/org.eclipse.jst.j2ee.web/templates/filter.javajet
new file mode 100644
index 0000000..4e67e60
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.web/templates/filter.javajet
@@ -0,0 +1,48 @@
+<%@ jet package="org.eclipse.jst.j2ee.web" 
+	imports="org.eclipse.jst.j2ee.internal.web.operations.* java.util.* " 
+	class="FilterTemplate" 
+%><%@ include file="filterHeader.template" %>
+
+<%if (model.isPublic()) {%>public<%}%> <%if (model.isAbstract()) {%>abstract <%}%><%if (model.isFinal()) {%>final <%}
+%>class <%=model.getFilterClassName()%><%
+String superClass = model.getSuperclassName();
+if (superClass.trim().length() > 0) {%> extends <%=superClass%><%}%>
+<%
+ List interfaces = model.getInterfaces(); 
+ if (interfaces.size()>0) {%> implements <% }
+ for (int i=0; i<interfaces.size(); i++) {
+   String INTERFACE = (String) interfaces.get(i);
+   if (i>0) { %>, <%}%><%=INTERFACE%><%}%> {
+	<% if (model.shouldGenDestroy()) { %>	
+	/* (non-Javadoc)
+	 * @see javax.servlet.Filter#destroy()
+	 */
+	public void destroy() {
+		// TODO Auto-generated method stub
+		
+	} <% } %> <% if (model.shouldGenDoFilter()) { %>
+	
+	/* (non-Javadoc)
+	 * @see javax.servlet.Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
+	 */
+	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+		// TODO Auto-generated method stub
+		
+	} <% } %> 	<% if (model.shouldGenInit()) { %>
+	
+	/* (non-Javadoc)
+	 * @see javax.servlet.Filter#init(FilterConfig)
+	 */
+	public void init(FilterConfig fConfig) throws ServletException {
+		// TODO Auto-generated method stub
+		
+	} <% } %>  <% if (model.shouldGenToString()) { %>
+	
+	/* (non-Javadoc)
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString() {
+		// TODO Auto-generated method stub
+		return super.toString();
+	} <% } %>
+}
diff --git a/plugins/org.eclipse.jst.j2ee.web/templates/filterHeader.template b/plugins/org.eclipse.jst.j2ee.web/templates/filterHeader.template
new file mode 100644
index 0000000..2fbdd81
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.web/templates/filterHeader.template
@@ -0,0 +1,18 @@
+<%@ jet package="org.eclipse.jst.j2ee.web" 
+	imports="org.eclipse.jst.j2ee.internal.web.operations.* java.util.* " 
+	class="FilterTemplate" 
+%>
+<% CreateFilterTemplateModel model = (CreateFilterTemplateModel) argument; 
+if (model.getJavaPackageName()!=null && model.getJavaPackageName()!="") { %>package <%=model.getJavaPackageName()%>;<%}%>
+
+import java.io.IOException;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+/**
+ * Filter implementation class for Filter: <%=model.getFilterClassName()%>
+ *
+ */
\ No newline at end of file
diff --git a/plugins/org.eclipse.jst.j2ee.web/templates/listener.javajet b/plugins/org.eclipse.jst.j2ee.web/templates/listener.javajet
index 4ac97cb..6fe41cb 100644
--- a/plugins/org.eclipse.jst.j2ee.web/templates/listener.javajet
+++ b/plugins/org.eclipse.jst.j2ee.web/templates/listener.javajet
@@ -40,14 +40,14 @@
    if (i > 0) { %>, <% } %><%=INTERFACE%><% } %> { 
    
 <% if (model.implementServletContextListener()) { %>
-	/**
+	/* (non-Javadoc)
 	 * @see javax.servlet.ServletContextListener#contextDestroyed(ServletContextEvent)
 	 */
 	public void contextDestroyed(ServletContextEvent arg0) {
 		// TODO Auto-generated method stub
 	}
 	
-	/**
+	/* (non-Javadoc)
 	 * @see javax.servlet.ServletContextListener#contextInitialized(ServletContextEvent)
 	 */
 	public void contextInitialized(ServletContextEvent arg0) {
@@ -56,21 +56,21 @@
 	
 <% }
  if (model.implementServletContextAttributeListener()) { %>
-	/**
+	/* (non-Javadoc)
 	 * @see javax.servlet.ServletContextAttributeListener#attributeAdded(ServletContextAttributeEvent)
 	 */
 	public void attributeAdded(ServletContextAttributeEvent arg0) {
 		// TODO Auto-generated method stub
 	}
 
-	/**
+	/* (non-Javadoc)
 	 * @see javax.servlet.ServletContextAttributeListener#attributeRemoved(ServletContextAttributeEvent)
 	 */
 	public void attributeRemoved(ServletContextAttributeEvent arg0) {
 		// TODO Auto-generated method stub
 	}
 	
-	/**
+	/* (non-Javadoc)
 	 * @see javax.servlet.ServletContextAttributeListener#attributeReplaced(ServletContextAttributeEvent)
 	 */
 	public void attributeReplaced(ServletContextAttributeEvent arg0) {
@@ -79,14 +79,14 @@
 	
 <% }
  if (model.implementHttpSessionListener()) { %>
-	/**
+	/* (non-Javadoc)
 	 * @see javax.servlet.http.HttpSessionListener#sessionCreated(HttpSessionEvent)
 	 */
 	public void sessionCreated(HttpSessionEvent arg0) {
 		// TODO Auto-generated method stub
 	}
 
-	/**
+	/* (non-Javadoc)
 	 * @see javax.servlet.http.HttpSessionListener#sessionDestroyed(HttpSessionEvent)
 	 */
 	public void sessionDestroyed(HttpSessionEvent arg0) {
@@ -95,21 +95,21 @@
 	
 <% }
  if (model.implementHttpSessionAttributeListener()) { %>
-	/**
+	/* (non-Javadoc)
 	 * @see javax.servlet.http.HttpSessionAttributeListener#attributeAdded(HttpSessionBindingEvent)
 	 */
 	public void attributeAdded(HttpSessionBindingEvent arg0) {
 		// TODO Auto-generated method stub
 	}
 
-	/**
+	/* (non-Javadoc)
 	 * @see javax.servlet.http.HttpSessionAttributeListener#attributeRemoved(HttpSessionBindingEvent)
 	 */
 	public void attributeRemoved(HttpSessionBindingEvent arg0) {
 		// TODO Auto-generated method stub
 	}
 
-	/**
+	/* (non-Javadoc)
 	 * @see javax.servlet.http.HttpSessionAttributeListener#attributeReplaced(HttpSessionBindingEvent)
 	 */
 	public void attributeReplaced(HttpSessionBindingEvent arg0) {
@@ -118,14 +118,14 @@
 	
 <% }
  if (model.implementHttpSessionActivationListener()) { %>
-	/**
+	/* (non-Javadoc)
 	 * @see javax.servlet.http.HttpSessionActivationListener#sessionDidActivate(HttpSessionEvent)
 	 */
 	public void sessionDidActivate(HttpSessionEvent arg0) {
 		// TODO Auto-generated method stub
 	}
 
-	/**
+	/* (non-Javadoc)
 	 * @see javax.servlet.http.HttpSessionActivationListener#sessionWillPassivate(HttpSessionEvent)
 	 */
 	public void sessionWillPassivate(HttpSessionEvent arg0) {
@@ -134,14 +134,14 @@
 	
 <% }
  if (model.implementHttpSessionBindingListener()) { %>
-	/**
+	/* (non-Javadoc)
 	 * @see javax.servlet.http.HttpSessionBindingListener#valueBound(HttpSessionBindingEvent)
 	 */
 	public void valueBound(HttpSessionBindingEvent arg0) {
 		// TODO Auto-generated method stub
 	}
 
-	/**
+	/* (non-Javadoc)
 	 * @see javax.servlet.http.HttpSessionBindingListener#valueUnbound(HttpSessionBindingEvent)
 	 */
 	public void valueUnbound(HttpSessionBindingEvent arg0) {
@@ -150,14 +150,14 @@
 	
 <% }
  if (model.implementServletRequestListener()) { %>
-	/**
+	/* (non-Javadoc)
 	 * @see javax.servlet.ServletRequestListener#requestDestroyed(ServletRequestEvent)
 	 */
 	public void requestDestroyed(ServletRequestEvent arg0) {
 		// TODO Auto-generated method stub
 	}
 
-	/**
+	/* (non-Javadoc)
 	 * @see javax.servlet.ServletRequestListener#requestInitialized(ServletRequestEvent)
 	 */
 	public void requestInitialized(ServletRequestEvent arg0) {
@@ -166,21 +166,21 @@
 	
 <% }
  if (model.implementServletRequestAttributeListener()) { %>
-	/**
+	/* (non-Javadoc)
 	 * @see javax.servlet.ServletRequestAttributeListener#attributeAdded(ServletRequestAttributeEvent)
 	 */
 	public void attributeAdded(ServletRequestAttributeEvent arg0) {
 		// TODO Auto-generated method stub
 	}
 
-	/**
+	/* (non-Javadoc)
 	 * @see javax.servlet.ServletRequestAttributeListener#attributeRemoved(ServletRequestAttributeEvent)
 	 */
 	public void attributeRemoved(ServletRequestAttributeEvent arg0) {
 		// TODO Auto-generated method stub
 	}
 	
-	/**
+	/* (non-Javadoc)
 	 * @see javax.servlet.ServletRequestAttributeListener#attributeReplaced(ServletRequestAttributeEvent)
 	 */
 	public void attributeReplaced(ServletRequestAttributeEvent arg0) {
diff --git a/plugins/org.eclipse.jst.j2ee.web/templates/listenerHeader.template b/plugins/org.eclipse.jst.j2ee.web/templates/listenerHeader.template
index e675dc5..c4963d5 100644
--- a/plugins/org.eclipse.jst.j2ee.web/templates/listenerHeader.template
+++ b/plugins/org.eclipse.jst.j2ee.web/templates/listenerHeader.template
@@ -39,5 +39,4 @@
 /**
  * Application Lifecycle Listener implementation class <%=model.getListenerClassName()%>
  *
- */
- 
\ No newline at end of file
+ */
\ No newline at end of file
diff --git a/plugins/org.eclipse.jst.j2ee.web/templates/servlet.javajet b/plugins/org.eclipse.jst.j2ee.web/templates/servlet.javajet
index 0179fdc..6ceb75e 100644
--- a/plugins/org.eclipse.jst.j2ee.web/templates/servlet.javajet
+++ b/plugins/org.eclipse.jst.j2ee.web/templates/servlet.javajet
@@ -11,7 +11,7 @@
  for (int i=0; i<interfaces.size(); i++) {
    String INTERFACE = (String) interfaces.get(i);
    if (i>0) { %>, <%}%><%=INTERFACE%><%}%> {
-   static final long serialVersionUID = 1L;
+	static final long serialVersionUID = 1L;
    
     /* (non-Java-doc)
 	 * @see javax.servlet.http.HttpServlet#HttpServlet()
diff --git a/plugins/org.eclipse.jst.j2ee.web/templates/servletHeader.template b/plugins/org.eclipse.jst.j2ee.web/templates/servletHeader.template
index b6590a3..1334358 100644
--- a/plugins/org.eclipse.jst.j2ee.web/templates/servletHeader.template
+++ b/plugins/org.eclipse.jst.j2ee.web/templates/servletHeader.template
@@ -40,4 +40,4 @@
  *    value="<%=value%>" <% if (description !=null && description!="") { %>

  *    description="<%=description%>" <%} %>

  * <% } } } %>

- */ 
\ No newline at end of file
+ */
\ No newline at end of file
diff --git a/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/AddFilterOperation.java b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/AddFilterOperation.java
new file mode 100644
index 0000000..34d8600
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/AddFilterOperation.java
@@ -0,0 +1,448 @@
+package org.eclipse.jst.j2ee.internal.web.operations;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.*;
+import org.eclipse.jem.util.UIContextDetermination;
+import org.eclipse.jem.util.emf.workbench.ProjectUtilities;
+import org.eclipse.jem.util.logger.proxy.Logger;
+import org.eclipse.jst.j2ee.internal.J2EEVersionConstants;
+import org.eclipse.jst.j2ee.internal.common.operations.INewJavaClassDataModelProperties;
+import org.eclipse.jst.j2ee.model.IModelProvider;
+import org.eclipse.jst.j2ee.model.ModelProviderManager;
+import org.eclipse.jst.j2ee.webapplication.*;
+import org.eclipse.jst.javaee.core.DisplayName;
+import org.eclipse.jst.javaee.core.JavaeeFactory;
+import org.eclipse.jst.javaee.core.UrlPatternType;
+import org.eclipse.jst.javaee.web.WebFactory;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.wst.common.componentcore.internal.operation.ArtifactEditProviderOperation;
+import org.eclipse.wst.common.componentcore.internal.operation.IArtifactEditOperationDataModelProperties;
+import org.eclipse.wst.common.frameworks.datamodel.AbstractDataModelOperation;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
+
+/**
+ * This class, AddFilter Operation is a IDataModelOperation following the
+ * IDataModel wizard and operation framework.
+ * 
+ * @see org.eclipse.wst.common.frameworks.datamodel.IDataModelOperation
+ * @see org.eclipse.wst.common.frameworks.datamodel.IDataModelProvider
+ * 
+ * This operation subclasses the ArtifactEditProviderOperation so the changes
+ * made to the deployment descriptor models are saved to the artifact edit
+ * model.
+ * @see org.eclipse.wst.common.componentcore.internal.operation.ArtifactEditProviderOperation
+ * 
+ * It is the operation which should be used when adding a new filter to a web
+ * app. This uses the NewFilterClassDataModelProvider to retrieve properties set by the
+ * user in order to create the custom filter.
+ * @see org.eclipse.jst.j2ee.internal.web.operations.NewFilterClassDataModelProvider
+ * 
+ * This operation will add the metadata necessary into the web deployment descriptor. 
+ * To actually create the java class for the filter, the operation uses the NewFilterClassOperation. 
+ * The NewFilterClassOperation shares the same data model provider.
+ * @see org.eclipse.jst.j2ee.internal.web.operations.NewFilterClassOperation
+ * 
+ * Clients may subclass this operation to provide their own behavior on filter
+ * creation. The execute method can be extended to do so. Also,
+ * generateFilterMetaData and creteFilterClass are exposed.
+ * 
+ * The use of this class is EXPERIMENTAL and is subject to substantial changes.
+ */
+public class AddFilterOperation extends AbstractDataModelOperation implements
+		IArtifactEditOperationDataModelProperties {
+
+	private IModelProvider provider = null;
+
+	/**
+	 * This is the constructor which should be used when creating the operation.
+	 * It will not accept null parameter. It will not return null.
+	 * 
+	 * @see ArtifactEditProviderOperation#ArtifactEditProviderOperation(IDataModel)
+	 * 
+	 * @param dataModel
+	 * @return AddFilterOperation
+	 */
+	public AddFilterOperation(IDataModel dataModel) {
+		super(dataModel);
+		provider = ModelProviderManager.getModelProvider(getTargetProject());
+	}
+
+	/**
+	 * Subclasses may extend this method to add their own actions during
+	 * execution. The implementation of the execute method drives the running of
+	 * the operation. This implementation will create the filter class, and
+	 * then it will create the filter metadata for the web deployment descriptor. 
+	 * This method will accept null as a parameter.
+	 * 
+	 * @see org.eclipse.core.commands.operations.AbstractOperation#execute(org.eclipse.core.runtime.IProgressMonitor,
+	 *      org.eclipse.core.runtime.IAdaptable)
+	 * @see AddFilterOperation#createFilterClass()
+	 * @see AddFilterOperation#generateFilterMetaData(NewFilterClassDataModel,
+	 *      String)
+	 * 
+	 * @param monitor
+	 *            IProgressMonitor
+	 * @param info
+	 *            IAdaptable
+	 * @throws CoreException
+	 * @throws InterruptedException
+	 * @throws InvocationTargetException
+	 */
+	public IStatus doExecute(IProgressMonitor monitor, IAdaptable info)
+			throws ExecutionException {
+		// Retrieve values set in the newfilterclass data model
+	    boolean useExisting = model.getBooleanProperty(INewFilterClassDataModelProperties.USE_EXISTING_CLASS);
+		String qualifiedClassName = model.getStringProperty(INewJavaClassDataModelProperties.CLASS_NAME);
+
+		// create the java class
+		if (!useExisting) qualifiedClassName = createFilterClass();
+
+		// If the filter is not annotated, generate the filter metadata for
+		// the DD
+		generateFilterMetaData(model, qualifiedClassName);
+		return OK_STATUS;
+	}
+
+	/**
+	 * Subclasses may extend this method to add their own creation of the actual
+	 * filter java class. This implementation uses the NewFilterClassOperation
+	 * which is a subclass of the NewJavaClassOperation. The
+	 * NewFilterClassOperation will use the same
+	 * NewFilterClassDataModelProvider to retrieve the properties in order to
+	 * create the java class accordingly. This method will not return null.
+	 * 
+	 * @see NewFilterClassOperation
+	 * @see org.eclipse.jst.j2ee.internal.common.operations.NewJavaClassOperation
+	 * @see NewFilterClassDataModelProvider
+	 * 
+	 * @return String qualified filter classname
+	 */
+	protected String createFilterClass() {
+		// Create filter java class file using the NewFilterClassOperation.
+		// The same data model is shared.
+		NewFilterClassOperation op = new NewFilterClassOperation(model);
+		try {
+			op.execute(new NullProgressMonitor(), null);
+		} catch (Exception e) {
+			Logger.getLogger().log(e);
+		}
+		// Return the qualified classname of the newly created java class for
+		// the fitler
+		return getQualifiedClassName();
+	}
+
+	/**
+	 * This method will return the qualified java class name as specified by the
+	 * class name and package name properties in the data model. This method
+	 * should not return null.
+	 * 
+	 * @see INewJavaClassDataModelProperties#CLASS_NAME
+	 * @see INewJavaClassDataModelProperties#JAVA_PACKAGE
+	 * 
+	 * @return String qualified java classname
+	 */
+	public final String getQualifiedClassName() {
+		// Use the java package name and unqualified class name to create a
+		// qualified java class name
+		String packageName = model
+				.getStringProperty(INewJavaClassDataModelProperties.JAVA_PACKAGE);
+		String className = model
+				.getStringProperty(INewJavaClassDataModelProperties.CLASS_NAME);
+		// Ensure the class is not in the default package before adding package
+		// name to qualified name
+		if (packageName != null && packageName.trim().length() > 0)
+			return packageName + "." + className; //$NON-NLS-1$
+		return className;
+	}
+
+	/**
+	 * Subclasses may extend this method to add their own generation steps for
+	 * the creation of the metadata for the web deployment descriptor. This
+	 * implementation uses the J2EE models to create the Filter model instance,
+	 * any init params specified, and any filter mappings. It then adds these
+	 * to the web application model. This will then be written out to the
+	 * deployment descriptor file. This method does not accept null parameters.
+	 * 
+	 * @see Filter
+	 * @see AddFilterOperation#createFilter(String)
+	 * @see AddFilterOperation#setUpInitParams(List, Filter)
+	 * @see AddFilterOperation#setUpURLMappings(List, Filter)
+	 * 
+	 * @param aModel
+	 * @param qualifiedClassName
+	 */
+	protected void generateFilterMetaData(IDataModel aModel,
+			String qualifiedClassName) {
+		// Set up the filter modelled object
+		Object filter = createFilter(qualifiedClassName);
+
+		// Set up the InitParams if any
+		List initParamList = 
+		    (List) aModel.getProperty(INewFilterClassDataModelProperties.INIT_PARAM);
+		if (initParamList != null)
+			setUpInitParams(initParamList, filter);
+
+		// Set up the filter URL mappings if any
+		 List urlMappingList = 
+		     (List) aModel.getProperty(INewFilterClassDataModelProperties.URL_MAPPINGS);
+
+		 // Set up the filter servlet name mappings if any
+         List srvNameMappingList = 
+             (List) aModel.getProperty(INewFilterClassDataModelProperties.SERVLET_MAPPINGS);
+         if ((urlMappingList != null) || (srvNameMappingList != null))
+             setUpMappings(urlMappingList, srvNameMappingList, filter);
+	}
+
+	/**
+	 * This method is intended for private use only. This method is used to
+	 * create the filter modeled object, to set any parameters specified in
+	 * the data model, and then to add the filter instance to the web
+	 * application model. This method does not accept null parameters. It will
+	 * not return null.
+	 * 
+	 * @see AddFilterOperation#generateFilterMetaData(NewFilterClassDataModel,
+	 *      String)
+	 * @see WebapplicationFactory#createFilter()
+	 * @see Filter
+	 * 
+	 * @param qualifiedClassName
+	 * @return Filter instance
+	 */
+	/**
+	 * @param qualifiedClassName
+	 * @return
+	 */
+	private Object createFilter(String qualifiedClassName) {
+		// Get values from data model
+		String displayName = 
+		    model.getStringProperty(INewFilterClassDataModelProperties.DISPLAY_NAME);
+		String description = 
+		    model.getStringProperty(INewFilterClassDataModelProperties.DESCRIPTION);
+
+		// Create the filter instance and set up the parameters from data model
+		Object modelObject = provider.getModelObject();
+		if (modelObject instanceof org.eclipse.jst.j2ee.webapplication.WebApp) {
+			Filter filter = WebapplicationFactory.eINSTANCE.createFilter();
+			filter.setName(displayName);
+			filter.setDisplayName(displayName);
+			filter.setDescription(description);
+			filter.setFilterClassName(qualifiedClassName);
+	
+
+			// Add the filter to the web application model
+			WebApp webApp = (WebApp) modelObject;
+			webApp.getFilters().add(filter);
+			return filter;
+		} else if (modelObject instanceof org.eclipse.jst.javaee.web.WebApp) {
+			org.eclipse.jst.javaee.web.WebApp webApp = (org.eclipse.jst.javaee.web.WebApp) modelObject;
+			org.eclipse.jst.javaee.web.Filter filter = WebFactory.eINSTANCE.createFilter();
+			DisplayName displayNameObj = JavaeeFactory.eINSTANCE.createDisplayName();
+            displayNameObj.setValue(displayName);
+            filter.getDisplayNames().add(displayNameObj);
+			filter.setFilterName(displayName);
+			filter.setFilterClass(qualifiedClassName);
+			if (webApp != null) {
+				webApp.getFilters().add(filter);
+			}
+			// Should be return Filter's instance
+			return filter;
+		}
+		// Return the filter instance
+		return null;
+	}
+
+	/**
+	 * This method is intended for internal use only. This is used to create any
+	 * init params for the new filter metadata. It will not accept null
+	 * parameters. The init params are set on the filter modeled object.
+	 * 
+	 * @see AddFilterOperation#generateFilterMetaData(NewFilterClassDataModel,
+	 *      String)
+	 * @see WebapplicationFactory#createInitParam()
+	 * 
+	 * @param initParamList
+	 * @param filter
+	 */
+	private void setUpInitParams(List initParamList, Object filterObj) {
+		// Get the web app instance from the data model
+		Object modelObject = provider.getModelObject();
+		if (modelObject instanceof org.eclipse.jst.j2ee.webapplication.WebApp) {
+			WebApp webApp = (WebApp) modelObject;
+			Filter filter = (Filter) filterObj;
+
+			// If J2EE 1.4, add the param value and description info instances
+			// to the filter init params
+			if (webApp.getJ2EEVersionID() >= J2EEVersionConstants.J2EE_1_4_ID) {
+				for (int iP = 0; iP < initParamList.size(); iP++) {
+					String[] stringArray = (String[]) initParamList.get(iP);
+					// Create 1.4 common param value
+					InitParam param = WebapplicationFactory.eINSTANCE.createInitParam();
+					param.setParamName(stringArray[0]);
+					param.setParamValue(stringArray[1]);
+					param.setDescription(stringArray[2]);
+					// Set the param to the filter model list of init params
+					filter.getInitParams().add(param);
+				}
+			}
+			// If J2EE 1.2 or 1.3, use the filter specific init param instances
+			else {
+				for (int iP = 0; iP < initParamList.size(); iP++) {
+					String[] stringArray = (String[]) initParamList.get(iP);
+					// Create the web init param
+					InitParam ip = WebapplicationFactory.eINSTANCE.createInitParam();
+					// Set the param name
+					ip.setParamName(stringArray[0]);
+					// Set the param value
+					ip.setParamValue(stringArray[1]);
+					// Set the param description
+					ip.setDescription(stringArray[2]);
+					// Add the init param to the filter model list of params
+					filter.getInitParams().add(ip);
+				}
+			}
+		} else if (modelObject instanceof org.eclipse.jst.javaee.web.WebApp) {
+			org.eclipse.jst.javaee.web.Filter filter = (org.eclipse.jst.javaee.web.Filter) filterObj;
+
+			for (int iP = 0; iP < initParamList.size(); iP++) {
+				String[] stringArray = (String[]) initParamList.get(iP);
+				// Create 1.4 common param value
+				org.eclipse.jst.javaee.core.ParamValue param = 
+				    JavaeeFactory.eINSTANCE.createParamValue();
+				param.setParamName(stringArray[0]);
+				param.setParamValue(stringArray[1]);
+
+				org.eclipse.jst.javaee.core.Description descriptionObj = 
+				    JavaeeFactory.eINSTANCE.createDescription();
+				descriptionObj.setValue(stringArray[2]);
+				// Set the description on the param
+				param.getDescriptions().add(descriptionObj);
+				// Add the param to the filter model list of init params
+				filter.getInitParams().add(param);
+			}
+		}
+	}
+
+	/**
+	 * This method is intended for internal use only. This method is used to
+	 * create the filter mapping modelled objects so the metadata for the
+	 * filter mappings is store in the web deployment descriptor. This method
+	 * will not accept null parameters. The filter mappings are added to the
+	 * web application modeled object.
+	 * 
+	 * @see AddFilterOperation#generateFilterMetaData(NewFilterClassDataModel,
+	 *      String)
+	 * @see WebapplicationFactory#createFilterMapping()
+	 * 
+	 * @param urlMappingList
+	 * @param filter
+	 */
+	private void setUpMappings(List urlMappingList, List servletMappingList, Object filterObj) {
+		// Get the web app modelled object from the data model
+		// WebApp webApp = (WebApp) artifactEdit.getContentModelRoot();
+		Object modelObject = provider.getModelObject();
+
+		// Create the filter mappings if any
+		if (modelObject instanceof org.eclipse.jst.j2ee.webapplication.WebApp) {
+			WebApp webApp = (WebApp) modelObject;
+			Filter filter = (Filter) filterObj;
+			if (urlMappingList != null) for (int iM = 0; iM < urlMappingList.size(); iM++) {
+				String[] stringArray = (String[]) urlMappingList.get(iM);
+				// Create the filter mapping instance from the web factory
+				FilterMapping mapping = WebapplicationFactory.eINSTANCE.createFilterMapping();
+				// Set the filter
+				mapping.setFilter(filter);
+				//mapping.setName(filter.getName()); //TODO: icobgr: to check the name
+				// Set the URL pattern to map the filter to
+				mapping.setUrlPattern(stringArray[0]);
+				// Add the filter mapping to the web application modelled list
+				webApp.getFilterMappings().add(mapping);
+			}
+            if (servletMappingList != null) for (int iM = 0; iM < servletMappingList.size(); iM++) {
+                String[] stringArray = (String[]) servletMappingList.get(iM);
+                // Create the filter mapping instance from the web factory
+                FilterMapping mapping = WebapplicationFactory.eINSTANCE.createFilterMapping();
+                // Set the filter
+                mapping.setFilter(filter);
+                //mapping.setName(filter.getName()); //TODO: icobgr: to check the name
+                // Set the URL pattern to map the filter to
+                mapping.setServletName(stringArray[0]);
+                // Add the filter mapping to the web application modelled list
+                webApp.getFilterMappings().add(mapping);
+            }
+		} else if (modelObject instanceof org.eclipse.jst.javaee.web.WebApp) {
+			org.eclipse.jst.javaee.web.WebApp webApp = (org.eclipse.jst.javaee.web.WebApp) modelObject;
+			org.eclipse.jst.javaee.web.Filter filter = (org.eclipse.jst.javaee.web.Filter) filterObj;
+
+            // Create the filter mapping instance from the web factory
+            org.eclipse.jst.javaee.web.FilterMapping mapping = null;
+			// Create the filter mappings if any
+			if (urlMappingList != null && urlMappingList.size() > 0) {
+			    mapping = WebFactory.eINSTANCE.createFilterMapping();
+			    mapping.setFilterName(filter.getFilterName());
+				for (int i = 0; i < urlMappingList.size(); i++) {
+					String[] stringArray = (String[]) urlMappingList.get(i);
+					// Set the URL pattern to map the filter to
+					UrlPatternType url = JavaeeFactory.eINSTANCE.createUrlPatternType();
+					url.setValue(stringArray[0]);
+					mapping.getUrlPatterns().add(url);
+				}
+			}
+			if (servletMappingList != null && servletMappingList.size() > 0) {
+			    if (mapping == null) {
+			        mapping = WebFactory.eINSTANCE.createFilterMapping();
+			        mapping.setFilterName(filter.getFilterName());
+			    }
+			    for (int i = 0; i < servletMappingList.size(); i++) {
+			        String[] servletName = (String[]) servletMappingList.get(i);
+			        mapping.getServletNames().add(servletName[0]);
+			    }
+			}
+            // Add the filter mapping to the web application model list
+			if (mapping != null) {
+			    webApp.getFilterMappings().add(mapping);
+			}
+		}
+	}
+
+	public IProject getTargetProject() {
+		String projectName = model
+				.getStringProperty(IArtifactEditOperationDataModelProperties.PROJECT_NAME);
+		return ProjectUtilities.getProject(projectName);
+	}
+
+	@Override
+	public IStatus execute(final IProgressMonitor monitor, final IAdaptable info)
+			throws ExecutionException {
+		Runnable runnable = null;
+		try {
+			Object ctx = null;
+			if (UIContextDetermination.getCurrentContext() == UIContextDetermination.UI_CONTEXT) {
+				Display display = Display.getCurrent();
+				if (display != null)
+					ctx = display.getActiveShell();
+			}
+
+			if (provider.validateEdit(null, ctx).isOK()) {
+				runnable = new Runnable() {
+
+					public void run() {
+						try {
+							doExecute(monitor, info);
+						} catch (ExecutionException e) {
+							e.printStackTrace();
+						}
+					}
+				};
+				provider.modify(runnable, null);
+			}
+			// return doExecute(monitor, info);
+			return Status.CANCEL_STATUS;
+		} finally {
+
+		}
+	}
+}
diff --git a/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/CreateFilterTemplateModel.java b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/CreateFilterTemplateModel.java
new file mode 100644
index 0000000..713cb0a
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/CreateFilterTemplateModel.java
@@ -0,0 +1,131 @@
+/*
+ * Created on Aug 6, 2004
+ */
+package org.eclipse.jst.j2ee.internal.web.operations;
+
+import java.util.List;
+
+import org.eclipse.jst.j2ee.internal.common.operations.INewJavaClassDataModelProperties;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
+
+public class CreateFilterTemplateModel {
+
+	IDataModel dataModel = null;
+	public static final String INIT = "init"; //$NON-NLS-1$
+	public static final String TO_STRING = "toString"; //$NON-NLS-1$
+	public static final String DO_FILTER = "doFilter"; //$NON-NLS-1$
+	public static final String DESTROY = "destroy"; //$NON-NLS-1$
+
+	public static final int NAME = 0;
+	public static final int VALUE = 1;
+	public static final int DESCRIPTION = 2;
+
+	/**
+	 * Constructor
+	 */
+	public CreateFilterTemplateModel(IDataModel dataModel) {
+		super();
+		this.dataModel = dataModel;
+	}
+
+	public String getFilterClassName() {
+		return getProperty(INewJavaClassDataModelProperties.CLASS_NAME).trim();
+	}
+
+	public String getJavaPackageName() {
+		return getProperty(INewJavaClassDataModelProperties.JAVA_PACKAGE).trim();
+	}
+
+	public String getQualifiedJavaClassName() {
+		return getJavaPackageName() + "." + getFilterClassName(); //$NON-NLS-1$
+	}
+
+	public String getSuperclassName() {
+		return getProperty(INewJavaClassDataModelProperties.SUPERCLASS).trim();
+	}
+
+	public String getFilterName() {
+		return getProperty(INewJavaClassDataModelProperties.CLASS_NAME).trim();
+	}
+
+	public boolean isPublic() {
+		return dataModel.getBooleanProperty(INewJavaClassDataModelProperties.MODIFIER_PUBLIC);
+	}
+
+	public boolean isFinal() {
+		return dataModel.getBooleanProperty(INewJavaClassDataModelProperties.MODIFIER_FINAL);
+	}
+
+	public boolean isAbstract() {
+		return dataModel.getBooleanProperty(INewJavaClassDataModelProperties.MODIFIER_ABSTRACT);
+	}
+
+	protected String getProperty(String propertyName) {
+		return dataModel.getStringProperty(propertyName);
+	}
+
+	public boolean shouldGenInit() {
+		return implementImplementedMethod(INIT);
+	}
+
+	public boolean shouldGenToString() {
+		return implementImplementedMethod(TO_STRING);
+	}
+
+	public boolean shouldGenDoFilter() {
+		return implementImplementedMethod(DO_FILTER);
+	}
+
+	public boolean shouldGenDestroy() {
+		return implementImplementedMethod(DESTROY);
+	}
+
+	public List getInitParams() {
+		return (List) dataModel.getProperty(INewFilterClassDataModelProperties.INIT_PARAM);
+	}
+
+	public String getInitParam(int index, int type) {
+		List params = getInitParams();
+		if (index < params.size()) {
+			String[] stringArray = (String[]) params.get(index);
+			return stringArray[type];
+		}
+		return null;
+	}
+
+	public List getFilterMappings() {
+		return (List) dataModel.getProperty(INewFilterClassDataModelProperties.URL_MAPPINGS);
+	}
+
+	public String getFilterMapping(int index) {
+		List mappings = getFilterMappings();
+		if (index < mappings.size()) {
+			String[] map = (String[]) mappings.get(index);
+			return map[0];
+		}
+		return null;
+	}
+
+	public String getFilterDescription() {
+		return dataModel.getStringProperty(INewFilterClassDataModelProperties.DESCRIPTION);
+	}
+
+	public List getInterfaces() {
+		return (List) this.dataModel.getProperty(INewJavaClassDataModelProperties.INTERFACES);
+	}
+
+	protected boolean implementImplementedMethod(String methodName) {
+		if (dataModel.getBooleanProperty(INewJavaClassDataModelProperties.ABSTRACT_METHODS)) {
+			if (methodName.equals(INIT))
+				return dataModel.getBooleanProperty(INewFilterClassDataModelProperties.INIT);
+			else if (methodName.equals(TO_STRING))
+				return dataModel.getBooleanProperty(INewFilterClassDataModelProperties.TO_STRING);
+			else if (methodName.equals(DO_FILTER))
+				return dataModel.getBooleanProperty(INewFilterClassDataModelProperties.DO_FILTER);
+			else if (methodName.equals(DESTROY))
+				return dataModel.getBooleanProperty(INewFilterClassDataModelProperties.DESTROY);
+		}		
+		return false;
+	}
+
+}
diff --git a/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/INewFilterClassDataModelProperties.java b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/INewFilterClassDataModelProperties.java
new file mode 100644
index 0000000..a6700f0
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/INewFilterClassDataModelProperties.java
@@ -0,0 +1,62 @@
+package org.eclipse.jst.j2ee.internal.web.operations;
+
+import org.eclipse.jst.j2ee.application.internal.operations.IAnnotationsDataModel;
+import org.eclipse.jst.j2ee.internal.common.operations.INewJavaClassDataModelProperties;
+
+public interface INewFilterClassDataModelProperties extends INewJavaClassDataModelProperties, IAnnotationsDataModel {
+	/**
+	 * Optional, boolean property used to specify whether to generate the init method.
+	 * The default is false.
+	 */
+	public static final String INIT = "NewFilterClassDataModel.INIT"; //$NON-NLS-1$
+	
+	/**
+	 * Optional, boolean property used to specify whether to generate the destroy method.
+	 * The default is false.
+	 */
+	public static final String DESTROY = "NewFilterClassDataModel.DESTROY"; //$NON-NLS-1$
+	
+	/**
+	 * Optional, boolean property used to specify whether to generate the toString method.
+	 * The default is false.
+	 */
+	public static final String TO_STRING = "NewFilterClassDataModel.TO_STRING"; //$NON-NLS-1$
+	
+	/**
+	 * Optional, boolean property used to specify whether to generate the doFilter method.
+	 * The default is true.
+	 */
+	public static final String DO_FILTER = "NewFilterClassDataModel.DO_FILTER"; //$NON-NLS-1$
+	
+	/**
+	 * Optional, List property used to cache all the init params defined on the filter.
+	 */
+	public static final String INIT_PARAM = "NewFilterClassDataModel.INIT_PARAM"; //$NON-NLS-1$
+	
+	/**
+	 * Optional, List propety used to cache all the filter mappings for this filter on the web application.
+	 */
+	public static final String URL_MAPPINGS = "NewFilterClassDataModel.URL_MAPPINGS"; //$NON-NLS-1$
+
+	/**
+     * Optional, List propety used to cache all the filter mappings for this filter on the web application.
+     */
+    public static final String SERVLET_MAPPINGS = "NewFilterClassDataModel.SERVLET_MAPPINGS"; //$NON-NLS-1$
+
+	/**
+	 * Required, String property of the display name for the filter
+	 */
+	public static final String DISPLAY_NAME = "NewFilterClassDataModel.DISPLAY_NAME"; //$NON-NLS-1$
+	
+	/**
+	 * Optional, String property of the description info for the filter
+	 */
+	public static final String DESCRIPTION = "NewFilterClassDataModel.DESCRIPTION"; //$NON-NLS-1$
+	
+    /**
+	 * Optional, boolean property used to specify whether or not to gen a new java class.
+	 * The default is false.
+	 */
+	public static final String USE_EXISTING_CLASS = "NewFilterClassDataModel.USE_EXISTING_CLASS"; //$NON-NLS-1$
+	
+}
diff --git a/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/NewFilterClassDataModelProvider.java b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/NewFilterClassDataModelProvider.java
new file mode 100644
index 0000000..54ce623
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/NewFilterClassDataModelProvider.java
@@ -0,0 +1,499 @@
+package org.eclipse.jst.j2ee.internal.web.operations;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jst.j2ee.application.internal.operations.IAnnotationsDataModel;
+import org.eclipse.jst.j2ee.internal.common.operations.NewJavaClassDataModelProvider;
+import org.eclipse.jst.j2ee.model.IModelProvider;
+import org.eclipse.jst.j2ee.model.ModelProviderManager;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModelOperation;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModelProvider;
+import org.eclipse.wst.common.frameworks.internal.plugin.WTPCommonPlugin;
+
+public class NewFilterClassDataModelProvider extends NewJavaClassDataModelProvider implements INewFilterClassDataModelProperties {
+
+	/**
+	 * String array of the default, minimum required fully qualified Filter interfaces
+	 */
+	private final static String[] FILTER_INTERFACES = {"javax.servlet.Filter"}; //$NON-NLS-1$
+    
+    private final static String NON_ANNOTATED_TEMPLATE_DEFAULT = "filterNonAnnotated.javajet"; //$NON-NLS-1$
+
+	/**
+	 * The cache of all the interfaces the filter java class will implement.
+	 */
+	private List interfaceList;
+
+	private static boolean useAnnotations = false;
+
+	/**
+	 * Subclasses may extend this method to provide their own default operation for this data model
+	 * provider. This implementation uses the AddFilterOperation to drive the filter creation. It
+	 * will not return null.
+	 * 
+	 * @see IDataModel#getDefaultOperation()
+	 * 
+	 * @return IDataModelOperation AddFilterOperation
+	 */
+	public IDataModelOperation getDefaultOperation() {
+		return new AddFilterOperation(getDataModel());
+	}
+
+	/**
+	 * Subclasses may extend this method to provide their own determination of whether or not
+	 * certain properties should be disabled or enabled. This method does not accept null parameter.
+	 * It will not return null. This implementation makes sure annotation support is only allowed on
+	 * web projects of J2EE version 1.3 or higher.
+	 * 
+	 * @see org.eclipse.wst.common.frameworks.datamodel.IDataModelProvider#isPropertyEnabled(String)
+	 * @see IAnnotationsDataModel#USE_ANNOTATIONS
+	 * 
+	 * @param propertyName
+	 * @return boolean should property be enabled?
+	 */
+	public boolean isPropertyEnabled(String propertyName) {
+	    // Annotations should only be enabled on a valid j2ee project of version 1.3 or higher
+        if (USE_ANNOTATIONS.equals(propertyName)) {
+            if (getBooleanProperty(USE_EXISTING_CLASS) || !isAnnotationsSupported())
+                return false;
+            return true;
+        }
+		// Otherwise return super implementation
+		return super.isPropertyEnabled(propertyName);
+	}
+
+	/**
+	 * Subclasses may extend this method to add their own data model's properties as valid base
+	 * properties.
+	 * 
+	 * @see org.eclipse.wst.common.frameworks.datamodel.IDataModelProvider#getPropertyNames()
+	 */
+	public Set getPropertyNames() {
+		// Add filter specific properties defined in this data model
+		Set propertyNames = super.getPropertyNames();
+		propertyNames.add(INIT);
+		propertyNames.add(DESTROY);
+		propertyNames.add(TO_STRING);
+		propertyNames.add(DO_FILTER);
+		propertyNames.add(INIT_PARAM);
+		propertyNames.add(URL_MAPPINGS);
+        propertyNames.add(SERVLET_MAPPINGS);
+		propertyNames.add(USE_ANNOTATIONS);
+		propertyNames.add(DISPLAY_NAME);
+		propertyNames.add(DESCRIPTION);
+		propertyNames.add(USE_EXISTING_CLASS);
+		return propertyNames;
+	}
+
+	/**
+	 * Subclasses may extend this method to provide their own default values for any of the
+	 * properties in the data model hierarchy. This method does not accept a null parameter. It may
+	 * return null. This implementation sets annotation use to be true, and to generate a filter
+	 * with doFilter.
+	 * 
+	 * @see NewJavaClassDataModelProvider#getDefaultProperty(String)
+	 * @see IDataModelProvider#getDefaultProperty(String)
+	 * 
+	 * @param propertyName
+	 * @return Object default value of property
+	 */
+	public Object getDefaultProperty(String propertyName) {
+		if (propertyName.equals(DISPLAY_NAME)) {
+			String className = getStringProperty(CLASS_NAME);
+			int index = className.lastIndexOf("."); //$NON-NLS-1$
+			className = className.substring(index+1);
+			return className;
+		}
+        else if (propertyName.equals(DESTROY))
+            return Boolean.TRUE;
+		else if (propertyName.equals(DO_FILTER))
+            return Boolean.TRUE;
+        else if (propertyName.equals(INIT))
+            return Boolean.TRUE;
+		else if (propertyName.equals(URL_MAPPINGS))
+			return getDefaultUrlMapping();
+		else if (propertyName.equals(INTERFACES))
+			return getFilterInterfaces();
+		else if (propertyName.equals(SUPERCLASS))
+			return "";
+		else if (propertyName.equals(USE_EXISTING_CLASS))
+			return Boolean.FALSE;
+		// Otherwise check super for default value for property
+		return super.getDefaultProperty(propertyName);
+	}
+
+	/**
+	 * Returns the default Url Mapping depending upon the display name of the Filter
+	 * 
+	 * @return List containting the default Url Mapping
+	 */
+	private Object getDefaultUrlMapping() {
+		List urlMappings = null;
+		String text = (String) getProperty(DISPLAY_NAME);
+		if (text != null) {
+			urlMappings = new ArrayList();
+			urlMappings.add(new String[]{"/" + text}); //$NON-NLS-1$
+		}
+		return urlMappings;
+	}
+
+	/**
+	 * Subclasses may extend this method to add their own specific behaviour when a certain property
+	 * in the data model heirarchy is set. This method does not accept null for the property name,
+	 * but it will for propertyValue. It will not return null. It will return false if the set
+	 * fails. This implementation verifies the display name is set to the classname, that the
+	 * annotations is disabled/enabled properly, and that the target project name is determined from
+	 * the source folder setting.
+	 * 
+	 * @see org.eclipse.wst.common.frameworks.datamodel.IDataModelProvider#propertySet(String,
+	 *      Object)
+	 * 
+	 * @param propertyName
+	 * @param propertyValue
+	 * @return boolean was property set?
+	 */
+	public boolean propertySet(String propertyName, Object propertyValue) {
+		// If annotations is changed, notify an enablement change
+		if (propertyName.equals(USE_ANNOTATIONS)) {
+			useAnnotations = ((Boolean) propertyValue).booleanValue();
+			if (useAnnotations && !isAnnotationsSupported())
+				return true;
+			getDataModel().notifyPropertyChange(USE_ANNOTATIONS, IDataModel.ENABLE_CHG);
+		}
+		// If the source folder is changed, ensure we have the correct project name
+		if (propertyName.equals(SOURCE_FOLDER)) {
+			// Get the project name from the source folder name
+			String sourceFolder = (String) propertyValue;
+			int index = sourceFolder.indexOf(File.separator);
+			String projectName = sourceFolder;
+			if (index == 0)
+				projectName = sourceFolder.substring(1);
+			index = projectName.indexOf(File.separator);
+			if (index != -1) {
+				projectName = projectName.substring(0, index);
+				setProperty(PROJECT_NAME, projectName);
+			}
+		}
+		// Call super to set the property on the data model
+		boolean result = super.propertySet(propertyName, propertyValue);
+		// If class name is changed, update the display name to be the same
+		if (propertyName.equals(CLASS_NAME) && !getDataModel().isPropertySet(DISPLAY_NAME)) {
+			getDataModel().notifyPropertyChange(DISPLAY_NAME, IDataModel.DEFAULT_CHG);
+		}
+		// After the property is set, if project changed, update the nature and the annotations
+		// enablement
+		if (propertyName.equals(COMPONENT_NAME)) {
+			getDataModel().notifyPropertyChange(USE_ANNOTATIONS, IDataModel.ENABLE_CHG);
+		}
+		// After property is set, if annotations is set to true, update its value based on the new
+		// level of the project
+		if (getBooleanProperty(USE_ANNOTATIONS)) {
+			if (!isAnnotationsSupported())
+				setBooleanProperty(USE_ANNOTATIONS, false);
+		}
+		if (propertyName.equals(USE_EXISTING_CLASS)) {
+			getDataModel().notifyPropertyChange(USE_ANNOTATIONS, IDataModel.ENABLE_CHG);
+			if (((Boolean)propertyValue).booleanValue())
+				setProperty(USE_ANNOTATIONS,Boolean.FALSE);
+			setProperty(JAVA_PACKAGE, null);
+			setProperty(CLASS_NAME, null);
+		}
+		// Return whether property was set
+		return result;
+	}
+
+	/**
+	 * This method is used to determine if annotations should try to enable based on workspace settings
+	 * @return does any valid annotation provider or xdoclet handler exist
+	 */
+	//TODO add this method back in for defect 146696
+//	protected boolean isAnnotationProviderDefined() {
+//		boolean isControllerEnabled = AnnotationsControllerManager.INSTANCE.isAnyAnnotationsSupported();
+//		final String preferred = AnnotationPreferenceStore.getProperty(AnnotationPreferenceStore.ANNOTATIONPROVIDER);
+//		IAnnotationProvider annotationProvider = null;
+//		boolean isProviderEnabled = false;
+//		if (preferred != null) {
+//			try {
+//				annotationProvider = AnnotationUtilities.findAnnotationProviderByName(preferred);
+//			} catch (Exception ex) { 
+//				//Default
+//			}
+//			if (annotationProvider != null && annotationProvider.isValid())
+//				isProviderEnabled = true;
+//		}
+//		return isControllerEnabled || isProviderEnabled;
+//	}
+	
+	/**
+	 * This method checks to see if valid annotation providers exist and if valid project version levels exist.
+	 * @return should annotations be supported for this project in this workspace
+	 */
+	protected boolean isAnnotationsSupported() {
+	    return false;
+//		//TODO add this check back in for defect 146696
+////		if (!isAnnotationProviderDefined())
+////			return false;
+//		if (!getDataModel().isPropertySet(IArtifactEditOperationDataModelProperties.PROJECT_NAME))
+//			return true;
+//		if (getStringProperty(IArtifactEditOperationDataModelProperties.PROJECT_NAME).equals("")) //$NON-NLS-1$
+//			return true;
+//		IProject project = ProjectUtilities.getProject(getStringProperty(IArtifactEditOperationDataModelProperties.PROJECT_NAME));
+//		String moduleName = getStringProperty(IArtifactEditOperationDataModelProperties.COMPONENT_NAME);
+//		if (project == null || moduleName == null || moduleName.equals(""))return true; //$NON-NLS-1$
+//		int j2eeVersion = J2EEVersionUtil.convertVersionStringToInt(J2EEProjectUtilities.getJ2EEProjectVersion(project));
+//		
+//		return j2eeVersion > J2EEVersionConstants.VERSION_1_2;
+//		
+	}
+
+	/**
+	 * Subclasses may extend this method to provide their own validation on any of the valid data
+	 * model properties in the hierarchy. This implementation adds validation for the init params,
+	 * filter mappings, display name, and existing class fields specific to the filter java class
+	 * creation. It does not accept a null parameter. This method will not return null.
+	 * 
+	 * @see NewJavaClassDataModelProvider#validate(String)
+	 * 
+	 * @param propertyName
+	 * @return IStatus is property value valid?
+	 */
+	public IStatus validate(String propertyName) {
+		IStatus result = Status.OK_STATUS;
+		// If our default is the superclass, we know it is ok
+		if (propertyName.equals(SUPERCLASS) && "".equals(getStringProperty(propertyName)))
+			return WTPCommonPlugin.OK_STATUS;
+		// Validate init params
+		if (propertyName.equals(INIT_PARAM))
+			return validateInitParamList((List) getProperty(propertyName));
+		// Validate url pattern and servlet name mappings
+		if (propertyName.equals(URL_MAPPINGS) || propertyName.equals(SERVLET_MAPPINGS))
+			return validateFilterMappingList((List) getProperty(URL_MAPPINGS), (List) getProperty(SERVLET_MAPPINGS));
+		// Validate the filter name in DD
+		if (propertyName.equals(DISPLAY_NAME))
+			return validateDisplayName(getStringProperty(propertyName));
+		if (propertyName.equals(CLASS_NAME)) {
+			if (getStringProperty(propertyName).length()!=0 && getBooleanProperty(USE_EXISTING_CLASS))
+				return WTPCommonPlugin.OK_STATUS;
+			result = super.validateJavaClassName(getStringProperty(propertyName));
+			if (result.isOK()) {
+				result = validateJavaClassName(getStringProperty(propertyName));
+				if (result.isOK()&&!getBooleanProperty(USE_EXISTING_CLASS))
+					result = canCreateTypeInClasspath(getStringProperty(CLASS_NAME));
+			}
+			return result;
+		}
+		// Otherwise defer to super to validate the property
+		return super.validate(propertyName);
+	}
+
+	/**
+	 * This method is intended for internal use only. It will be used to validate the init params
+	 * list to ensure there are not any duplicates. This method will accept a null paramter. It will
+	 * not return null.
+	 * 
+	 * @see NewFilterClassDataModelProvider#validate(String)
+	 * 
+	 * @param prop
+	 * @return IStatus is init params list valid?
+	 */
+	private IStatus validateInitParamList(List prop) {
+		if (prop != null && !prop.isEmpty()) {
+			// Ensure there are not duplicate entries in the list
+			boolean dup = hasDuplicatesInStringArrayList(prop);
+			if (dup) {
+				String msg = "WebMessages.ERR_DUPLICATED_INIT_PARAMETER";
+				return WTPCommonPlugin.createErrorStatus(msg);
+			}
+		}
+		// Return OK
+		return WTPCommonPlugin.OK_STATUS;
+	}
+
+	/**
+     * This method is intended for internal use only. This will validate the filter servlet name 
+     * mappings list and ensure there are not duplicate entries. It will accept a null parameter. 
+     * It will not return null.
+     * 
+     * @see NewFilterClassDataModelProvider#validate(String)
+     * 
+     * @param prop
+     * @return IStatus is filter's servlet name mapping list valid?
+     */
+	private IStatus validateFilterMappingList(List urlProp, List servletsProp) {
+	    boolean isUrlPatternMappingsEmpty = false;
+	    boolean isServletMappingsEmpty = false;
+	    if (urlProp != null && !urlProp.isEmpty()) {
+            // Ensure there are not duplicates in the mapping list
+            boolean dup = hasDuplicatesInStringArrayList(urlProp);
+            if (dup) {
+                String msg = WebMessages.ERR_DUPLICATED_URL_MAPPING;
+                return WTPCommonPlugin.createErrorStatus(msg);
+            }
+        } else {
+            isUrlPatternMappingsEmpty = true;
+        }
+	    if (servletsProp == null || servletsProp.isEmpty()) {
+	        isServletMappingsEmpty = true;
+        }
+	    if (isUrlPatternMappingsEmpty && isServletMappingsEmpty) {
+	        String msg = WebMessages.ERR_FILTER_MAPPING_EMPTY;
+	        return WTPCommonPlugin.createErrorStatus(msg);
+	    }
+        // Return OK
+        return WTPCommonPlugin.OK_STATUS;
+	}
+
+	/**
+	 * This method is intended for internal use only. It provides a simple algorithm for detecting
+	 * if there are duplicate entries in a list. It will accept a null paramter. It will not return
+	 * null.
+	 * 
+	 * @see NewFilterClassDataModelProvider#validateInitParamList(List)
+	 * @see NewFilterClassDataModelProvider#validateURLMappingList(List)
+	 * 
+	 * @param input
+	 * @return boolean are there dups in the list?
+	 */
+	private boolean hasDuplicatesInStringArrayList(List input) {
+		// If list is null or empty return false
+		if (input == null)
+			return false;
+		int n = input.size();
+		boolean dup = false;
+		// nested for loops to check each element to see if other elements are the same
+		for (int i = 0; i < n; i++) {
+			String[] sArray1 = (String[]) input.get(i);
+			for (int j = i + 1; j < n; j++) {
+				String[] sArray2 = (String[]) input.get(j);
+				if (isTwoStringArraysEqual(sArray1, sArray2)) {
+					dup = true;
+					break;
+				}
+			}
+			if (dup)
+				break;
+		}
+		// Return boolean status for duplicates
+		return dup;
+	}
+
+	/**
+	 * This method is intended for internal use only. This checks to see if the two string arrays
+	 * are equal. If either of the arrays are null or empty, it returns false.
+	 * 
+	 * @see NewFilterClassDataModelProvider#hasDuplicatesInStringArrayList(List)
+	 * 
+	 * @param sArray1
+	 * @param sArray2
+	 * @return boolean are Arrays equal?
+	 */
+	private boolean isTwoStringArraysEqual(String[] sArray1, String[] sArray2) {
+		// If either array is null, return false
+		if (sArray1 == null || sArray2 == null)
+			return false;
+		int n1 = sArray1.length;
+		int n2 = sArray1.length;
+		// If either array is empty, return false
+		if (n1 == 0 || n2 == 0)
+			return false;
+		// If they don't have the same length, return false
+		if (n1 != n2)
+			return false;
+		// If their first elements do not match, return false
+		if (!sArray1[0].equals(sArray2[0]))
+			return false;
+		// Otherwise return true
+		return true;
+	}
+
+	/**
+	 * This method will return the list of filter interfaces to be implemented for the new servlet
+	 * java class. It will intialize the list using lazy initialization to the minimum interfaces
+	 * required by the data model FILTER_INTERFACES. This method will not return null.
+	 * 
+	 * @see INewFilterClassDataModelProperties#FILTER_INTERFACES
+	 * 
+	 * @return List of servlet interfaces to be implemented
+	 */
+	private List getFilterInterfaces() {
+		if (interfaceList == null) {
+			interfaceList = new ArrayList();
+			// Add minimum required list of servlet interfaces to be implemented
+			for (int i = 0; i < FILTER_INTERFACES.length; i++) {
+				interfaceList.add(FILTER_INTERFACES[i]);
+			}
+		}
+		// Return interface list
+		return interfaceList;
+	}
+
+	/**
+	 * This method is intended for internal use only. This will validate whether the display name
+	 * selected is a valid display name for the filter in the specified web application. It will
+	 * make sure the name is not empty and that it doesn't already exist in the web app. This method
+	 * will accept null as a parameter. It will not return null.
+	 * 
+	 * @see NewFilterClassDataModelProvider#validate(String)
+	 * 
+	 * @param prop
+	 * @return IStatus is filter display name valid?
+	 */
+	private IStatus validateDisplayName(String prop) {
+		// Ensure the filter display name is not null or empty
+		if (prop == null || prop.trim().length() == 0) {
+			String msg = WebMessages.ERR_DISPLAY_NAME_EMPTY;
+			return WTPCommonPlugin.createErrorStatus(msg);
+		}
+		if (getTargetProject() == null || getTargetComponent() == null)
+			return WTPCommonPlugin.OK_STATUS;
+		
+		IModelProvider provider = ModelProviderManager.getModelProvider( getTargetProject() );
+		Object mObj = provider.getModelObject();
+		if( mObj instanceof org.eclipse.jst.j2ee.webapplication.WebApp ){
+			org.eclipse.jst.j2ee.webapplication.WebApp webApp = (org.eclipse.jst.j2ee.webapplication.WebApp) mObj;
+
+			List filters = webApp.getFilters();
+			boolean exists = false;
+			// Ensure the display does not already exist in the web application
+			if (filters != null && !filters.isEmpty()) {
+				for (int i = 0; i < filters.size(); i++) {
+					String name = ((org.eclipse.jst.j2ee.webapplication.Filter) filters.get(i)).getName();
+					if (prop.equals(name))
+						exists = true;
+				}
+			}
+			// If the filter name already exists, throw an error
+			if (exists) {
+				String msg = WebMessages.getResourceString(WebMessages.ERR_SERVLET_DISPLAY_NAME_EXIST, new String[]{prop});
+				return WTPCommonPlugin.createErrorStatus(msg);
+			}			
+		} else if ( mObj instanceof org.eclipse.jst.javaee.web.WebApp){
+			org.eclipse.jst.javaee.web.WebApp webApp= (org.eclipse.jst.javaee.web.WebApp) mObj;
+
+			List filters = webApp.getFilters();
+			boolean exists = false;
+			// Ensure the display does not already exist in the web application
+			if (filters != null && !filters.isEmpty()) {
+				for (int i = 0; i < filters.size(); i++) {
+					String name = ((org.eclipse.jst.javaee.web.Filter) filters.get(i)).getFilterName();
+					if (prop.equals(name))
+						exists = true;
+				}
+			}
+			// If the filter name already exists, throw an error
+			if (exists) {
+				String msg = WebMessages.getResourceString(WebMessages.ERR_SERVLET_DISPLAY_NAME_EXIST, new String[]{prop});
+				return WTPCommonPlugin.createErrorStatus(msg);
+			}			
+		}
+		
+		// Otherwise, return OK
+		return WTPCommonPlugin.OK_STATUS;
+	}
+}
diff --git a/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/NewFilterClassOperation.java b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/NewFilterClassOperation.java
new file mode 100644
index 0000000..0ade037
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/NewFilterClassOperation.java
@@ -0,0 +1,310 @@
+package org.eclipse.jst.j2ee.internal.web.operations;
+
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.emf.codegen.jet.JETEmitter;
+import org.eclipse.emf.codegen.jet.JETException;
+import org.eclipse.jdt.core.*;
+import org.eclipse.jem.util.emf.workbench.ProjectUtilities;
+import org.eclipse.jem.util.logger.proxy.Logger;
+import org.eclipse.jst.common.internal.annotations.controller.AnnotationsController;
+import org.eclipse.jst.common.internal.annotations.controller.AnnotationsControllerManager;
+import org.eclipse.jst.j2ee.internal.common.operations.INewJavaClassDataModelProperties;
+import org.eclipse.jst.j2ee.internal.project.WTPJETEmitter;
+import org.eclipse.jst.j2ee.internal.web.plugin.WebPlugin;
+import org.eclipse.wst.common.componentcore.internal.operation.ArtifactEditProviderOperation;
+import org.eclipse.wst.common.componentcore.internal.operation.IArtifactEditOperationDataModelProperties;
+import org.eclipse.wst.common.frameworks.datamodel.AbstractDataModelOperation;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
+import org.eclipse.wst.common.frameworks.internal.enablement.nonui.WFTWrappedException;
+import org.eclipse.wst.common.frameworks.internal.plugin.WTPCommonPlugin;
+
+/**
+ * The NewFilterClassOperation is an IDataModelOperation following the
+ * IDataModel wizard and operation framework.
+ * 
+ * @see org.eclipse.wst.common.frameworks.datamodel.IDataModelOperation
+ * @see org.eclipse.wst.common.frameworks.datamodel.IDataModelProvider
+ * 
+ * It extends ArtifactEditProviderOperation to provide filter specific java
+ * class generation.
+ * @see org.eclipse.wst.common.componentcore.internal.operation.ArtifactEditProviderOperation
+ * 
+ * This operation is used by the AddFilterOperation to generate an
+ * non annotated java class for an added filter. It shares the
+ * NewFilterClassDataModelProvider with the AddFilterOperation to store the
+ * appropriate properties required to generate the new filter.
+ * @see org.eclipse.jst.j2ee.internal.web.operations.AddFilterOperation
+ * @see org.eclipse.jst.j2ee.internal.web.operations.NewFilterClassDataModelProvider
+ * 
+ * A WTPJetEmitter filter template is used to create the class with the filter template. 
+ * @see org.eclipse.jst.j2ee.internal.project.WTPJETEmitter
+ * @see org.eclipse.jst.j2ee.internal.web.operations.CreateFilterTemplateModel
+ * 
+ * Subclasses may extend this operation to provide their own specific filter
+ * java class generation. The execute method may be extended to do so. Also,
+ * generateUsingTemplates is exposed.
+ * 
+ * The use of this class is EXPERIMENTAL and is subject to substantial changes.
+ */
+public class NewFilterClassOperation extends AbstractDataModelOperation {
+
+	/**
+	 * The extension name for a java class
+	 */
+	private static final String DOT_JAVA = ".java"; //$NON-NLS-1$
+
+	/**
+	 * variable for the web plugin
+	 */
+	protected static final String WEB_PLUGIN = "WEB_PLUGIN"; //$NON-NLS-1$
+
+	/**
+	 * folder location of the filter creation templates diretory
+	 */
+	protected static final String TEMPLATE_FILE = "/templates/filter.javajet"; //$NON-NLS-1$
+
+	/**
+	 * name of the template emitter to be used to generate the deployment
+	 * descriptor from the tags
+	 */
+	protected static final String TEMPLATE_EMITTER = "org.eclipse.jst.j2ee.ejb.annotations.emitter.template"; //$NON-NLS-1$
+
+	/**
+	 * id of the builder used to kick off generation of web metadata based on
+	 * parsing of annotations
+	 */
+	protected static final String BUILDER_ID = "builderId"; //$NON-NLS-1$
+
+	/**
+	 * This is the constructor which should be used when creating a
+	 * NewFilterClassOperation. An instance of the NewFilterClassDataModel
+	 * should be passed in. This does not accept null parameter. It will not
+	 * return null.
+	 * 
+	 * @see ArtifactEditProviderOperation#ArtifactEditProviderOperation(IDataModel)
+	 * @see NewFilterClassDataModel
+	 * 
+	 * @param dataModel
+	 * @return NewFilterClassOperation
+	 */
+	public NewFilterClassOperation(IDataModel dataModel) {
+		super(dataModel);
+	}
+
+	/**
+	 * Subclasses may extend this method to add their own actions during
+	 * execution. The implementation of the execute method drives the running of
+	 * the operation. This implementation will create the java source folder,
+	 * create the java package, and then the filter java class file will be created 
+	 * using templates. Optionally, subclasses may extend the
+	 * generateUsingTemplates or createJavaFile method rather than extend the
+	 * execute method. This method will accept a null parameter.
+	 * 
+	 * @see org.eclipse.wst.common.frameworks.internal.operation.WTPOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
+	 * @see NewFilterClassOperation#generateUsingTemplates(IProgressMonitor,
+	 *      IPackageFragment)
+	 * 
+	 * @param monitor
+	 * @throws CoreException
+	 * @throws InterruptedException
+	 * @throws InvocationTargetException
+	 */
+	public IStatus doExecute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
+		// Create source folder if it does not exist
+		createJavaSourceFolder();
+		// Create java package if it does not exist
+		IPackageFragment pack = createJavaPackage();
+		// Generate filter class using templates
+		try {
+			generateUsingTemplates(monitor, pack);
+		} catch (Exception e) {
+			return WTPCommonPlugin.createErrorStatus(e.toString());
+		}
+		return OK_STATUS;
+	}
+
+	/**
+	 * This method will return the java package as specified by the new java
+	 * class data model. If the package does not exist, it will create the
+	 * package. This method should not return null.
+	 * 
+	 * @see INewJavaClassDataModelProperties#JAVA_PACKAGE
+	 * @see IPackageFragmentRoot#createPackageFragment(java.lang.String,
+	 *      boolean, org.eclipse.core.runtime.IProgressMonitor)
+	 * 
+	 * @return IPackageFragment the java package
+	 */
+	protected final IPackageFragment createJavaPackage() {
+		// Retrieve the package name from the java class data model
+		String packageName = model.getStringProperty(INewJavaClassDataModelProperties.JAVA_PACKAGE);
+		IPackageFragmentRoot packRoot = (IPackageFragmentRoot) model
+				.getProperty(INewJavaClassDataModelProperties.JAVA_PACKAGE_FRAGMENT_ROOT);
+		IPackageFragment pack = packRoot.getPackageFragment(packageName);
+		// Handle default package
+		if (pack == null) {
+			pack = packRoot.getPackageFragment(""); //$NON-NLS-1$
+		}
+		
+		
+		// Create the package fragment if it does not exist
+		if (!pack.exists()) {
+			String packName = pack.getElementName();
+			try {
+				pack = packRoot.createPackageFragment(packName, true, null);
+			} catch (JavaModelException e) {
+				Logger.getLogger().log(e);
+			}
+		}
+		// Return the package
+		return pack;
+	}
+
+	/**
+	 * Subclasses may extend this method to provide their own template based
+	 * creation of an annotated filter java class file. This implementation
+	 * uses the creation of a CreateFilterTemplateModel and the WTPJetEmitter
+	 * to create the java class with the annotated tags. This method accepts
+	 * null for monitor, it does not accept null for fragment. If annotations
+	 * are not being used the tags will be omitted from the class.
+	 * 
+	 * @see CreateFilterTemplateModel
+	 * @see NewFilterClassOperation#generateTemplateSource(CreateFilterTemplateModel,
+	 *      IProgressMonitor)
+	 * 
+	 * @param monitor
+	 * @param fragment
+	 * @throws CoreException
+	 * @throws WFTWrappedException
+	 */
+	protected void generateUsingTemplates(IProgressMonitor monitor, IPackageFragment fragment) throws WFTWrappedException, CoreException {
+	    // Create the filter template model
+	    CreateFilterTemplateModel tempModel = createTemplateModel();
+        IProject project = getTargetProject();
+        String source;
+        // Using the WTPJetEmitter, generate the java source based on the filter template model
+        try {
+            source = generateTemplateSource(tempModel, monitor);
+        } catch (Exception e) {
+            throw new WFTWrappedException(e);
+        }
+        if (fragment != null) {
+            // Create the java file
+            String javaFileName = tempModel.getFilterClassName() + DOT_JAVA;
+            ICompilationUnit cu = fragment.getCompilationUnit(javaFileName);
+            // Add the compilation unit to the java file
+            if (cu == null || !cu.exists())
+                cu = fragment.createCompilationUnit(javaFileName, source, true, monitor);
+            IFile aFile = (IFile) cu.getResource();
+            // Let the annotations controller process the annotated resource
+            AnnotationsController controller = AnnotationsControllerManager.INSTANCE.getAnnotationsController(project);
+            if (controller != null)
+                controller.process(aFile);
+        }
+	}
+
+	/**
+     * This method is intended for internal use only. This method will create an
+     * instance of the CreateFilterTemplate model to be used in conjunction
+     * with the WTPJETEmitter. This method will not return null.
+     * 
+     * @see CreateFilterTemplateModel
+     * @see NewFilterClassOperation#generateUsingTemplates(IProgressMonitor,
+     *      IPackageFragment)
+     * 
+     * @return CreateFilterTemplateModel
+     */
+    private CreateFilterTemplateModel createTemplateModel() {
+        // Create the CreateFilterTemplateModel instance with the new filter
+        // class data model
+        CreateFilterTemplateModel templateModel = new CreateFilterTemplateModel(model);
+        return templateModel;
+    }
+    
+    /**
+     * This method is intended for internal use only. This will use the
+     * WTPJETEmitter to create an annotated java file based on the passed in
+     * filter class template model. This method does not accept null
+     * parameters. It will not return null. If annotations are not used, it will
+     * use the non annotated template to omit the annotated tags.
+     * 
+     * @see NewFilterClassOperation#generateUsingTemplates(IProgressMonitor,
+     *      IPackageFragment)
+     * @see JETEmitter#generate(org.eclipse.core.runtime.IProgressMonitor,
+     *      java.lang.Object[])
+     * @see CreateFilterTemplateModel
+     * 
+     * @param tempModel
+     * @param monitor
+     * @return String the source for the java file
+     * @throws JETException
+     */
+    private String generateTemplateSource(CreateFilterTemplateModel tempModel, IProgressMonitor monitor) throws JETException {
+        URL templateURL = FileLocator.find(WebPlugin.getDefault().getBundle(), new Path(TEMPLATE_FILE), null);
+        cleanUpOldEmitterProject();
+        WTPJETEmitter emitter = new WTPJETEmitter(templateURL.toString(), this.getClass().getClassLoader());
+        emitter.setIntelligentLinkingEnabled(true);
+        emitter.addVariable(WEB_PLUGIN, WebPlugin.PLUGIN_ID);
+        return emitter.generate(monitor, new Object[] { tempModel });
+    }
+    
+	private void cleanUpOldEmitterProject() {
+		IProject project = ProjectUtilities.getProject(WTPJETEmitter.PROJECT_NAME);
+		if (project == null || !project.exists())
+			return;
+		try {
+			IMarker[] markers = project.findMarkers(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
+			for (int i = 0, l = markers.length; i < l; i++) {
+				if (((Integer) markers[i].getAttribute(IMarker.SEVERITY)).intValue() == IMarker.SEVERITY_ERROR) {
+					project.delete(true, new NullProgressMonitor());
+					break;
+				}
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * This method will return the java source folder as specified in the java
+	 * class data model. It will create the java source folder if it does not
+	 * exist. This method may return null.
+	 * 
+	 * @see INewJavaClassDataModelProperties#SOURCE_FOLDER
+	 * @see IFolder#create(boolean, boolean,
+	 *      org.eclipse.core.runtime.IProgressMonitor)
+	 * 
+	 * @return IFolder the java source folder
+	 */
+	protected final IFolder createJavaSourceFolder() {
+		// Get the source folder name from the data model
+		String folderFullPath = model.getStringProperty(INewJavaClassDataModelProperties.SOURCE_FOLDER);
+		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+		IFolder folder = root.getFolder(new Path(folderFullPath));
+		// If folder does not exist, create the folder with the specified path
+		if (!folder.exists()) {
+			try {
+				folder.create(true, true, null);
+			} catch (CoreException e) {
+				Logger.getLogger().log(e);
+			}
+		}
+		// Return the source folder
+		return folder;
+	}
+
+	@Override
+	public IStatus execute(IProgressMonitor monitor, IAdaptable info)
+			throws ExecutionException {
+		return doExecute(monitor, info);
+	}
+	
+	public IProject getTargetProject() {
+		String projectName = model.getStringProperty(IArtifactEditOperationDataModelProperties.PROJECT_NAME);
+		return ProjectUtilities.getProject(projectName);
+	}	
+}
diff --git a/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/NewListenerClassOperation.java b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/NewListenerClassOperation.java
index 9fb1d84..bbccbe8 100644
--- a/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/NewListenerClassOperation.java
+++ b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/NewListenerClassOperation.java
@@ -23,6 +23,7 @@
 import org.eclipse.core.resources.IWorkspaceRoot;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.FileLocator;
 import org.eclipse.core.runtime.IAdaptable;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
@@ -336,7 +337,7 @@
 	 * @throws JETException
 	 */
 	private String generateTemplateSource(CreateListenerTemplateModel tempModel, IProgressMonitor monitor) throws JETException {
-		URL templateURL = WebPlugin.getDefault().find(new Path(TEMPLATE_FILE));
+		URL templateURL = FileLocator.find(WebPlugin.getDefault().getBundle(), new Path(TEMPLATE_FILE), null);
 		cleanUpOldEmitterProject();
 		WTPJETEmitter emitter = new WTPJETEmitter(templateURL.toString(), this.getClass().getClassLoader());
 		emitter.setIntelligentLinkingEnabled(true);
diff --git a/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/NewServletClassOperation.java b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/NewServletClassOperation.java
index 38dc81d..b723758 100644
--- a/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/NewServletClassOperation.java
+++ b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/NewServletClassOperation.java
@@ -23,6 +23,7 @@
 import org.eclipse.core.resources.IWorkspaceRoot;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.FileLocator;
 import org.eclipse.core.runtime.IAdaptable;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
@@ -337,7 +338,7 @@
 	 * @throws JETException
 	 */
 	private String generateTemplateSource(CreateServletTemplateModel tempModel, IProgressMonitor monitor) throws JETException {
-		URL templateURL = WebPlugin.getDefault().find(new Path(TEMPLATE_FILE));
+		URL templateURL = FileLocator.find(WebPlugin.getDefault().getBundle(), new Path(TEMPLATE_FILE), null);
 		cleanUpOldEmitterProject();
 		WTPJETEmitter emitter = new WTPJETEmitter(templateURL.toString(), this.getClass().getClassLoader());
 		emitter.setIntelligentLinkingEnabled(true);
diff --git a/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/WebMessages.java b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/WebMessages.java
index c9c5dfc..85d5f81 100644
--- a/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/WebMessages.java
+++ b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/WebMessages.java
@@ -42,10 +42,7 @@
 	public static String ERR_SERVLET_MAPPING_URL_PATTERN_EMPTY;
 	public static String ERR_SERVLET_MAPPING_URL_PATTERN_EXIST;
 	public static String ERR_SERVLET_MAPPING_URL_PATTERN_INVALID;
-	public static String KEY_3;
-	public static String KEY_4;
-	public static String KEY_5;
-	public static String KEY_6;
+	public static String ERR_FILTER_MAPPING_EMPTY;
 	public static String ERR_FILTER_PARAMETER_NAME_EXIST;
 	public static String ERR_FILTER_MAPPING_SERVLET_EXIST;
 	public static String ERR_FILTER_MAPPING_SERVLET_DISPATCHER_TYPES_EMPTY;
diff --git a/plugins/org.eclipse.jst.servlet.ui/icons/full/ctool16/newfilter_wiz.gif b/plugins/org.eclipse.jst.servlet.ui/icons/full/ctool16/newfilter_wiz.gif
new file mode 100644
index 0000000..06cafc3
--- /dev/null
+++ b/plugins/org.eclipse.jst.servlet.ui/icons/full/ctool16/newfilter_wiz.gif
Binary files differ
diff --git a/plugins/org.eclipse.jst.servlet.ui/plugin.properties b/plugins/org.eclipse.jst.servlet.ui/plugin.properties
index 48a20d2..613c50f 100644
--- a/plugins/org.eclipse.jst.servlet.ui/plugin.properties
+++ b/plugins/org.eclipse.jst.servlet.ui/plugin.properties
@@ -35,6 +35,8 @@
 ServletWebRegionWizard.description=Create a new Servlet
 ServletWebRegionWizard.title=New Servlet
 Servlet_UI_=Servlet...
+FilterWebRegionWizard.name=Filter
+FilterWebRegionWizard.description=Create a new Filter - IcoBgr2
 servletAnnotationDecorator=Servlet Annotation Decorator
 servletAnnotationDecorator.description=Adds a decorator to an annotated servlet.
 web-project-wizard-name = Web Project
diff --git a/plugins/org.eclipse.jst.servlet.ui/plugin.xml b/plugins/org.eclipse.jst.servlet.ui/plugin.xml
index 1d379ef..dfcc8dd 100644
--- a/plugins/org.eclipse.jst.servlet.ui/plugin.xml
+++ b/plugins/org.eclipse.jst.servlet.ui/plugin.xml
@@ -49,7 +49,7 @@
                class="org.eclipse.core.resources.IResource">
          </selection>
       </wizard>
-      
+
       <!--new servlet contribution-->
  	  <wizard
             name="%ServletWebRegionWizard.name"
@@ -62,6 +62,18 @@
          </description>
       </wizard>
       
+      <!--new filter contribution-->      
+      <wizard
+            category="org.eclipse.wst.web.ui"
+            class="org.eclipse.jst.servlet.ui.internal.wizard.AddFilterWizard"
+            icon="icons/full/ctool16/newfilter_wiz.gif"
+            id="org.eclipse.jst.servlet.ui.internal.wizard.AddFilterWizard"
+            name="%FilterWebRegionWizard.name">
+         <description>
+            %FilterWebRegionWizard.description
+         </description>
+      </wizard>
+      
       <!--new listener contribution-->
  	  <wizard
             name="%ListenerWebRegionWizard.name"
diff --git a/plugins/org.eclipse.jst.servlet.ui/property_files/web_ui.properties b/plugins/org.eclipse.jst.servlet.ui/property_files/web_ui.properties
index 4151250..e550d78 100644
--- a/plugins/org.eclipse.jst.servlet.ui/property_files/web_ui.properties
+++ b/plugins/org.eclipse.jst.servlet.ui/property_files/web_ui.properties
@@ -31,12 +31,21 @@
 ADD_SERVLET_WIZARD_PAGE_TITLE=Create Servlet
 ADD_SERVLET_WIZARD_PAGE_DESC=Enter servlet deployment descriptor specific information.
 
+ADD_FILTER_WIZARD_WINDOW_TITLE=Create Filter
+ADD_FILTER_WIZARD_PAGE_TITLE=Create Filter
+ADD_FILTER_WIZARD_PAGE_DESC=Enter servlet filter deployment descriptor specific information.
+
+ADD_LISTENER_WIZARD_WINDOW_TITLE=Create Listener
+ADD_LISTENER_WIZARD_PAGE_TITLE=Select Events
+ADD_LISTENER_WIZARD_PAGE_DESC=Select the application lifecycle events to listen to. 
+
 DEFAULT_PACKAGE=(default package)
 SELECT_CLASS_TITLE=Select Class
 MAP_CLASS_NAME_TO_CLASS_ERROR_MSG=IWAE0060E Could not uniquely map the class name to a class.
 EMPTY_LIST_MSG=Empty List
 ADD_LABEL=Add
 USE_EXISTING_SERVLET_CLASS=Use existing Servlet class
+USE_EXISTING_FILTER_CLASS=Use existing Filter class
 INIT_PARAM_LABEL=Initialization Parameters:
 URL_MAPPINGS_LABEL=URL Mappings:
 CHOOSE_SERVLET_CLASS=Choose a servlet class
@@ -47,9 +56,10 @@
 SERVLET_PACKAGE_LABEL=Java package:
 SERVLET_NAME_LABEL=Servlet name:
 
-ADD_LISTENER_WIZARD_WINDOW_TITLE=Create Listener
-ADD_LISTENER_WIZARD_PAGE_TITLE=Select Events
-ADD_LISTENER_WIZARD_PAGE_DESC=Select the application lifecycle events to listen to. 
+NEW_FILTER_WIZARD_WINDOW_TITLE=New Filter
+CHOOSE_FILTER_CLASS=Choose a filter class
+SERVLET_MAPPINGS_LABEL=Servlet Mappings:
+
 ADD_LISTENER_WIZARD_SERVLET_CONTEXT_EVENTS=Servlet Context Events
 ADD_LISTENER_WIZARD_HTTP_SESSION_EVENTS=HTTP Session Events
 ADD_LISTENER_WIZARD_SERVLET_REQUEST_EVENTS=Servlet Request Events
diff --git a/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/plugin/WEBUIMessages.java b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/plugin/WEBUIMessages.java
index a771722..009a53a 100644
--- a/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/plugin/WEBUIMessages.java
+++ b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/plugin/WEBUIMessages.java
@@ -24,6 +24,7 @@
 	public static String NEW_SERVLET_WIZARD_PAGE_TITLE;
 	public static String FOLDER_LABEL;
 	public static String URL_MAPPINGS_LABEL;
+	public static String SERVLET_MAPPINGS_LABEL;
 	public static String JAVA_CLASS_MODIFIERS_LABEL;
 	public static String SUPERCLASS_LABEL;
 	public static String WEB_CONT_PAGE_TITLE;
@@ -32,6 +33,8 @@
 	public static String JAVA_CLASS_ABSTRACT_CHECKBOX_LABEL;
 	public static String ADD_SERVLET_WIZARD_WINDOW_TITLE;
 	public static String ADD_SERVLET_WIZARD_PAGE_TITLE;
+    public static String ADD_FILTER_WIZARD_WINDOW_TITLE;
+    public static String ADD_FILTER_WIZARD_PAGE_TITLE;
 	public static String JAVA_CLASS_MAIN_CHECKBOX_LABEL;
 	public static String EMPTY_LIST_MSG;
 	public static String ExportWARAction_UI_;
@@ -50,10 +53,12 @@
 	public static String CONTAINER_SELECTION_DIALOG_VALIDATOR_MESG;
 	public static String DESCRIPTION_LABEL;
 	public static String USE_EXISTING_SERVLET_CLASS;
+    public static String USE_EXISTING_FILTER_CLASS;
 	public static String JAVA_CLASS_FINAL_CHECKBOX_LABEL;
 	public static String INTERFACE_SELECTION_DIALOG_DESC;
 	public static String ADD_LABEL;
 	public static String ADD_SERVLET_WIZARD_PAGE_DESC;
+    public static String ADD_FILTER_WIZARD_PAGE_DESC;
 	public static String SELECT_CLASS_TITLE;
 	public static String JAVA_CLASS_BROWER_DIALOG_MESSAGE;
 	public static String ImportWARAction_UI_;
@@ -93,11 +98,13 @@
 	public static String NEW_JAVA_CLASS_OPTIONS_WIZARD_PAGE_DESC;
 	public static String REMOVE_BUTTON_LABEL;
 	public static String NEW_SERVLET_WIZARD_WINDOW_TITLE;
+    public static String NEW_FILTER_WIZARD_WINDOW_TITLE;
 	public static String INTERFACE_SELECTION_DIALOG_TITLE;
 	public static String NAME_LABEL;
 	public static String VALUE_LABEL;
 	public static String WEB_CONT_PAGE_COMP_LABEL;
 	public static String CHOOSE_SERVLET_CLASS;
+	public static String CHOOSE_FILTER_CLASS;
 	public static String NEW_SERVLET_WIZARD_PAGE_DESC;
 	public static String JAVA_CLASS_INHERIT_CHECKBOX_LABEL;
 	public static String WEB_CONT_PAGE_DESCRIPTION;
diff --git a/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/AddFilterWizard.java b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/AddFilterWizard.java
new file mode 100644
index 0000000..f4585b1
--- /dev/null
+++ b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/AddFilterWizard.java
@@ -0,0 +1,128 @@
+package org.eclipse.jst.servlet.ui.internal.wizard;
+
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jst.j2ee.internal.common.operations.INewJavaClassDataModelProperties;
+import org.eclipse.jst.j2ee.internal.plugin.J2EEEditorUtility;
+import org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin;
+import org.eclipse.jst.j2ee.internal.plugin.J2EEUIPlugin;
+import org.eclipse.jst.j2ee.internal.project.J2EEProjectUtilities;
+import org.eclipse.jst.j2ee.internal.web.operations.NewFilterClassDataModelProvider;
+import org.eclipse.jst.j2ee.web.componentcore.util.WebArtifactEdit;
+import org.eclipse.jst.servlet.ui.IWebUIContextIds;
+import org.eclipse.jst.servlet.ui.internal.plugin.ServletUIPlugin;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModelProvider;
+
+/**
+ * New servlet filter wizard
+ */
+public class AddFilterWizard extends NewWebWizard {
+
+	private static final String PAGE_ONE = "pageOne"; //$NON-NLS-1$
+    private static final String PAGE_TWO = "pageTwo"; //$NON-NLS-1$
+    
+	public AddFilterWizard(IDataModel model) {
+		super(model);
+        setWindowTitle(IWebWizardConstants.ADD_FILTER_WIZARD_WINDOW_TITLE);
+        setDefaultPageImageDescriptor(getFilterWizBan());
+	}
+	
+    public AddFilterWizard() {
+        this(null);
+    }
+    
+    /* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.Wizard#addPages()
+	 */
+	public void doAddPages() {
+		NewFilterClassWizardPage page1 = new NewFilterClassWizardPage(
+		        getDataModel(),
+		        PAGE_ONE,
+		        IWebWizardConstants.NEW_JAVA_CLASS_DESTINATION_WIZARD_PAGE_DESC,
+				IWebWizardConstants.ADD_FILTER_WIZARD_PAGE_TITLE, 
+				J2EEProjectUtilities.DYNAMIC_WEB);
+//		page1.setInfopopID(IWebUIContextIds.WEBEDITOR_FILTER_PAGE_ADD_FILTER_WIZARD_1);
+		addPage(page1);
+
+		AddFilterWizardPage page2 = new AddFilterWizardPage(getDataModel(), PAGE_TWO);
+//		page2.setInfopopID(IWebUIContextIds.WEBEDITOR_FILTER_PAGE_ADD_FILTER_WIZARD_2);
+		addPage(page2);
+	}
+	
+	/* (non-Javadoc)
+     * @see org.eclipse.jem.util.ui.wizard.WTPWizard#runForked()
+     */
+    protected boolean runForked() {
+        return false;
+    }
+	
+    public boolean canFinish() {
+        return getDataModel().isValid();
+    }
+    
+	@Override
+	protected IDataModelProvider getDefaultProvider() {
+		return new NewFilterClassDataModelProvider();
+	}
+
+//	protected IStructuredSelection getCurrentSelection() {
+//		IWorkbenchWindow window = J2EEUIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
+//		if (window != null) {
+//			ISelection selection = window.getSelectionService().getSelection();
+//			if (selection instanceof IStructuredSelection) {
+//				return (IStructuredSelection) selection;
+//			}
+//		}
+//		return null;
+//	}
+
+    @Override
+    protected void postPerformFinish() throws InvocationTargetException {
+      //open new filter class in java editor
+        WebArtifactEdit artifactEdit = null;
+        try {
+            String className = getDataModel().getStringProperty(INewJavaClassDataModelProperties.QUALIFIED_CLASS_NAME);
+            IProject p = (IProject) getDataModel().getProperty(INewJavaClassDataModelProperties.PROJECT);
+            // filter class
+            IJavaProject javaProject = J2EEEditorUtility.getJavaProject(p);
+            IFile file = (IFile) javaProject.findType(className).getResource();
+            openEditor(file);
+        } catch (Exception cantOpen) {
+            ServletUIPlugin.log(cantOpen);
+        } finally {
+            if (artifactEdit!=null)
+                artifactEdit.dispose();
+        }
+    }
+	
+    private void openEditor(final IFile file) {
+        if (file != null) {
+            getShell().getDisplay().asyncExec(new Runnable() {
+                public void run() {
+                    try {
+                        IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+                        IDE.openEditor(page, file, true);
+                    }
+                    catch (PartInitException e) {
+                        ServletUIPlugin.log(e);
+                    }
+                }
+            });
+        }
+    }
+    
+    private ImageDescriptor getFilterWizBan() {
+		URL url = (URL) J2EEPlugin.getDefault().getImage("newfilter_wiz"); //$NON-NLS-1$
+		return ImageDescriptor.createFromURL(url);
+	}
+}
diff --git a/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/AddFilterWizardPage.java b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/AddFilterWizardPage.java
new file mode 100644
index 0000000..58575d3
--- /dev/null
+++ b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/AddFilterWizardPage.java
@@ -0,0 +1,168 @@
+package org.eclipse.jst.servlet.ui.internal.wizard;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jst.j2ee.internal.common.operations.INewJavaClassDataModelProperties;
+import org.eclipse.jst.j2ee.internal.web.operations.INewFilterClassDataModelProperties;
+import org.eclipse.jst.j2ee.internal.wizard.StringArrayTableWizardSection;
+import org.eclipse.jst.j2ee.model.IModelProvider;
+import org.eclipse.jst.j2ee.model.ModelProviderManager;
+import org.eclipse.jst.j2ee.webapplication.Servlet;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.wst.common.componentcore.internal.operation.IArtifactEditOperationDataModelProperties;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
+import org.eclipse.wst.common.frameworks.internal.datamodel.ui.DataModelWizardPage;
+import org.eclipse.wst.common.frameworks.internal.plugin.WTPCommonPlugin;
+
+/**
+ * Filter Wizard Setting Page
+ */
+public class AddFilterWizardPage extends DataModelWizardPage {
+	final static String[] FILTEREXTENSIONS = {"java"}; //$NON-NLS-1$
+
+	private Text displayNameText;
+
+	private StringArrayTableWizardSection urlSection;
+	private ServletNameArrayTableWizardSection servletSection;
+
+	public AddFilterWizardPage(IDataModel model, String pageName) {
+		super(model, pageName);
+		setDescription(IWebWizardConstants.ADD_FILTER_WIZARD_PAGE_DESC);
+		this.setTitle(IWebWizardConstants.ADD_FILTER_WIZARD_PAGE_TITLE);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jem.util.ui.wizard.WTPWizardPage#getValidationPropertyNames()
+	 */
+	protected String[] getValidationPropertyNames() {
+		return new String[]{INewFilterClassDataModelProperties.DISPLAY_NAME, 
+		        INewFilterClassDataModelProperties.INIT_PARAM, 
+		        INewFilterClassDataModelProperties.URL_MAPPINGS,
+		        INewFilterClassDataModelProperties.SERVLET_MAPPINGS};
+	}
+
+	protected Composite createTopLevelComposite(Composite parent) {
+		Composite composite = new Composite(parent, SWT.NULL);
+		composite.setLayout(new GridLayout());
+		GridData data = new GridData(GridData.FILL_BOTH);
+		data.widthHint = 300;
+		composite.setLayoutData(data);
+
+		createNameDescription(composite);
+		
+		StringArrayTableWizardSectionCallback callback = new StringArrayTableWizardSectionCallback();
+		StringArrayTableWizardSection initSection = new StringArrayTableWizardSection(composite, IWebWizardConstants.INIT_PARAM_LABEL, IWebWizardConstants.ADD_BUTTON_LABEL, IWebWizardConstants.EDIT_BUTTON_LABEL, 
+				IWebWizardConstants.REMOVE_BUTTON_LABEL, new String[]{IWebWizardConstants.NAME_LABEL, IWebWizardConstants.VALUE_LABEL, IWebWizardConstants.DESCRIPTION_LABEL}, null,// WebPlugin.getDefault().getImage("initializ_parameter"),
+				model, INewFilterClassDataModelProperties.INIT_PARAM);
+		initSection.setCallback(callback);
+		
+		urlSection = new StringArrayTableWizardSection(composite, IWebWizardConstants.URL_MAPPINGS_LABEL, IWebWizardConstants.ADD_BUTTON_LABEL, IWebWizardConstants.EDIT_BUTTON_LABEL, IWebWizardConstants.REMOVE_BUTTON_LABEL,
+				new String[]{IWebWizardConstants.URL_PATTERN_LABEL}, null,// WebPlugin.getDefault().getImage("url_type"),
+				model, INewFilterClassDataModelProperties.URL_MAPPINGS);
+		urlSection.setCallback(callback);
+
+		IProject p = (IProject) model.getProperty(INewJavaClassDataModelProperties.PROJECT);
+		IModelProvider provider = ModelProviderManager.getModelProvider(p);
+		Object mObj = provider.getModelObject();
+		ArrayList<String> servletsList = new ArrayList<String>();
+		if (mObj instanceof org.eclipse.jst.j2ee.webapplication.WebApp) {
+			org.eclipse.jst.j2ee.webapplication.WebApp webApp = (org.eclipse.jst.j2ee.webapplication.WebApp) mObj;
+			List<Servlet> servlets = webApp.getServlets();
+			for (Servlet servlet : servlets) {
+				servletsList.add(servlet.getServletName());
+			}
+		} else if (mObj instanceof org.eclipse.jst.javaee.web.WebApp) {
+			org.eclipse.jst.javaee.web.WebApp webApp= (org.eclipse.jst.javaee.web.WebApp) mObj;
+			List<org.eclipse.jst.javaee.web.Servlet> servlets = webApp.getServlets();
+			for (org.eclipse.jst.javaee.web.Servlet servlet : servlets) {
+				servletsList.add(servlet.getServletName());
+			}
+		}
+		ServletNamesArrayTableWizardSectionCallback callback1 =  new ServletNamesArrayTableWizardSectionCallback(servletsList);
+        servletSection = new ServletNameArrayTableWizardSection(composite, 
+                IWebWizardConstants.SERVLET_MAPPINGS_LABEL, IWebWizardConstants.ADD_BUTTON_LABEL, 
+                IWebWizardConstants.REMOVE_BUTTON_LABEL,
+                new String[]{IWebWizardConstants.SERVLET_NAME_LABEL}, null,
+                model, INewFilterClassDataModelProperties.SERVLET_MAPPINGS);
+        servletSection.setCallback(callback1);
+		
+		String text = displayNameText.getText();
+		// Set default URL Pattern
+		List input = new ArrayList();
+		input.add(new String[]{"/" + text}); //$NON-NLS-1$
+		if (urlSection != null)
+			urlSection.setInput(input);
+		displayNameText.setFocus();
+
+		IStatus projectStatus = validateProjectName();
+		if (!projectStatus.isOK()) {
+			setErrorMessage(projectStatus.getMessage());
+			composite.setEnabled(false);
+		}
+	    Dialog.applyDialogFont(parent);
+		return composite;
+	}
+
+	protected IStatus validateProjectName() {
+		// check for empty
+		if (model.getStringProperty(IArtifactEditOperationDataModelProperties.PROJECT_NAME) == null || model.getStringProperty(IArtifactEditOperationDataModelProperties.PROJECT_NAME).trim().length() == 0) {
+			return WTPCommonPlugin.createErrorStatus(IWebWizardConstants.NO_WEB_PROJECTS);
+		}
+		return WTPCommonPlugin.OK_STATUS;
+	}
+
+	protected void createNameDescription(Composite parent) {
+		Composite composite = new Composite(parent, SWT.NULL);
+		composite.setLayout(new GridLayout(2, false));
+		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+		// display name
+		Label displayNameLabel = new Label(composite, SWT.LEFT);
+		displayNameLabel.setText(IWebWizardConstants.NAME_LABEL);
+		displayNameLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
+		displayNameText = new Text(composite, SWT.SINGLE | SWT.BORDER);
+		displayNameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		displayNameText.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+				String text = displayNameText.getText();
+				// Set default URL Pattern
+				List input = new ArrayList();
+				input.add(new String[]{"/" + text}); //$NON-NLS-1$
+				if (urlSection != null)
+					urlSection.setInput(input);
+			}
+
+		});
+		synchHelper.synchText(displayNameText, INewFilterClassDataModelProperties.DISPLAY_NAME, null);
+
+		// description
+		Label descLabel = new Label(composite, SWT.LEFT);
+		descLabel.setText(IWebWizardConstants.DESCRIPTION_LABEL);
+		descLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
+		Text descText = new Text(composite, SWT.SINGLE | SWT.BORDER);
+		descText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		synchHelper.synchText(descText, INewFilterClassDataModelProperties.DESCRIPTION, null);
+	}
+
+	public String getDisplayName() {
+		return displayNameText.getText();
+	}
+	
+	public boolean canFlipToNextPage() {
+		if (model.getBooleanProperty(INewFilterClassDataModelProperties.USE_EXISTING_CLASS))
+			return false;
+		return super.canFlipToNextPage();
+	}
+}
diff --git a/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/IWebWizardConstants.java b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/IWebWizardConstants.java
index 9f8e710..22f6eb1 100644
--- a/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/IWebWizardConstants.java
+++ b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/IWebWizardConstants.java
@@ -35,6 +35,18 @@
 	public final static String NEW_SERVLET_WIZARD_PAGE_DESC = WEBUIMessages.NEW_SERVLET_WIZARD_PAGE_DESC;
 	public final static String SERVLET_PACKAGE_LABEL = WEBUIMessages.SERVLET_PACKAGE_LABEL;
 	public final static String SERVLET_NAME_LABEL = WEBUIMessages.SERVLET_NAME_LABEL;
+	
+    // AddFilterWizard
+    public final static String ADD_FILTER_WIZARD_WINDOW_TITLE = WEBUIMessages.ADD_FILTER_WIZARD_WINDOW_TITLE;
+    public final static String ADD_FILTER_WIZARD_PAGE_TITLE = WEBUIMessages.ADD_FILTER_WIZARD_PAGE_TITLE;
+    public final static String ADD_FILTER_WIZARD_PAGE_DESC = WEBUIMessages.ADD_FILTER_WIZARD_PAGE_DESC;
+
+    public final static String USE_EXISTING_FILTER_CLASS = WEBUIMessages.USE_EXISTING_FILTER_CLASS;
+    public final static String CHOOSE_FILTER_CLASS = WEBUIMessages.CHOOSE_FILTER_CLASS;
+    public final static String SERVLET_MAPPINGS_LABEL = WEBUIMessages.SERVLET_MAPPINGS_LABEL;
+    
+    // NewFilterWizard
+    public final static String NEW_FILTER_WIZARD_WINDOW_TITLE = WEBUIMessages.NEW_FILTER_WIZARD_WINDOW_TITLE;
 
 	// AddListenerWizard
 	public final static String ADD_LISTENER_WIZARD_WINDOW_TITLE = WEBUIMessages.ADD_LISTENER_WIZARD_WINDOW_TITLE;
diff --git a/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/MultiSelectFilteredFilterFileSelectionDialog.java b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/MultiSelectFilteredFilterFileSelectionDialog.java
new file mode 100644
index 0000000..ed4c33d
--- /dev/null
+++ b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/MultiSelectFilteredFilterFileSelectionDialog.java
@@ -0,0 +1,602 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.servlet.ui.internal.wizard;
+
+/**
+ * 
+ */
+import java.util.ArrayList;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.ITypeHierarchy;
+import org.eclipse.jdt.ui.ISharedImages;
+import org.eclipse.jdt.ui.JavaUI;
+import org.eclipse.jem.util.logger.proxy.Logger;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableContext;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jst.j2ee.internal.dialogs.FilteredFileSelectionDialog;
+import org.eclipse.jst.j2ee.internal.dialogs.TwoArrayQuickSorter;
+import org.eclipse.jst.j2ee.internal.dialogs.TypedFileViewerFilter;
+import org.eclipse.jst.j2ee.internal.plugin.J2EEUIPlugin;
+import org.eclipse.jst.j2ee.internal.web.providers.WebAppEditResourceHandler;
+import org.eclipse.jst.servlet.ui.internal.plugin.ServletUIPlugin;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
+import org.eclipse.ui.dialogs.ISelectionStatusValidator;
+import org.eclipse.ui.part.PageBook;
+
+/**
+ * Insert the type's description here.
+ * Creation date: (7/30/2001 11:16:36 AM)
+ */
+public class MultiSelectFilteredFilterFileSelectionDialog extends FilteredFileSelectionDialog {
+	
+
+	private static class PackageRenderer extends LabelProvider {
+		private final Image PACKAGE_ICON = JavaUI.getSharedImages().getImage(ISharedImages.IMG_OBJS_PACKAGE); 
+
+		public String getText(Object element) {
+			IType type = (IType) element;
+			String p = type.getPackageFragment().getElementName();
+			if ("".equals(p)) //$NON-NLS-1$
+				p = IWebWizardConstants.DEFAULT_PACKAGE;
+			return (p + " - " + type.getPackageFragment().getParent().getPath().toString()); //$NON-NLS-1$
+		}
+		public Image getImage(Object element) {
+			return PACKAGE_ICON;
+		}
+	}
+
+	private static class TypeRenderer extends LabelProvider {
+		private final Image CLASS_ICON = JavaUI.getSharedImages().getImage(ISharedImages.IMG_OBJS_CLASS); 
+
+		public String getText(Object element) {
+			IType e = ((IType) element);
+			return e.getElementName();
+		}
+
+		public Image getImage(Object element) {
+			return CLASS_ICON;
+		}
+
+	}
+	protected PageBook fPageBook = null;
+	protected Control fServletControl = null;
+	protected Composite fChild = null;
+	// construction parameters
+	protected IRunnableContext fRunnableContext;
+	protected ILabelProvider fElementRenderer;
+	protected ILabelProvider fQualifierRenderer;
+	private Object[] fElements;
+	private boolean fIgnoreCase = true;
+	private String fUpperListLabel;
+	private String fLowerListLabel;
+	// SWT widgets
+	private Table fUpperList;
+	private Table fLowerList;
+	protected Text fText;
+	private IType[] fIT;
+	private String[] fRenderedStrings;
+	private int[] fElementMap;
+	private Integer[] fQualifierMap;
+
+	private ISelectionStatusValidator fLocalValidator = null;
+	/**
+	 * This is a selection dialog for available servlet.
+	 * @param parent Shell
+	 * @param title String
+	 * @param message String
+	 * @parent extensions String[]
+	 * @param allowMultiple boolean
+	 */
+	public MultiSelectFilteredFilterFileSelectionDialog(Shell parent, String title, String message, String[] extensions, boolean allowMultiple, IProject project) {
+		super(parent, title, message, extensions, allowMultiple);
+		setShellStyle(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL | SWT.RESIZE);
+
+		if (title == null)
+			setTitle(WebAppEditResourceHandler.getString("File_Selection_UI_")); //$NON-NLS-1$
+		if (message == null)
+			message = WebAppEditResourceHandler.getString("Select_a_file__UI_"); //$NON-NLS-1$
+		setMessage(message);
+		setExtensions(extensions);
+		addFilter(new TypedFileViewerFilter(extensions));
+		fLocalValidator = new SimpleTypedElementSelectionValidator(new Class[] { IFile.class }, allowMultiple);
+		setValidator(fLocalValidator);
+		
+		//StatusInfo currStatus = new StatusInfo();
+		//currStatus.setOK();
+		Status currStatus = new Status(Status.OK, ServletUIPlugin.PLUGIN_ID, Status.OK, "", null);
+		
+		updateStatus(currStatus);
+		fElementRenderer = new TypeRenderer();
+		fQualifierRenderer = new PackageRenderer();
+		fRunnableContext = J2EEUIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
+		try {
+			IJavaElement jelem = null;
+			IProject proj = null;
+			jelem = (IJavaElement) project.getAdapter(IJavaElement.class);
+			if (jelem == null) {
+				IResource resource = (IResource) project.getAdapter(IResource.class);
+				if (resource != null) {
+					proj = resource.getProject();
+					if (proj != null) {
+						jelem = org.eclipse.jdt.core.JavaCore.create(proj);
+					}
+				}
+			}
+			IJavaProject jp = jelem.getJavaProject();
+			 IType filterType = jp.findType("javax.servlet.Filter"); //$NON-NLS-1$
+			// next 3 lines fix defect 177686
+			if (filterType == null) {
+			    return;
+			}
+			ArrayList filterClasses = new ArrayList();
+			ITypeHierarchy tH = filterType.newTypeHierarchy(jp, null);
+			IType[] types = tH.getAllSubtypes(filterType);
+			for (int i = 0; i < types.length; i++) {
+			    if (types[i].isClass() && !filterClasses.contains(types[i]))
+			        filterClasses.add(types[i]);
+			}
+			fIT = (IType[]) filterClasses.toArray(new IType[filterClasses.size()]);
+			filterClasses = null;
+		} catch (Exception exc) {
+			Logger.getLogger().logError(exc);
+		}
+	}
+	
+	/**
+	 * @private
+	 */
+	protected void computeResult() {
+	    IType type = (IType) getWidgetSelection();
+	    if (type != null) {
+	        if (type == null) {
+	            String title = WebAppEditResourceHandler.getString("Select_Class_UI_"); //$NON-NLS-1$ = "Select Class"
+	            String message = WebAppEditResourceHandler.getString("Could_not_uniquely_map_the_ERROR_"); //$NON-NLS-1$ = "Could not uniquely map the class name to a class."
+	            MessageDialog.openError(getShell(), title, message);
+	            setResult(null);
+	        } else {
+	            java.util.List result = new ArrayList(1);
+	            result.add(type);
+	            setResult(result);
+	        }
+		}
+	}
+	
+	public void create() {
+		super.create();
+		fText.setFocus();
+		rematch(""); //$NON-NLS-1$
+		updateOkState();
+	}
+	
+	/**
+	 * Creates and returns the contents of this dialog's 
+	 * button bar.
+	 * <p>
+	 * The <code>Dialog</code> implementation of this framework method
+	 * lays out a button bar and calls the <code>createButtonsForButtonBar</code>
+	 * framework method to populate it. Subclasses may override.
+	 * </p>
+	 *
+	 * @param parent the parent composite to contain the button bar
+	 * @return the button bar control
+	 */
+	protected Control createButtonBar(Composite parent) {
+		Composite composite = new Composite(parent, SWT.NULL);
+		GridLayout layout = new GridLayout();
+
+		layout.numColumns = 2;
+
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		composite.setLayout(layout);
+		composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+		Composite composite2 = new Composite(composite, SWT.NONE);
+
+		// create a layout with spacing and margins appropriate for the font size.
+		layout = new GridLayout();
+		layout.numColumns = 0; // this is incremented by createButton
+		layout.makeColumnsEqualWidth = true;
+		layout.marginWidth = convertHorizontalDLUsToPixels(org.eclipse.jface.dialogs.IDialogConstants.HORIZONTAL_MARGIN);
+		layout.marginHeight = convertVerticalDLUsToPixels(org.eclipse.jface.dialogs.IDialogConstants.VERTICAL_MARGIN);
+		layout.horizontalSpacing = convertHorizontalDLUsToPixels(org.eclipse.jface.dialogs.IDialogConstants.HORIZONTAL_SPACING);
+		layout.verticalSpacing = convertVerticalDLUsToPixels(org.eclipse.jface.dialogs.IDialogConstants.VERTICAL_SPACING);
+
+		composite2.setLayout(layout);
+
+		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END | GridData.VERTICAL_ALIGN_CENTER);
+		composite2.setLayoutData(data);
+
+		composite2.setFont(parent.getFont());
+
+		// Add the buttons to the button bar.
+		super.createButtonsForButtonBar(composite2);
+
+		return composite;
+	}
+	
+	/*
+	 * @private
+	 */
+	protected Control createDialogArea(Composite parent) {
+		GridData gd = new GridData();
+
+		fChild = new Composite(parent, SWT.NONE);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(fChild, "com.ibm.etools.webapplicationedit.webx2010"); //$NON-NLS-1$
+		GridLayout gl = new GridLayout();
+		gl.numColumns = 2;
+		gl.marginHeight = 5;
+		fChild.setLayout(gl);
+
+		gd.verticalAlignment = GridData.FILL;
+		gd.horizontalAlignment = GridData.FILL;
+		gd.grabExcessVerticalSpace = true;
+		fChild.setLayoutData(gd);
+
+		fPageBook = new PageBook(fChild, SWT.NONE);
+		gd = new GridData();
+		gd.horizontalAlignment = GridData.FILL;
+		gd.verticalAlignment = GridData.FILL;
+		gd.grabExcessHorizontalSpace = true;
+		gd.grabExcessVerticalSpace = true;
+		gd.horizontalSpan = 2;
+		fPageBook.setLayoutData(gd);
+		super.createDialogArea(fPageBook);
+
+		Composite composite = new Composite(fPageBook, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
+		layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+		layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
+		layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
+		composite.setLayout(layout);
+		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+		composite.setFont(parent.getFont());
+
+		Label messageLabel = new Label(composite, SWT.NONE);
+		gd = new GridData();
+		messageLabel.setLayoutData(gd);
+        messageLabel.setText(WebAppEditResourceHandler.getString("Choose_a_filter__1")); //$NON-NLS-1$
+
+        fText = createText(composite);
+
+		messageLabel = new Label(composite, SWT.NONE);
+		gd = new GridData();
+		messageLabel.setLayoutData(gd);
+        messageLabel.setText(WebAppEditResourceHandler.getString("Matching_filters__2")); //$NON-NLS-1$
+
+		fUpperList = createUpperList(composite);
+
+		messageLabel = new Label(composite, SWT.NONE);
+		gd = new GridData();
+		messageLabel.setLayoutData(gd);
+		messageLabel.setText(WebAppEditResourceHandler.getString("Qualifier__3")); //$NON-NLS-1$
+
+		fLowerList = createLowerList(composite);
+
+		fServletControl = composite;
+
+		fPageBook.showPage(fServletControl);
+		return parent;
+	}
+	
+	/**
+	 * Creates the list widget and sets layout data.
+	 * @return org.eclipse.swt.widgets.List
+	 */
+	private Table createLowerList(Composite parent) {
+		if (fLowerListLabel != null)
+			 (new Label(parent, SWT.NONE)).setText(fLowerListLabel);
+
+		Table list = new Table(parent, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
+		list.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event evt) {
+				handleLowerSelectionChanged();
+			}
+		});
+		list.addListener(SWT.MouseDoubleClick, new Listener() {
+			public void handleEvent(Event evt) {
+				handleLowerDoubleClick();
+			}
+		});
+		list.addDisposeListener(new DisposeListener() {
+			public void widgetDisposed(DisposeEvent e) {
+				fQualifierRenderer.dispose();
+			}
+		});
+		GridData spec = new GridData();
+		spec.widthHint = convertWidthInCharsToPixels(50);
+		spec.heightHint = convertHeightInCharsToPixels(5);
+		spec.grabExcessVerticalSpace = true;
+		spec.grabExcessHorizontalSpace = true;
+		spec.horizontalAlignment = GridData.FILL;
+		spec.verticalAlignment = GridData.FILL;
+		list.setLayoutData(spec);
+		return list;
+	}
+	
+	/**
+	 * Creates the text widget and sets layout data.
+	 * @return org.eclipse.swt.widgets.Text
+	 */
+	private Text createText(Composite parent) {
+		Text text = new Text(parent, SWT.BORDER);
+		GridData spec = new GridData();
+		spec.grabExcessVerticalSpace = false;
+		spec.grabExcessHorizontalSpace = true;
+		spec.horizontalAlignment = GridData.FILL;
+		spec.verticalAlignment = GridData.BEGINNING;
+		text.setLayoutData(spec);
+		Listener l = new Listener() {
+			public void handleEvent(Event evt) {
+				rematch(fText.getText());
+			}
+		};
+		text.addListener(SWT.Modify, l);
+		return text;
+	}
+	
+	/**
+	 * Creates the list widget and sets layout data.
+	 * @return org.eclipse.swt.widgets.List
+	 */
+	private Table createUpperList(Composite parent) {
+		if (fUpperListLabel != null)
+			 (new Label(parent, SWT.NONE)).setText(fUpperListLabel);
+
+		Table list = new Table(parent, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
+		list.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event evt) {
+				handleUpperSelectionChanged();
+			}
+		});
+		list.addListener(SWT.MouseDoubleClick, new Listener() {
+			public void handleEvent(Event evt) {
+				handleUpperDoubleClick();
+			}
+		});
+		list.addDisposeListener(new DisposeListener() {
+			public void widgetDisposed(DisposeEvent e) {
+				fElementRenderer.dispose();
+			}
+		});
+		GridData spec = new GridData();
+		spec.widthHint = convertWidthInCharsToPixels(50);
+		spec.heightHint = convertHeightInCharsToPixels(15);
+		spec.grabExcessVerticalSpace = true;
+		spec.grabExcessHorizontalSpace = true;
+		spec.horizontalAlignment = GridData.FILL;
+		spec.verticalAlignment = GridData.FILL;
+		list.setLayoutData(spec);
+		return list;
+	}
+	
+	/**
+	 * @return the ID of the button that is 'pressed' on doubleClick in the lists.
+	 * By default it is the OK button.
+	 * Override to change this setting.
+	 */
+	protected int getDefaultButtonID() {
+		return IDialogConstants.OK_ID;
+	}
+	
+	protected Object getWidgetSelection() {
+		int i = fLowerList.getSelectionIndex();
+		if (fQualifierMap != null) {
+			if (fQualifierMap.length == 1)
+				i = 0;
+			if (i < 0) {
+				return null;
+			} 
+			Integer index = fQualifierMap[i];
+			return fElements[index.intValue()];
+		}
+		return null;
+	}
+	
+	protected final void handleLowerDoubleClick() {
+		if (getWidgetSelection() != null)
+			buttonPressed(getDefaultButtonID());
+	}
+	
+	protected final void handleLowerSelectionChanged() {
+		updateOkState();
+	}
+	
+	protected final void handleUpperDoubleClick() {
+		if (getWidgetSelection() != null)
+			buttonPressed(getDefaultButtonID());
+	}
+	
+	protected final void handleUpperSelectionChanged() {
+		int selection = fUpperList.getSelectionIndex();
+		if (selection >= 0) {
+			int i = fElementMap[selection];
+			int k = i;
+			int length = fRenderedStrings.length;
+			while (k < length && fRenderedStrings[k].equals(fRenderedStrings[i])) {
+				k++;
+			}
+			updateLowerListWidget(i, k);
+		} else
+			updateLowerListWidget(0, 0);
+	}
+	
+	public int open() {
+		if (fIT == null || fIT.length == 0) {
+		    MessageDialog.openInformation(getShell(), 
+		            WebAppEditResourceHandler.getString("Empty_List_1"), 
+		            WebAppEditResourceHandler.getString("_INFO_No_filters_exist_to_add._1"));  //$NON-NLS-2$ //$NON-NLS-1$
+			return CANCEL;
+		}
+
+		setElements(fIT);
+		setInitialSelection(""); //$NON-NLS-1$
+		return super.open();
+	}
+	
+	/**
+	 * update the list to reflect a new match string.
+	 * @param matchString java.lang.String
+	 */
+	protected final void rematch(String matchString) {
+		int k = 0;
+		String text = fText.getText();
+		StringMatcher matcher = new StringMatcher(text + "*", fIgnoreCase, false); //$NON-NLS-1$
+		String lastString = null;
+		int length = fElements.length;
+		for (int i = 0; i < length; i++) {
+			while (i < length && fRenderedStrings[i].equals(lastString))
+				i++;
+			if (i < length) {
+				lastString = fRenderedStrings[i];
+				if (matcher.match(fRenderedStrings[i])) {
+					fElementMap[k] = i;
+					k++;
+				}
+			}
+		}
+		fElementMap[k] = -1;
+
+		updateUpperListWidget(fElementMap, k);
+	}
+	
+	/**
+		 * 
+		 * @return java.lang.String[]
+		 * @param p org.eclipse.jface.elements.IIndexedProperty
+		 */
+	private String[] renderStrings(Object[] p) {
+		String[] strings = new String[p.length];
+		int size = strings.length;
+		for (int i = 0; i < size; i++) {
+			strings[i] = fElementRenderer.getText(p[i]);
+		}
+		new TwoArrayQuickSorter(fIgnoreCase).sort(strings, p);
+		return strings;
+	}
+
+	public void setElements(Object[] elements) {
+		fElements = elements;
+		fElementMap = new int[fElements.length + 1];
+		fRenderedStrings = renderStrings(fElements);
+	}
+
+	private void updateLowerListWidget(int from, int to) {
+		fLowerList.removeAll();
+		fQualifierMap = new Integer[to - from];
+		String[] qualifiers = new String[to - from];
+		for (int i = from; i < to; i++) {
+			// XXX: 1G65LDG: JFUIF:WIN2000 - ILabelProvider used outside a viewer
+			qualifiers[i - from] = fQualifierRenderer.getText(fElements[i]);
+			fQualifierMap[i - from] = new Integer(i);
+		}
+
+		new TwoArrayQuickSorter(fIgnoreCase).sort(qualifiers, fQualifierMap);
+
+		for (int i = 0; i < to - from; i++) {
+			TableItem ti = new TableItem(fLowerList, i);
+			ti.setText(qualifiers[i]);
+			// XXX: 1G65LDG: JFUIF:WIN2000 - ILabelProvider used outside a viewer
+			Image img = fQualifierRenderer.getImage(fElements[from + i]);
+			if (img != null)
+				ti.setImage(img);
+		}
+
+		if (fLowerList.getItemCount() > 0)
+			fLowerList.setSelection(0);
+		updateOkState();
+	}
+	
+	private void updateOkState() {
+		Button okButton = getOkButton();
+		if (okButton != null)
+			okButton.setEnabled(getWidgetSelection() != null);
+	}
+	
+	private void updateUpperListWidget(int[] indices, int size) {
+		fUpperList.setRedraw(false);
+		int itemCount = fUpperList.getItemCount();
+		if (size < itemCount)
+			fUpperList.remove(0, itemCount - size - 1);
+		TableItem[] items = fUpperList.getItems();
+		for (int i = 0; i < size; i++) {
+			TableItem ti = null;
+			if (i < itemCount)
+				ti = items[i];
+			else
+				ti = new TableItem(fUpperList, i);
+			ti.setText(fRenderedStrings[indices[i]]);
+			// XXX: 1G65LDG: JFUIF:WIN2000 - ILabelProvider used outside a viewer
+			Image img = fElementRenderer.getImage(fElements[indices[i]]);
+			if (img != null)
+				ti.setImage(img);
+		}
+		if (fUpperList.getItemCount() > 0)
+			fUpperList.setSelection(0);
+		fUpperList.setRedraw(true);
+		handleUpperSelectionChanged();
+	}
+	
+	/**
+	 * Sent when default selection occurs in the control.
+	 * <p>
+	 * For example, on some platforms default selection occurs
+	 * in a List when the user double-clicks an item or types
+	 * return in a Text.
+	 * </p>
+	 *
+	 * @param e an event containing information about the default selection
+	 */
+	public void widgetDefaultSelected(SelectionEvent e) {
+		// Do nothing
+	}
+	
+	/**
+	 * @see ElementTreeSelectionDialog#updateOKStatus()
+	 */
+	protected void updateOKStatus() {
+		super.updateOKStatus();
+		Button okButton = getOkButton();
+		if (okButton != null)
+			okButton.setEnabled(fLocalValidator.validate(getResult()).isOK());
+	}
+
+}
diff --git a/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/NewFilterClassWizardPage.java b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/NewFilterClassWizardPage.java
new file mode 100644
index 0000000..a2072e5
--- /dev/null
+++ b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/NewFilterClassWizardPage.java
@@ -0,0 +1,135 @@
+package org.eclipse.jst.servlet.ui.internal.wizard;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jem.util.emf.workbench.ProjectUtilities;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jst.j2ee.internal.common.operations.INewJavaClassDataModelProperties;
+import org.eclipse.jst.j2ee.internal.war.ui.util.WebFiltersGroupItemProvider;
+import org.eclipse.jst.j2ee.internal.war.ui.util.WebServletGroupItemProvider;
+import org.eclipse.jst.j2ee.internal.web.operations.INewFilterClassDataModelProperties;
+import org.eclipse.jst.j2ee.internal.wizard.NewJavaClassWizardPage;
+import org.eclipse.jst.j2ee.webapplication.WebApp;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.wst.common.componentcore.ComponentCore;
+import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
+
+public class NewFilterClassWizardPage extends NewJavaClassWizardPage {
+    private Button existingButton;
+    private Label existingClassLabel;
+    private Text existingClassText;
+    private Button existingClassButton;
+    private final static String[] FILTEREXTENSIONS = { "java" }; //$NON-NLS-1$
+    
+	public NewFilterClassWizardPage(IDataModel model, String pageName, String pageDesc, String pageTitle, String moduleType) {
+		super(model, pageName, pageDesc, pageTitle, moduleType);
+		//setFirstTimeToPage(false);
+	}
+	
+	protected Composite createTopLevelComposite(Composite parent) {
+		Composite composite = super.createTopLevelComposite(parent);
+		addSeperator(composite,3);
+		createUseExistingGroup(composite);
+//		createAnnotationsGroup(composite);
+		return composite;
+	}
+
+	protected IProject getExtendedSelectedProject(Object selection) {
+		if (selection instanceof WebFiltersGroupItemProvider) {
+			WebApp webApp = (WebApp)((WebFiltersGroupItemProvider)selection).getParent();
+			return ProjectUtilities.getProject(webApp);
+		}
+//		else if (selection instanceof CompressedJavaProject) {
+//			return ((CompressedJavaProject)selection).getProject().getProject();
+//		}
+		return super.getExtendedSelectedProject(selection);
+	}
+	
+	private void createUseExistingGroup(Composite composite) {
+        existingButton = new Button(composite, SWT.CHECK);
+        existingButton.setText(IWebWizardConstants.USE_EXISTING_FILTER_CLASS);
+        GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+        data.horizontalSpan = 3;
+        existingButton.setLayoutData(data);
+        synchHelper.synchCheckbox(existingButton, INewFilterClassDataModelProperties.USE_EXISTING_CLASS, null);
+        existingButton.addSelectionListener(new SelectionAdapter() {
+            public void widgetSelected(SelectionEvent e) {
+                handleExistingButtonSelected();
+            }
+        });
+        
+        existingClassLabel = new Label(composite, SWT.LEFT);
+        existingClassLabel.setText(IWebWizardConstants.CLASS_NAME_LABEL);
+        existingClassLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
+        existingClassLabel.setEnabled(false);
+
+        existingClassText = new Text(composite, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY);
+        existingClassText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+        existingClassText.setEnabled(false);
+        synchHelper.synchText(existingClassText, INewJavaClassDataModelProperties.CLASS_NAME, null);
+
+        existingClassButton = new Button(composite, SWT.PUSH);
+        existingClassButton.setText(IWebWizardConstants.BROWSE_BUTTON_LABEL);
+        existingClassButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+        existingClassButton.setEnabled(false);
+        existingClassButton.addSelectionListener(new SelectionAdapter() {
+            public void widgetSelected(SelectionEvent e) {
+                handleClassButtonSelected();
+            }
+        });
+    }
+	
+	private void handleClassButtonSelected() {
+        getControl().setCursor(new Cursor(getShell().getDisplay(), SWT.CURSOR_WAIT));
+        IProject project = (IProject) model.getProperty(INewJavaClassDataModelProperties.PROJECT);
+        IVirtualComponent component = ComponentCore.createComponent(project);
+        MultiSelectFilteredFilterFileSelectionDialog ms = new MultiSelectFilteredFilterFileSelectionDialog(
+                getShell(),
+                IWebWizardConstants.NEW_FILTER_WIZARD_WINDOW_TITLE,
+                IWebWizardConstants.CHOOSE_FILTER_CLASS, 
+                FILTEREXTENSIONS, 
+                false, 
+                project);
+        IContainer root = component.getRootFolder().getUnderlyingFolder();
+        ms.setInput(root);
+        ms.open();
+        if (ms.getReturnCode() == Window.OK) {
+            String qualifiedClassName = ""; //$NON-NLS-1$
+            IType type = (IType) ms.getFirstResult();
+            if (type != null) {
+                qualifiedClassName = type.getFullyQualifiedName();
+            }
+            existingClassText.setText(qualifiedClassName);
+        }
+        getControl().setCursor(null);
+    }
+	
+	private void handleExistingButtonSelected() {
+        boolean enable = existingButton.getSelection();
+        if (!enable) {
+            existingClassText.setText(""); //$NON-NLS-1$
+        }
+        existingClassLabel.setEnabled(enable);
+        existingClassButton.setEnabled(enable);
+        packageText.setEnabled(!enable);
+        packageButton.setEnabled(!enable);
+        packageLabel.setEnabled(!enable);
+        classText.setEnabled(!enable);
+        classText.setText(""); //$NON-NLS-1$
+        classLabel.setEnabled(!enable);
+        superText.setEnabled(!enable);
+        superButton.setEnabled(!enable);
+        superLabel.setEnabled(!enable);
+    }
+	
+//	private boolean isWebDocletProject() {
+//		return false;
+//	}
+}
diff --git a/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/ServletNameArrayTableWizardSection.java b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/ServletNameArrayTableWizardSection.java
new file mode 100644
index 0000000..113aa86
--- /dev/null
+++ b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/ServletNameArrayTableWizardSection.java
@@ -0,0 +1,459 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * David Schneider, david.schneider@unisys.com - [142500] WTP properties pages fonts don't follow Eclipse preferences
+ *******************************************************************************/
+package org.eclipse.jst.servlet.ui.internal.wizard;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.jdt.ui.ISharedImages;
+import org.eclipse.jdt.ui.JavaUI;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
+
+/**
+ * @author jialin
+ * 
+ * To change the template for this generated type comment go to Window -
+ * Preferences - Java - Code Generation - Code and Comments
+ */
+public class ServletNameArrayTableWizardSection extends Composite {
+
+	protected class StringArrayListContentProvider implements IStructuredContentProvider {
+		public boolean isDeleted(Object element) {
+			return false;
+		}
+		public Object[] getElements(Object element) {
+			if (element instanceof List) {
+				return ((List) element).toArray();
+			}
+			return new Object[0];
+		}
+		public void inputChanged(Viewer aViewer, Object oldInput, Object newInput) {
+			//Default nothing
+		}
+		public void dispose() {
+			//Default nothing
+		}
+	}
+	protected class StringArrayListLabelProvider extends LabelProvider {
+		public Image getImage(Object element) {
+            return labelProviderImage;
+        }
+		public String getText(Object element) {
+            String[] array = (String[]) element;
+			String s = array[0];
+			return s;
+        }
+	}
+
+	protected class AddStringArrayDialog extends Dialog {
+	    protected String result;
+	    private Table fServletList;
+	    protected Text fText;
+	    protected ILabelProvider fElementRenderer;
+	    private int[] fElementMap;
+	    private String[] fElements;
+	    private boolean fIgnoreCase = true;
+	    
+	    private class TypeRenderer extends LabelProvider {
+	        private final Image CLASS_ICON = JavaUI.getSharedImages().getImage(ISharedImages.IMG_OBJS_CLASS); 
+
+	        public String getText(Object element) {
+	            return (String) element;
+	        }
+
+	        public Image getImage(Object element) {
+	            return CLASS_ICON;
+	        }
+
+	    }
+	    
+	    public AddStringArrayDialog(Shell shell, String windowTitle, String[] labelsForTextField) {
+	        super(shell);
+	        fElementRenderer = new TypeRenderer();
+	    }
+	    
+	    /**
+	     * CMPFieldDialog constructor comment.
+	     */
+	    public Control createDialogArea(Composite parent) {
+	        Composite composite = (Composite) super.createDialogArea(parent);
+	        getShell().setText("Select Servlet Name");
+	        
+	        GridLayout layout = new GridLayout();
+	        layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
+	        layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+	        layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
+	        layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
+	        composite.setLayout(layout);
+	        composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+	        composite.setFont(parent.getFont());
+
+	        Label messageLabel = new Label(composite, SWT.NONE);
+	        GridData gd = new GridData();
+	        messageLabel.setLayoutData(gd);
+	        messageLabel.setText("Choose a servlet name:"); //$NON-NLS-1$
+
+	        fText = createText(composite);
+	        
+	        messageLabel = new Label(composite, SWT.NONE);
+	        gd = new GridData();
+	        messageLabel.setLayoutData(gd);
+	        messageLabel.setText("Servlet Names"); //$NON-NLS-1$
+
+	        fServletList = createServletsList(composite);
+	        
+	        // set focus
+	        //texts[0].setFocus();
+	        Dialog.applyDialogFont(parent);
+	        return composite;
+	    }
+
+	    protected Control createContents(Composite parent) {
+	        Composite composite = (Composite) super.createContents(parent);
+	        updateOKButton();
+	        return composite;
+	    }
+	    
+	    /**
+	     * update the list to reflect a new match string.
+	     * @param matchString java.lang.String
+	     */
+	    protected final void rematch(String matchString) {
+	        int k = 0;
+	        String text = fText.getText();
+	        StringMatcher matcher = new StringMatcher(text + "*", fIgnoreCase, false); //$NON-NLS-1$
+	        String lastString = null;
+	        int length = fElements.length;
+	        for (int i = 0; i < length; i++) {
+	            while (i < length && fElements[i].equals(lastString))
+	                i++;
+	            if (i < length) {
+	                lastString = fElements[i];
+	                if (matcher.match(fElements[i])) {
+	                    fElementMap[k] = i;
+	                    k++;
+	                }
+	            }
+	        }
+	        fElementMap[k] = -1;
+
+	        updateServletsListWidget(fElementMap, k);
+	    }
+	    
+	    private void updateServletsListWidget(int[] indices, int size) {
+	        fServletList.setRedraw(false);
+	        int itemCount = fServletList.getItemCount();
+	        if (size < itemCount)
+	            fServletList.remove(0, itemCount - size - 1);
+	        TableItem[] items = fServletList.getItems();
+	        for (int i = 0; i < size; i++) {
+	            TableItem ti = null;
+	            if (i < itemCount)
+	                ti = items[i];
+	            else
+	                ti = new TableItem(fServletList, i);
+	            ti.setText(fElements[indices[i]]);
+	            Image img = fElementRenderer.getImage(fElements[indices[i]]);
+	            if (img != null)
+	                ti.setImage(img);
+	        }
+	        if (fServletList.getItemCount() > 0)
+	            fServletList.setSelection(0);
+	        fServletList.setRedraw(true);
+	        handleServletSelectionChanged();
+	    }
+	    
+	    protected void okPressed() {
+	        TableItem[] selection = fServletList.getSelection();
+            result = fText.getText();
+            if (selection.length > 0) {
+                result = selection[0].getText(); 
+            }
+            callback.getServlets().remove(result);
+	        super.okPressed();
+	    }
+
+	    public String getResult() {
+	        return result;
+	    }
+
+	    private void updateOKButton() {
+	        TableItem[] selection = fServletList.getSelection();
+	        String result = fText.getText();
+	        if (selection.length > 0) {
+	            result = selection[0].getText(); 
+	        }
+	        getButton(IDialogConstants.OK_ID).setEnabled(callback.validate(result));
+	    }
+	    
+	    /**
+	     * Creates the list widget and sets layout data.
+	     * @return org.eclipse.swt.widgets.List
+	     */
+	    private Table createServletsList(Composite parent) {
+	        Table list = new Table(parent, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
+	        list.addListener(SWT.Selection, new Listener() {
+	            public void handleEvent(Event evt) {
+	                handleServletSelectionChanged();
+	            }
+	        });
+	        list.addListener(SWT.MouseDoubleClick, new Listener() {
+	            public void handleEvent(Event evt) {
+	                handleServletDoubleClick();
+	            }
+	        });
+	        list.addDisposeListener(new DisposeListener() {
+	            public void widgetDisposed(DisposeEvent e) {
+	                fElementRenderer.dispose();
+	            }
+	        });
+	        GridData spec = new GridData();
+	        spec.widthHint = convertWidthInCharsToPixels(50);
+	        spec.heightHint = convertHeightInCharsToPixels(15);
+	        spec.grabExcessVerticalSpace = true;
+	        spec.grabExcessHorizontalSpace = true;
+	        spec.horizontalAlignment = GridData.FILL;
+	        spec.verticalAlignment = GridData.FILL;
+	        list.setLayoutData(spec);
+	        return list;
+	    }
+	    
+	    /**
+	     * Creates the text widget and sets layout data.
+	     * @return org.eclipse.swt.widgets.Text
+	     */
+	    private Text createText(Composite parent) {
+	        Text text = new Text(parent, SWT.BORDER);
+	        GridData spec = new GridData();
+	        spec.grabExcessVerticalSpace = false;
+	        spec.grabExcessHorizontalSpace = true;
+	        spec.horizontalAlignment = GridData.FILL;
+	        spec.verticalAlignment = GridData.BEGINNING;
+	        text.setLayoutData(spec);
+	        Listener l = new Listener() {
+	            public void handleEvent(Event evt) {
+	                rematch(fText.getText());
+	            }
+	        };
+	        text.addListener(SWT.Modify, l);
+	        return text;
+	    }
+	    
+	    /**
+	     * @return the ID of the button that is 'pressed' on doubleClick in the lists.
+	     * By default it is the OK button.
+	     * Override to change this setting.
+	     */
+	    protected int getDefaultButtonID() {
+	        return IDialogConstants.OK_ID;
+	    }
+	    
+	    protected final void handleServletDoubleClick() {
+	        int selection = fServletList.getSelectionIndex();
+	        if (selection > -1) {
+	            buttonPressed(getDefaultButtonID());
+	        }
+	    }
+	    
+	    protected final void handleServletSelectionChanged() {
+	        int selection = fServletList.getSelectionIndex();
+	        if (selection >= 0) {
+	            int i = fElementMap[selection];
+	            int k = i;
+	            int length = fElements.length;
+	            while (k < length && fElements[k].equals(fElements[i])) {
+	                k++;
+	            }
+	        }
+	        updateOKButton();
+	    }
+
+        @Override
+        public void create() {
+            super.create();
+            fText.setFocus();
+            rematch(""); //$NON-NLS-1$
+            updateOKButton();
+        }
+
+        @Override
+        public int open() {
+            setElements(callback.getServletNames());
+            //setInitialSelection(""); //$NON-NLS-1$
+            return super.open();
+        }
+	    
+        public void setElements(String[] elements) {
+            fElements = elements;
+            fElementMap = new int[fElements.length + 1];
+        }
+	}
+	
+
+	private TableViewer viewer;
+	private Button addButton;
+	private Button removeButton;
+	private String title;
+	private String[] labelsForText;
+	private IDataModel model;
+	private String propertyName;
+	private Image labelProviderImage;
+	private ServletNamesArrayTableWizardSectionCallback callback;
+
+    public ServletNameArrayTableWizardSection(Composite parent, String title, String addButtonLabel, String removeButtonLabel, 
+            String[] labelsForText, Image labelProviderImage, IDataModel model, String propertyName) {
+	    super(parent, SWT.NONE);
+        this.title = title;
+        this.labelsForText = labelsForText;
+        this.labelProviderImage = labelProviderImage;
+        this.model = model;
+        this.propertyName = propertyName;
+
+        GridLayout layout = new GridLayout(2, false);
+        layout.marginHeight = 4;
+        layout.marginWidth = 0;
+        this.setLayout(layout);
+        this.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+        Label titleLabel = new Label(this, SWT.LEFT);
+        titleLabel.setText(title);
+        GridData data = new GridData();
+        data.horizontalSpan = 2;
+        titleLabel.setLayoutData(data);
+
+        viewer = new TableViewer(this);
+        viewer.getTable().setLayoutData(new GridData(GridData.FILL_BOTH));
+        viewer.setContentProvider(new StringArrayListContentProvider());
+        viewer.setLabelProvider(new StringArrayListLabelProvider());
+
+        Composite buttonCompo = new Composite(this, SWT.NULL);
+        layout = new GridLayout();
+        layout.marginHeight = 0;
+        buttonCompo.setLayout(layout);
+        buttonCompo.setLayoutData(new GridData(GridData.FILL_VERTICAL | GridData.VERTICAL_ALIGN_BEGINNING));
+
+        addButton = new Button(buttonCompo, SWT.PUSH);
+        addButton.setText(addButtonLabel);
+        addButton.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.HORIZONTAL_ALIGN_FILL));
+        addButton.addSelectionListener(new SelectionListener() {
+            public void widgetSelected(SelectionEvent event) {
+                handleAddButtonSelected();
+            }
+            public void widgetDefaultSelected(SelectionEvent event) {
+                //Do nothing
+            }
+        });
+
+        removeButton = new Button(buttonCompo, SWT.PUSH);
+        removeButton.setText(removeButtonLabel);
+        removeButton.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.HORIZONTAL_ALIGN_FILL));
+        removeButton.addSelectionListener(new SelectionListener() {
+            public void widgetSelected(SelectionEvent event) {
+                handleRemoveButtonSelected();
+            }
+            public void widgetDefaultSelected(SelectionEvent event) {
+                //Do nothing
+            }
+        });
+        removeButton.setEnabled(false);
+
+        viewer.addSelectionChangedListener(new ISelectionChangedListener() {
+            public void selectionChanged(SelectionChangedEvent event) {
+                ISelection selection = event.getSelection();
+                removeButton.setEnabled(!selection.isEmpty());
+            }
+        });
+        
+        callback = new ServletNamesArrayTableWizardSectionCallback(null);
+	}
+
+	private void handleAddButtonSelected() {
+		AddStringArrayDialog dialog = new AddStringArrayDialog(getShell(), title, labelsForText);
+		dialog.open();
+		String result = dialog.getResult();
+		addServletName(result != null ? new String[] { result } : null);
+	}
+
+	private void handleRemoveButtonSelected() {
+		ISelection selection = viewer.getSelection();
+		if (selection.isEmpty() || !(selection instanceof IStructuredSelection))
+			return;
+		List<String[]> selectedObj = ((IStructuredSelection) selection).toList();
+		removeStringArrays(selectedObj);
+		List<String> servlets = callback.getServlets();
+		for (String[] servlet : selectedObj) {
+		    servlets.add(servlet[0]);
+        }
+		
+	}
+	
+	public void addServletName(String[] servletName) {
+		if (servletName == null)
+			return;
+		List valueList = (List) viewer.getInput();
+		if (valueList == null)
+			valueList = new ArrayList();
+		valueList.add(servletName);
+		setInput(valueList);
+	}
+
+	public void removeStringArray(Object selectedStringArray) {
+		List valueList = (List) viewer.getInput();
+		valueList.remove(selectedStringArray);
+		setInput(valueList);
+	}
+	
+	public void removeStringArrays(Collection selectedStringArrays) {
+		List valueList = (List) viewer.getInput();
+		valueList.removeAll(selectedStringArrays);
+		setInput(valueList);
+	}
+
+	public void setInput(List input) {
+		viewer.setInput(input);
+		// Create a new list to trigger property change
+		List newInput = new ArrayList();
+		newInput.addAll(input);
+		model.setProperty(propertyName, newInput);
+	}
+
+	public TableViewer getTableViewer() {
+		return viewer;
+	}
+
+	public Button getAddButton() {
+		return addButton;
+	}
+
+	public Button getRemoveButton() {
+		return removeButton;
+	}
+	
+	/**
+	 * Set callback for customizing the preprocessing of the user input. 
+	 * 
+	 * @param callback an implementation of the callback interface. 
+	 */
+	public void setCallback(ServletNamesArrayTableWizardSectionCallback callback) {
+		this.callback = callback;
+	}
+}
diff --git a/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/ServletNamesArrayTableWizardSectionCallback.java b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/ServletNamesArrayTableWizardSectionCallback.java
new file mode 100644
index 0000000..6a069ab
--- /dev/null
+++ b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/ServletNamesArrayTableWizardSectionCallback.java
@@ -0,0 +1,39 @@
+package org.eclipse.jst.servlet.ui.internal.wizard;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ServletNamesArrayTableWizardSectionCallback {
+
+	private List<String> servletNames;
+	
+	
+	public ServletNamesArrayTableWizardSectionCallback(List<String> servletsList) {
+	    if (servletsList != null) {
+	        servletNames = servletsList;
+	    } else {
+	        servletNames = new ArrayList<String>();
+	    }
+	}
+
+	/**
+     * Trims the text values. 
+     */
+	public boolean validate(String text) {
+	    if (text != null) {
+	        String newServlet = text.trim();
+	        if (servletNames.contains(newServlet)) return true;
+	    }
+		return false;
+	}
+	
+	public List getServlets() {
+	    return servletNames;
+	}
+	
+	public String[] getServletNames() {
+	    String[] ret = new String[servletNames.size()];
+	    return servletNames.toArray(ret);
+	}
+
+}