[199106] Listener 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 e808e72..76c5bf2 100644
--- a/plugins/org.eclipse.jst.j2ee.navigator.ui/plugin.xml
+++ b/plugins/org.eclipse.jst.j2ee.navigator.ui/plugin.xml
@@ -624,6 +624,20 @@
 				</or>
 			</enablement>
 		</commonWizard>
+		<!-- New Listener -->
+		<commonWizard
+        menuGroupId="org.eclipse.wst.web.ui"
+        type="new"
+        wizardId="org.eclipse.jst.servlet.ui.internal.wizard.AddListenerWizard">
+			<enablement>
+				<or>
+					<instanceof
+						value="org.eclipse.jst.j2ee.webapplication.WebApp" />
+					<instanceof
+						value="org.eclipse.jst.j2ee.internal.war.ui.util.WebListenerGroupItemProvider" />
+				</or>
+			</enablement>
+		</commonWizard>
 
 		<!-- The contribution of the New *.jsp wizard to Files, Folders, and Projects 
 			is handled in org.eclipse.jst.jsp.ui. This contribution adds the 
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 32efa47..0232cee 100644
--- a/plugins/org.eclipse.jst.j2ee.web/property_files/web.properties
+++ b/plugins/org.eclipse.jst.j2ee.web/property_files/web.properties
@@ -86,3 +86,4 @@
 ERR_SERVLET_LIST_EMPTY=The list of servlets to be removed cannot be empty.
 ERR_FILTER_LIST_EMPTY=The list of filters to be removed cannot be empty.
 ERR_LISTENER_LIST_EMPTY=The list of listeners to be removed cannot be empty.
+ERR_NO_LISTENER_SELECTED=At least of the application lifecycle listeners must be selected. 
diff --git a/plugins/org.eclipse.jst.j2ee.web/templates/listener.javajet b/plugins/org.eclipse.jst.j2ee.web/templates/listener.javajet
new file mode 100644
index 0000000..4ac97cb
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.web/templates/listener.javajet
@@ -0,0 +1,191 @@
+<%@ jet package="org.eclipse.jst.j2ee.web" 
+	imports="org.eclipse.jst.j2ee.internal.web.operations.* java.util.* " 
+	class="ListenerTemplate" 
+%><%@ include file="listenerHeader.template" %>
+
+<%if (model.isPublic()) {%>public<%}%> <%if (model.isAbstract()) {%>abstract <%}%><%if (model.isFinal()) {%>final <%}
+%>class <%=model.getListenerClassName()%><%
+ String superclassName = model.getSuperclassName();
+ if (superclassName.length() > 0) {%> extends <%=superclassName%><% }
+ List interfaces = new ArrayList();
+ 
+ if (model.implementServletContextListener()) {
+   interfaces.add("ServletContextListener");
+ }
+ if (model.implementServletContextAttributeListener()) {
+   interfaces.add("ServletContextAttributeListener");
+ }
+ if (model.implementHttpSessionListener()) {
+   interfaces.add("HttpSessionListener");
+ }
+ if (model.implementHttpSessionAttributeListener()) {
+   interfaces.add("HttpSessionAttributeListener");
+ }
+ if (model.implementHttpSessionActivationListener()) {
+   interfaces.add("HttpSessionActivationListener");
+ }
+ if (model.implementHttpSessionBindingListener()) {
+   interfaces.add("HttpSessionBindingListener");
+ }
+ if (model.implementServletRequestListener()) {
+   interfaces.add("ServletRequestListener");
+ }
+ if (model.implementServletRequestAttributeListener()) {
+   interfaces.add("ServletRequestAttributeListener");
+ }
+  
+ 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.implementServletContextListener()) { %>
+	/**
+	 * @see javax.servlet.ServletContextListener#contextDestroyed(ServletContextEvent)
+	 */
+	public void contextDestroyed(ServletContextEvent arg0) {
+		// TODO Auto-generated method stub
+	}
+	
+	/**
+	 * @see javax.servlet.ServletContextListener#contextInitialized(ServletContextEvent)
+	 */
+	public void contextInitialized(ServletContextEvent arg0) {
+		// TODO Auto-generated method stub
+	}
+	
+<% }
+ if (model.implementServletContextAttributeListener()) { %>
+	/**
+	 * @see javax.servlet.ServletContextAttributeListener#attributeAdded(ServletContextAttributeEvent)
+	 */
+	public void attributeAdded(ServletContextAttributeEvent arg0) {
+		// TODO Auto-generated method stub
+	}
+
+	/**
+	 * @see javax.servlet.ServletContextAttributeListener#attributeRemoved(ServletContextAttributeEvent)
+	 */
+	public void attributeRemoved(ServletContextAttributeEvent arg0) {
+		// TODO Auto-generated method stub
+	}
+	
+	/**
+	 * @see javax.servlet.ServletContextAttributeListener#attributeReplaced(ServletContextAttributeEvent)
+	 */
+	public void attributeReplaced(ServletContextAttributeEvent arg0) {
+		// TODO Auto-generated method stub
+	}
+	
+<% }
+ if (model.implementHttpSessionListener()) { %>
+	/**
+	 * @see javax.servlet.http.HttpSessionListener#sessionCreated(HttpSessionEvent)
+	 */
+	public void sessionCreated(HttpSessionEvent arg0) {
+		// TODO Auto-generated method stub
+	}
+
+	/**
+	 * @see javax.servlet.http.HttpSessionListener#sessionDestroyed(HttpSessionEvent)
+	 */
+	public void sessionDestroyed(HttpSessionEvent arg0) {
+		// TODO Auto-generated method stub
+	}
+	
+<% }
+ if (model.implementHttpSessionAttributeListener()) { %>
+	/**
+	 * @see javax.servlet.http.HttpSessionAttributeListener#attributeAdded(HttpSessionBindingEvent)
+	 */
+	public void attributeAdded(HttpSessionBindingEvent arg0) {
+		// TODO Auto-generated method stub
+	}
+
+	/**
+	 * @see javax.servlet.http.HttpSessionAttributeListener#attributeRemoved(HttpSessionBindingEvent)
+	 */
+	public void attributeRemoved(HttpSessionBindingEvent arg0) {
+		// TODO Auto-generated method stub
+	}
+
+	/**
+	 * @see javax.servlet.http.HttpSessionAttributeListener#attributeReplaced(HttpSessionBindingEvent)
+	 */
+	public void attributeReplaced(HttpSessionBindingEvent arg0) {
+		// TODO Auto-generated method stub
+	}
+	
+<% }
+ if (model.implementHttpSessionActivationListener()) { %>
+	/**
+	 * @see javax.servlet.http.HttpSessionActivationListener#sessionDidActivate(HttpSessionEvent)
+	 */
+	public void sessionDidActivate(HttpSessionEvent arg0) {
+		// TODO Auto-generated method stub
+	}
+
+	/**
+	 * @see javax.servlet.http.HttpSessionActivationListener#sessionWillPassivate(HttpSessionEvent)
+	 */
+	public void sessionWillPassivate(HttpSessionEvent arg0) {
+		// TODO Auto-generated method stub
+	}
+	
+<% }
+ if (model.implementHttpSessionBindingListener()) { %>
+	/**
+	 * @see javax.servlet.http.HttpSessionBindingListener#valueBound(HttpSessionBindingEvent)
+	 */
+	public void valueBound(HttpSessionBindingEvent arg0) {
+		// TODO Auto-generated method stub
+	}
+
+	/**
+	 * @see javax.servlet.http.HttpSessionBindingListener#valueUnbound(HttpSessionBindingEvent)
+	 */
+	public void valueUnbound(HttpSessionBindingEvent arg0) {
+		// TODO Auto-generated method stub
+	}
+	
+<% }
+ if (model.implementServletRequestListener()) { %>
+	/**
+	 * @see javax.servlet.ServletRequestListener#requestDestroyed(ServletRequestEvent)
+	 */
+	public void requestDestroyed(ServletRequestEvent arg0) {
+		// TODO Auto-generated method stub
+	}
+
+	/**
+	 * @see javax.servlet.ServletRequestListener#requestInitialized(ServletRequestEvent)
+	 */
+	public void requestInitialized(ServletRequestEvent arg0) {
+		// TODO Auto-generated method stub
+	}
+	
+<% }
+ if (model.implementServletRequestAttributeListener()) { %>
+	/**
+	 * @see javax.servlet.ServletRequestAttributeListener#attributeAdded(ServletRequestAttributeEvent)
+	 */
+	public void attributeAdded(ServletRequestAttributeEvent arg0) {
+		// TODO Auto-generated method stub
+	}
+
+	/**
+	 * @see javax.servlet.ServletRequestAttributeListener#attributeRemoved(ServletRequestAttributeEvent)
+	 */
+	public void attributeRemoved(ServletRequestAttributeEvent arg0) {
+		// TODO Auto-generated method stub
+	}
+	
+	/**
+	 * @see javax.servlet.ServletRequestAttributeListener#attributeReplaced(ServletRequestAttributeEvent)
+	 */
+	public void attributeReplaced(ServletRequestAttributeEvent arg0) {
+		// TODO Auto-generated method stub
+	}
+	
+<% } %>
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jst.j2ee.web/templates/listenerHeader.template b/plugins/org.eclipse.jst.j2ee.web/templates/listenerHeader.template
new file mode 100644
index 0000000..e675dc5
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.web/templates/listenerHeader.template
@@ -0,0 +1,43 @@
+<% CreateListenerTemplateModel model = (CreateListenerTemplateModel) argument; 
+if (model.getJavaPackageName()!=null && model.getJavaPackageName()!="") { %>package <%=model.getJavaPackageName()%>;<%}%>
+
+<% if (model.implementServletContextListener()) { %>
+import javax.servlet.ServletContextListener;
+import javax.servlet.ServletContextEvent;
+<% } %>
+<% if (model.implementServletContextAttributeListener()) { %>
+import javax.servlet.ServletContextAttributeListener;
+import javax.servlet.ServletContextAttributeEvent;
+<% } %>
+<% if (model.implementHttpSessionListener()) { %>
+import javax.servlet.http.HttpSessionListener;
+import javax.servlet.http.HttpSessionEvent;
+<% } %>
+<% if (model.implementHttpSessionAttributeListener()) { %>
+import javax.servlet.http.HttpSessionAttributeListener;
+import javax.servlet.http.HttpSessionBindingEvent;
+<% } %>
+<% if (model.implementHttpSessionActivationListener()) { %>
+import javax.servlet.http.HttpSessionActivationListener;
+<% if (!model.implementHttpSessionListener()) { %>
+import javax.servlet.http.HttpSessionEvent;
+<% } } %>
+<% if (model.implementHttpSessionBindingListener()) { %>
+import javax.servlet.http.HttpSessionBindingListener;
+<% if (!model.implementHttpSessionAttributeListener()) { %>
+import javax.servlet.http.HttpSessionBindingEvent;
+<% } } %>
+<% if (model.implementServletRequestListener()) { %>
+import javax.servlet.ServletRequestListener;
+import javax.servlet.ServletRequestEvent;
+<% } %>
+<% if (model.implementServletRequestAttributeListener()) { %>
+import javax.servlet.ServletRequestAttributeListener;
+import javax.servlet.ServletRequestAttributeEvent;
+<% } %>
+
+/**
+ * Application Lifecycle Listener implementation class <%=model.getListenerClassName()%>
+ *
+ */
+ 
\ No newline at end of file
diff --git a/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/AddListenerOperation.java b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/AddListenerOperation.java
new file mode 100644
index 0000000..878985e
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/AddListenerOperation.java
@@ -0,0 +1,245 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.jst.j2ee.internal.web.operations;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+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.application.internal.operations.IAnnotationsDataModel;
+import org.eclipse.jst.j2ee.common.CommonFactory;
+import org.eclipse.jst.j2ee.common.Listener;
+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.WebApp;
+import org.eclipse.jst.javaee.core.JavaeeFactory;
+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, AddListenerOperation 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 application lifecycle listener to
+ * a web app, whether that be an annotated listener or a non annotated listener.  This uses the
+ * NewListenerClassDataModelProvider to retrieve properties set by the user in order to create the custom
+ * listener class.
+ * @see org.eclipse.jst.j2ee.internal.web.operations.NewListenerClassDataModelProvider
+ * 
+ * In the non annotated case, this operation will add the metadata necessary into the web deployment
+ * descriptor. In the annotated case, it will not, it will leave this up to the parsing of the
+ * annotations to build the deployment descriptor artifacts. To actually create the java class for
+ * the listener, the operation uses the NewListenerClassOperation. The NewListenerClassOperation 
+ * shares the same data model provider.
+ * @see org.eclipse.jst.j2ee.internal.web.operations.NewListenerClassOperation
+ * 
+ * Clients may subclass this operation to provide their own behavior on listener creation. The execute
+ * method can be extended to do so. Also, generateListenerMetaData and creteListenerClass are exposed.
+ * 
+ * The use of this class is EXPERIMENTAL and is subject to substantial changes.
+ */
+public class AddListenerOperation 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 AddListenerOperation
+	 */
+	public AddListenerOperation(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 listener class, and then if the listener is not
+	 * annotated, it will create the listener 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 AddListenerOperation#createListenerClass()
+	 * @see AddListenerOperation#generateListenerMetaData(IDataModel, 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 NewListenerClassDataModel
+		boolean useExisting = model.getBooleanProperty(INewListenerClassDataModelProperties.USE_EXISTING_CLASS);
+		String qualifiedClassName = model.getStringProperty(INewJavaClassDataModelProperties.CLASS_NAME);
+		
+		if (!useExisting)
+			qualifiedClassName = createListenerClass();
+
+		// If the listener is not annotated, generate the listener metadata for the DD
+		if (!model.getBooleanProperty(IAnnotationsDataModel.USE_ANNOTATIONS))
+			generateListenerMetaData(model, qualifiedClassName);
+		
+		return OK_STATUS;
+	}
+	
+	/**
+	 * Subclasses may extend this method to add their own creation of the actual listener java class.
+	 * This implementation uses the NewListenerClassOperation which is a subclass of the NewJavaClassOperation.
+	 * The NewListenerClassOperation will use the same NewListenerClassDataModelProvider to retrieve the properties in
+	 * order to create the java class accordingly.  This method will not return null.
+	 * @see NewListenerClassOperation
+	 * @see org.eclipse.jst.j2ee.internal.common.operations.NewJavaClassOperation
+	 * @see NewListenerClassDataModelProvider
+	 * 
+	 * @return String qualified listener class name
+	 */
+	protected String createListenerClass() {
+		//	Create listener java class file using the NewListenerClassOperation. The same data model is shared.
+		NewListenerClassOperation op = new NewListenerClassOperation(model);
+		try {
+			op.execute(new NullProgressMonitor(), null);
+		} catch (Exception e) {
+			Logger.getLogger().log(e);
+		} 
+		// Return the qualified class name of the newly created java class for the listener
+		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 class name
+	 */
+	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 Listener model instance. 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 Listener
+	 * @see AddListenerOperation#createListener(String)
+	 * 
+	 * @param aModel
+	 * @param qualifiedClassName
+	 */
+	protected void generateListenerMetaData(IDataModel aModel, String qualifiedClassName) {
+		// Set up the listener modeled object
+		createListener(qualifiedClassName);
+	}
+	
+	/**
+	 * This method is intended for private use only. This method is used to create the listener
+	 * modeled object, to set any parameters specified in the data model, and then to add the
+	 * listener instance to the web application model. This method does not accept null parameters.
+	 * It will not return null.
+	 * @see AddListenerOperation#generateListenerMetaData(IDataModel, String)
+	 * @see CommonFactory#createListener()
+	 * @see Listener
+	 * 
+	 * @param qualifiedClassName
+	 * @return Listener instance
+	 */
+	private Object createListener(String qualifiedClassName) {
+		Object modelObject = provider.getModelObject();
+		if (modelObject instanceof org.eclipse.jst.j2ee.webapplication.WebApp ){
+			// Create the listener instance and set up the parameters from data model
+			Listener listener = CommonFactory.eINSTANCE.createListener();
+			listener.setListenerClassName(qualifiedClassName);
+
+			// Add the listener to the web application model
+			WebApp webApp = (WebApp) modelObject;
+			webApp.getListeners().add(listener);
+			return listener;
+		} else if (modelObject instanceof org.eclipse.jst.javaee.web.WebApp ){
+			// Create the listener instance and set up the parameters from data model
+			org.eclipse.jst.javaee.core.Listener listener = JavaeeFactory.eINSTANCE.createListener();
+			listener.setListenerClass(qualifiedClassName);
+
+			// Add the listener to the web application model
+			org.eclipse.jst.javaee.web.WebApp webApp = (org.eclipse.jst.javaee.web.WebApp) modelObject;
+			webApp.getListeners().add(listener);	
+			return listener;
+		}
+		
+		return null;
+	}
+	
+	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, IModelProvider.FORCESAVE);
+			}
+			//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/CreateListenerTemplateModel.java b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/CreateListenerTemplateModel.java
new file mode 100644
index 0000000..967b731
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/CreateListenerTemplateModel.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+/*
+ * Created on Aug 6, 2004
+ */
+package org.eclipse.jst.j2ee.internal.web.operations;
+
+import org.eclipse.jst.j2ee.internal.common.operations.INewJavaClassDataModelProperties;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
+
+
+/**
+ * @author kraev
+ */
+public class CreateListenerTemplateModel {
+
+	private IDataModel dataModel = null;
+
+	/**
+	 * Constructor
+	 */
+	public CreateListenerTemplateModel(IDataModel dataModel) {
+		super();
+		this.dataModel = dataModel;
+	}
+
+	public String getListenerClassName() {
+		return getProperty(INewJavaClassDataModelProperties.CLASS_NAME).trim();
+	}
+
+	public String getJavaPackageName() {
+		return getProperty(INewJavaClassDataModelProperties.JAVA_PACKAGE).trim();
+	}
+
+	public String getQualifiedJavaClassName() {
+		return getJavaPackageName() + "." + getListenerClassName(); //$NON-NLS-1$
+	}
+
+	public String getSuperclassName() {
+		return getProperty(INewJavaClassDataModelProperties.SUPERCLASS).trim();
+	}
+
+	public String getListenerName() {
+		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 implementServletContextListener() {
+		return dataModel.getBooleanProperty(INewListenerClassDataModelProperties.SERVLET_CONTEXT_LISTENER);
+	}
+	
+	public boolean implementServletContextAttributeListener() {
+		return dataModel.getBooleanProperty(INewListenerClassDataModelProperties.SERVLET_CONTEXT_ATTRIBUTE_LISTENER);
+	}
+	
+	public boolean implementHttpSessionListener() {
+		return dataModel.getBooleanProperty(INewListenerClassDataModelProperties.HTTP_SESSION_LISTENER);
+	}
+	
+	public boolean implementHttpSessionAttributeListener() {
+		return dataModel.getBooleanProperty(INewListenerClassDataModelProperties.HTTP_SESSION_ATTRIBUTE_LISTENER);
+	}
+	
+	public boolean implementHttpSessionActivationListener() {
+		return dataModel.getBooleanProperty(INewListenerClassDataModelProperties.HTTP_SESSION_ACTIVATION_LISTENER);
+	}
+	
+	public boolean implementHttpSessionBindingListener() {
+		return dataModel.getBooleanProperty(INewListenerClassDataModelProperties.HTTP_SESSION_BINDING_LISTENER);
+	}
+	
+	public boolean implementServletRequestListener() {
+		return dataModel.getBooleanProperty(INewListenerClassDataModelProperties.SERVLET_REQUEST_LISTENER);
+	}
+	
+	public boolean implementServletRequestAttributeListener() {
+		return dataModel.getBooleanProperty(INewListenerClassDataModelProperties.SERVLET_REQUEST_ATTRIBUTE_LISTENER);
+	}
+
+}
diff --git a/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/INewListenerClassDataModelProperties.java b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/INewListenerClassDataModelProperties.java
new file mode 100644
index 0000000..e464714
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/INewListenerClassDataModelProperties.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2005 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.j2ee.internal.web.operations;
+
+import org.eclipse.jst.j2ee.application.internal.operations.IAnnotationsDataModel;
+import org.eclipse.jst.j2ee.internal.common.operations.INewJavaClassDataModelProperties;
+
+public interface INewListenerClassDataModelProperties extends INewJavaClassDataModelProperties, IAnnotationsDataModel {
+	
+	/**
+	 * Optional, boolean property used to specify whether to implement the
+	 * <code>javax.servlet.ServletContextListener</code> interface. 
+	 * The default is false.
+	 */
+	public static final String SERVLET_CONTEXT_LISTENER = "NewListenerClassDataModel.SERVLET_CONTEXT_LISTENER"; //$NON-NLS-1$
+	
+	/**
+	 * Optional, boolean property used to specify whether to implement the
+	 * <code>javax.servlet.ServletContextAttributeListener</code> interface. 
+	 * The default is false.
+	 */
+	public static final String SERVLET_CONTEXT_ATTRIBUTE_LISTENER = "NewListenerClassDataModel.SERVLET_CONTEXT_ATTRIBUTE_LISTENER"; //$NON-NLS-1$
+	
+	/**
+	 * Optional, boolean property used to specify whether to implement the
+	 * <code>javax.servlet.http.HttpSessionListener</code> interface. 
+	 * The default is false.
+	 */
+	public static final String HTTP_SESSION_LISTENER = "NewListenerClassDataModel.HTTP_SESSION_LISTENER"; //$NON-NLS-1$
+	
+	/**
+	 * Optional, boolean property used to specify whether to implement the
+	 * <code>javax.servlet.http.HttpSessionAttributeListener</code> interface. 
+	 * The default is false.
+	 */
+	public static final String HTTP_SESSION_ATTRIBUTE_LISTENER = "NewListenerClassDataModel.HTTP_SESSION_ATTRIBUTE_LISTENER"; //$NON-NLS-1$
+	
+	/**
+	 * Optional, boolean property used to specify whether to implement the
+	 * <code>javax.servlet.http.HttpSessionActivationListener</code> interface. 
+	 * The default is false.
+	 */
+	public static final String HTTP_SESSION_ACTIVATION_LISTENER = "NewListenerClassDataModel.HTTP_SESSION_ACTIVATION_LISTENER"; //$NON-NLS-1$
+	
+	/**
+	 * Optional, boolean property used to specify whether to implement the
+	 * <code>javax.servlet.http.HttpSessionBindingListener</code> interface. 
+	 * The default is false.
+	 */
+	public static final String HTTP_SESSION_BINDING_LISTENER = "NewListenerClassDataModel.HTTP_SESSION_BINDING_LISTENER"; //$NON-NLS-1$
+	
+	/**
+	 * Optional, boolean property used to specify whether to implement the
+	 * <code>javax.servlet.ServletRequestListener</code> interface. 
+	 * The default is false.
+	 */
+	public static final String SERVLET_REQUEST_LISTENER = "NewListenerClassDataModel.SERVLET_REQUEST_LISTENER"; //$NON-NLS-1$
+	
+	/**
+	 * Optional, boolean property used to specify whether to implement the
+	 * <code>javax.servlet.ServletRequestAttributeListener</code> interface. 
+	 * The default is false.
+	 */
+	public static final String SERVLET_REQUEST_ATTRIBUTE_LISTENER = "NewListenerClassDataModel.SERVLET_REQUEST_ATTRIBUTE_LISTENER"; //$NON-NLS-1$
+	
+	/**
+	 * Optional, boolean property used to specify whether or not to generate a new java class.
+	 * The default is false.
+	 */
+	public static final String USE_EXISTING_CLASS = "NewListenerClassDataModel.USE_EXISTING_CLASS"; //$NON-NLS-1$
+	
+}
diff --git a/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/NewListenerClassDataModelProvider.java b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/NewListenerClassDataModelProvider.java
new file mode 100644
index 0000000..7b2ffa1
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/NewListenerClassDataModelProvider.java
@@ -0,0 +1,399 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.jst.j2ee.internal.web.operations;
+
+import java.io.File;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jem.util.emf.workbench.ProjectUtilities;
+import org.eclipse.jst.j2ee.application.internal.operations.IAnnotationsDataModel;
+import org.eclipse.jst.j2ee.internal.J2EEVersionConstants;
+import org.eclipse.jst.j2ee.internal.common.J2EEVersionUtil;
+import org.eclipse.jst.j2ee.internal.common.operations.NewJavaClassDataModelProvider;
+import org.eclipse.jst.j2ee.internal.project.J2EEProjectUtilities;
+import org.eclipse.wst.common.componentcore.internal.operation.IArtifactEditOperationDataModelProperties;
+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;
+
+/**
+ * The NewListenerClassDataModelProvider is a subclass of ArtifactEditOperationDataModelProvider and
+ * follows the IDataModel Operation and Wizard frameworks.
+ * 
+ * @see org.eclipse.wst.common.frameworks.datamodel.IDataModelProvider
+ * @see org.eclipse.wst.common.frameworks.datamodel.IDataModelOperation
+ * 
+ * This data model provider is a subclass of the NewJavaClassDataModelProvider, which stores base
+ * properties necessary in the creation of a default java class.
+ * @see org.eclipse.jst.j2ee.internal.common.operations.NewJavaClassDataModelProvider
+ * 
+ * The NewListenerClassDataModelProvider provides more specific properties for java class creation
+ * that are required in creating a listener java class. The data model provider is used to store
+ * these values for the NewListenerClassOperation.
+ * @see org.eclipse.jst.j2ee.internal.web.operations.INewListenerClassDataModelProperties That
+ *      operation will create the listener java class based on the settings defined here in the data
+ *      model.
+ * @see org.eclipse.jst.j2ee.internal.web.operations.NewListenerClassOperation
+ * 
+ * This data model properties implements the IAnnotationsDataModel to get the USE_ANNOTATIONS
+ * property for determining whether or not to generate an annotated java class.
+ * @see org.eclipse.jst.j2ee.application.internal.operations.IAnnotationsDataModel
+ * 
+ * Clients can subclass this data model provider to cache and provide their own specific attributes.
+ * They should also provide their own validation methods, properties interface, and default values
+ * for the properties they add.
+ * 
+ * The use of this class is EXPERIMENTAL and is subject to substantial changes.
+ */
+public class NewListenerClassDataModelProvider extends NewJavaClassDataModelProvider implements INewListenerClassDataModelProperties {
+
+	/**
+	 * The fully qualified default listener superclass.
+	 */
+	private final static String LISTENER_SUPERCLASS = ""; //$NON-NLS-1$ 
+
+	/**
+	 * The cache of all the interfaces the listener 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 AddListenerOperation to drive the listener creation. It
+	 * will not return null.
+	 * 
+	 * @see IDataModel#getDefaultOperation()
+	 * 
+	 * @return IDataModelOperation AddListenerOperation
+	 */
+	public IDataModelOperation getDefaultOperation() {
+		return new AddListenerOperation(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 listener specific properties defined in this data model
+		Set propertyNames = super.getPropertyNames();
+		propertyNames.add(SERVLET_CONTEXT_LISTENER);
+		propertyNames.add(SERVLET_CONTEXT_ATTRIBUTE_LISTENER);
+		propertyNames.add(HTTP_SESSION_LISTENER);
+		propertyNames.add(HTTP_SESSION_ATTRIBUTE_LISTENER);
+		propertyNames.add(HTTP_SESSION_ACTIVATION_LISTENER);
+		propertyNames.add(HTTP_SESSION_BINDING_LISTENER);
+		propertyNames.add(SERVLET_REQUEST_LISTENER);
+		propertyNames.add(SERVLET_REQUEST_ATTRIBUTE_LISTENER);
+		propertyNames.add(USE_ANNOTATIONS);
+		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. 
+	 * 
+	 * @see NewJavaClassDataModelProvider#getDefaultProperty(String)
+	 * @see IDataModelProvider#getDefaultProperty(String)
+	 * 
+	 * @param propertyName
+	 * @return Object default value of property
+	 */
+	public Object getDefaultProperty(String propertyName) {
+		// Create an annotated listener java class by default
+		if (propertyName.equals(USE_ANNOTATIONS))
+			return shouldDefaultAnnotations();
+		else if (propertyName.equals(SUPERCLASS))
+			return LISTENER_SUPERCLASS;
+		else if (propertyName.equals(USE_EXISTING_CLASS))
+			return Boolean.FALSE;
+		// Otherwise check super for default value for property
+		return super.getDefaultProperty(propertyName);
+	}
+
+	/**
+	 * Subclasses may extend this method to add their own specific behavior when a certain property
+	 * in the data model hierarchy 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 class name, 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);
+		// 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() {
+		//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. 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) && getStringProperty(propertyName).equals(LISTENER_SUPERCLASS))
+			return WTPCommonPlugin.OK_STATUS;
+		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;
+		}
+		if (propIsListener(propertyName)) {
+			return validateListeners();
+		}
+		// Otherwise defer to super to validate the property
+		return super.validate(propertyName);
+	}
+	
+	private boolean propIsListener(String prop) {
+		return INewListenerClassDataModelProperties.SERVLET_CONTEXT_LISTENER.equals(prop) || 
+				INewListenerClassDataModelProperties.SERVLET_CONTEXT_ATTRIBUTE_LISTENER.equals(prop) || 
+				INewListenerClassDataModelProperties.HTTP_SESSION_LISTENER.equals(prop) || 
+				INewListenerClassDataModelProperties.HTTP_SESSION_ATTRIBUTE_LISTENER.equals(prop) || 
+				INewListenerClassDataModelProperties.HTTP_SESSION_ACTIVATION_LISTENER.equals(prop) || 
+				INewListenerClassDataModelProperties.HTTP_SESSION_BINDING_LISTENER.equals(prop) || 
+				INewListenerClassDataModelProperties.SERVLET_REQUEST_LISTENER.equals(prop) || 
+				INewListenerClassDataModelProperties.SERVLET_REQUEST_ATTRIBUTE_LISTENER.equals(prop);
+	}
+	
+	/**
+	 * Checks if at least one of the application lifecycle listeners is selected. 
+	 */
+	private IStatus validateListeners() {
+		boolean atLeastOneSelected = 
+			getBooleanProperty(INewListenerClassDataModelProperties.SERVLET_CONTEXT_LISTENER) || 
+			getBooleanProperty(INewListenerClassDataModelProperties.SERVLET_CONTEXT_ATTRIBUTE_LISTENER) || 
+			getBooleanProperty(INewListenerClassDataModelProperties.HTTP_SESSION_LISTENER) || 
+			getBooleanProperty(INewListenerClassDataModelProperties.HTTP_SESSION_ATTRIBUTE_LISTENER) || 
+			getBooleanProperty(INewListenerClassDataModelProperties.HTTP_SESSION_ACTIVATION_LISTENER) || 
+			getBooleanProperty(INewListenerClassDataModelProperties.HTTP_SESSION_BINDING_LISTENER) || 
+			getBooleanProperty(INewListenerClassDataModelProperties.SERVLET_REQUEST_LISTENER) || 
+			getBooleanProperty(INewListenerClassDataModelProperties.SERVLET_REQUEST_ATTRIBUTE_LISTENER);
+		
+		if (atLeastOneSelected) {
+			return WTPCommonPlugin.OK_STATUS;
+		} else {
+			String msg = WebMessages.ERR_NO_LISTENER_SELECTED;
+			return WTPCommonPlugin.createErrorStatus(msg);
+		}
+	}
+
+	/**
+	 * 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 parameter. It will not return
+	 * null.
+	 * 
+	 * @see NewListenerClassDataModelProvider#validateInitParamList(List)
+	 * @see NewListenerClassDataModelProvider#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 NewListenerClassDataModelProvider#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;
+	}
+
+	/**
+	 * @return boolean should the default annotations be true?
+	 */
+	private static Boolean shouldDefaultAnnotations() {
+		if (useAnnotations)
+			return Boolean.TRUE;
+		return Boolean.FALSE;
+	}
+}
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
new file mode 100644
index 0000000..9fb1d84
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/NewListenerClassOperation.java
@@ -0,0 +1,422 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.jst.j2ee.internal.web.operations;
+
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
+import java.util.Set;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.emf.codegen.jet.JETEmitter;
+import org.eclipse.emf.codegen.jet.JETException;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaModelMarker;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaModelException;
+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.common.internal.annotations.controller.AnnotationsControllerManager.Descriptor;
+import org.eclipse.jst.j2ee.application.internal.operations.IAnnotationsDataModel;
+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.jst.j2ee.project.facet.IJ2EEFacetConstants;
+import org.eclipse.jst.j2ee.web.project.facet.WebFacetUtils;
+import org.eclipse.wst.common.componentcore.ComponentCore;
+import org.eclipse.wst.common.componentcore.datamodel.FacetInstallDataModelProvider;
+import org.eclipse.wst.common.componentcore.datamodel.FacetProjectCreationDataModelProvider;
+import org.eclipse.wst.common.componentcore.datamodel.properties.IFacetDataModelProperties;
+import org.eclipse.wst.common.componentcore.datamodel.properties.IFacetProjectCreationDataModelProperties;
+import org.eclipse.wst.common.componentcore.datamodel.properties.IFacetProjectCreationDataModelProperties.FacetDataModelMap;
+import org.eclipse.wst.common.componentcore.internal.operation.ArtifactEditProviderOperation;
+import org.eclipse.wst.common.componentcore.internal.operation.IArtifactEditOperationDataModelProperties;
+import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
+import org.eclipse.wst.common.frameworks.datamodel.AbstractDataModelOperation;
+import org.eclipse.wst.common.frameworks.datamodel.DataModelFactory;
+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;
+import org.eclipse.wst.common.project.facet.core.IFacetedProject;
+import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager;
+
+/**
+ * The NewListenerClassOperation 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 listener specific java
+ * class generation.
+ * @see org.eclipse.wst.common.componentcore.internal.operation.ArtifactEditProviderOperation
+ * 
+ * This operation is used by the AddListenerOperation to generate either an
+ * annotated or non annotated java class for an added application lifecycle listener. 
+ * It shares the NewListenerClassDataModelProvider with the AddListenerOperation to 
+ * store the appropriate properties required to generate the new listener.
+ * @see org.eclipse.jst.j2ee.internal.web.operations.AddListenerOperation
+ * @see org.eclipse.jst.j2ee.internal.web.operations.NewListenerClassDataModelProvider
+ * 
+ * In the annotated case, a WTPJetEmitter listener template is created and used
+ * to generate the listener java class with the embedded annotated tags.
+ * @see org.eclipse.jst.j2ee.internal.project.WTPJETEmitter
+ * @see org.eclipse.jst.j2ee.internal.web.operations.CreateListenerTemplateModel
+ * 
+ * In the non annotated case, the same emitter is used to create the class with
+ * the non annotated listener template so the annotated tags are omitted.
+ * 
+ * Subclasses may extend this operation to provide their own specific listener
+ * 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 NewListenerClassOperation extends AbstractDataModelOperation {
+
+	/**
+	 * XDoclet facet constants
+	 */
+	private static final String JST_WEB_XDOCLET_VERSION = "1.2.3"; //$NON-NLS-1$
+
+	/**
+	 * The extension name for a java class
+	 */
+	private static final String DOT_JAVA = ".java"; //$NON-NLS-1$
+
+	/**
+	 * platform plugin beginning for URI string
+	 */
+	// private static final String PLATFORM_PLUGIN = "platform:/plugin/";
+	// //$NON-NLS-1$
+	/**
+	 * variable for the web plugin
+	 */
+	protected static final String WEB_PLUGIN = "WEB_PLUGIN"; //$NON-NLS-1$
+
+	/**
+	 * folder location of the listener creation templates directory
+	 */
+	protected static final String TEMPLATE_FILE = "/templates/listener.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 meta data 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
+	 * NewListenerClassOperation. An instance of the NewListenerClassDataModel
+	 * should be passed in. This does not accept null parameter. It will not
+	 * return null.
+	 * 
+	 * @see ArtifactEditProviderOperation#ArtifactEditProviderOperation(IDataModel)
+	 * @see NewListenerClassDataModel
+	 * 
+	 * @param dataModel
+	 * @return NewListenerClassOperation
+	 */
+	public NewListenerClassOperation(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 if using annotations, will use
+	 * templates to generate an annotated listener java class, or if it is not
+	 * annotated, the listener java class file will be created without the
+	 * annotated tags 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 NewListenerClassOperation#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 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 listener java class file. This implementation
+	 * uses the creation of a CreateListenerTemplateModel 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 CreateListenerTemplateModel
+	 * @see NewListenerClassOperation#generateTemplateSource(CreateListenerTemplateModel, IProgressMonitor)
+	 * 
+	 * @param monitor
+	 * @param fragment
+	 * @throws CoreException
+	 * @throws WFTWrappedException
+	 */
+	protected void generateUsingTemplates(IProgressMonitor monitor, IPackageFragment fragment) throws WFTWrappedException, CoreException {
+		// Create the listener template model
+		CreateListenerTemplateModel tempModel = createTemplateModel();
+		IProject project = getTargetProject();
+		String source;
+		// Using the WTPJetEmitter, generate the java source based on the listener template model
+		try {
+			source = generateTemplateSource(tempModel, monitor);
+		} catch (Exception e) {
+			throw new WFTWrappedException(e);
+		}
+		if (fragment != null) {
+			// Create the java file
+			String javaFileName = tempModel.getListenerClassName() + 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);
+		}
+		
+		// Add the xdoclet facet, if necessary, for xdoclet listener creation
+		try {
+			installXDocletFacetIfNecessary(monitor, project);
+		} catch (Exception e) {
+			throw new WFTWrappedException(e);
+		}
+	}
+
+	/**
+	 * This method is intended for internal use only. This will add an webdoclet facet to the project.
+	 * 
+	 * @throws CoreException 
+	 * @throws ExecutionException 
+	 */
+	private void installXDocletFacet(IProgressMonitor monitor, IProject project) throws CoreException, ExecutionException {
+		IFacetedProject facetedProject = ProjectFacetsManager.create(project);
+		Set fixedFacets = facetedProject.getFixedProjectFacets();
+		IDataModel dm = DataModelFactory.createDataModel(new FacetInstallDataModelProvider());
+		dm.setProperty(IFacetDataModelProperties.FACET_ID, IJ2EEFacetConstants.DYNAMIC_WEB_XDOCLET);
+		dm.setProperty(IFacetDataModelProperties.FACET_PROJECT_NAME, project.getName());
+		dm.setProperty(IFacetDataModelProperties.FACET_VERSION_STR, JST_WEB_XDOCLET_VERSION);
+		IDataModel fdm = DataModelFactory.createDataModel(new FacetProjectCreationDataModelProvider());
+		fdm.setProperty(IFacetProjectCreationDataModelProperties.FACET_PROJECT_NAME, project.getName());
+
+		FacetDataModelMap map = (FacetDataModelMap) fdm.getProperty(IFacetProjectCreationDataModelProperties.FACET_DM_MAP);
+		map.add(dm);
+
+		fdm.getDefaultOperation().execute(monitor, null);
+		facetedProject.setFixedProjectFacets(fixedFacets);
+	}
+	
+	/**
+	 * This method is intended for internal use only. This will check to see if it needs to add an 
+	 * webdoclet facet to the project.
+	 * 
+	 * @throws CoreException 
+	 * @throws ExecutionException 
+	 */
+	private void installXDocletFacetIfNecessary(IProgressMonitor monitor, IProject project) throws CoreException, ExecutionException {
+
+		// If not using annotations, ignore the xdoclet facet
+		if (!model.getBooleanProperty(IAnnotationsDataModel.USE_ANNOTATIONS))
+			return;
+		
+		// If an extended annotations processor is added, ignore the default xdoclet one
+		Descriptor descriptor = AnnotationsControllerManager.INSTANCE.getDescriptor(getTargetComponent().getProject());
+		if (descriptor != null)
+			return;
+
+		// Otherwise check and see if the xdoclet facet is on the project yet
+		IFacetedProject facetedProject = ProjectFacetsManager.create(project);
+		if (!facetedProject.hasProjectFacet(WebFacetUtils.WEB_XDOCLET_FACET))
+			return;
+			
+		// Install xdoclet facet
+		installXDocletFacet(monitor, project);
+	}
+
+	/**
+	 * This method is intended for internal use only. This will use the
+	 * WTPJETEmitter to create an annotated java file based on the passed in
+	 * listener 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 NewListenerClassOperation#generateUsingTemplates(IProgressMonitor,
+	 *      IPackageFragment)
+	 * @see JETEmitter#generate(org.eclipse.core.runtime.IProgressMonitor,
+	 *      java.lang.Object[])
+	 * @see CreateListenerTemplateModel
+	 * 
+	 * @param tempModel
+	 * @param monitor
+	 * @return String the source for the java file
+	 * @throws JETException
+	 */
+	private String generateTemplateSource(CreateListenerTemplateModel tempModel, IProgressMonitor monitor) throws JETException {
+		URL templateURL = WebPlugin.getDefault().find(new Path(TEMPLATE_FILE));
+		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 is intended for internal use only. This method will create an
+	 * instance of the CreateListenerTemplateModel to be used in conjunction
+	 * with the WTPJETEmitter. This method will not return null.
+	 * 
+	 * @see CreateListenerTemplateModel
+	 * @see NewListenerClassOperation#generateUsingTemplates(IProgressMonitor,
+	 *      IPackageFragment)
+	 * 
+	 * @return CreateListenerTemplateModel
+	 */
+	private CreateListenerTemplateModel createTemplateModel() {
+		// Create the CreateListenerTemplateModel instance with the new listener
+		// class data model
+		CreateListenerTemplateModel templateModel = new CreateListenerTemplateModel(model);
+		return templateModel;
+	}
+
+	/**
+	 * 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);
+	}
+	private IVirtualComponent getTargetComponent() {
+		return ComponentCore.createComponent(getTargetProject());
+	}	
+	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/WebMessages.java b/plugins/org.eclipse.jst.j2ee.web/web/org/eclipse/jst/j2ee/internal/web/operations/WebMessages.java
index 6a18bdb..c9c5dfc 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
@@ -107,6 +107,7 @@
 	public static String ERR_SERVLET_LIST_EMPTY;
 	public static String ERR_FILTER_LIST_EMPTY;
 	public static String ERR_LISTENER_LIST_EMPTY;
+	public static String ERR_NO_LISTENER_SELECTED;
 
 	static {
 		NLS.initializeMessages(BUNDLE_NAME, WebMessages.class);
diff --git a/plugins/org.eclipse.jst.servlet.ui/icons/full/ctool16/newlistener_wiz.gif b/plugins/org.eclipse.jst.servlet.ui/icons/full/ctool16/newlistener_wiz.gif
new file mode 100644
index 0000000..09f2a89
--- /dev/null
+++ b/plugins/org.eclipse.jst.servlet.ui/icons/full/ctool16/newlistener_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 4626821..48a20d2 100644
--- a/plugins/org.eclipse.jst.servlet.ui/plugin.properties
+++ b/plugins/org.eclipse.jst.servlet.ui/plugin.properties
@@ -41,4 +41,7 @@
 web-project-wizard-description = Create a Web project
 webAppLibrariesContainerName = Web App Libraries
 
+ListenerWebRegionWizard.name=Listener
+ListenerWebRegionWizard.description=Create a new Application Lifecycle Listener
+
 enhanced.java.for.web.name=Enhanced Java Rendering for Web
diff --git a/plugins/org.eclipse.jst.servlet.ui/plugin.xml b/plugins/org.eclipse.jst.servlet.ui/plugin.xml
index 543d638..1d379ef 100644
--- a/plugins/org.eclipse.jst.servlet.ui/plugin.xml
+++ b/plugins/org.eclipse.jst.servlet.ui/plugin.xml
@@ -60,7 +60,19 @@
          <description>
             %ServletWebRegionWizard.description
          </description>
-      </wizard>      
+      </wizard>
+      
+      <!--new listener contribution-->
+ 	  <wizard
+            name="%ListenerWebRegionWizard.name"
+            icon="icons/full/ctool16/newlistener_wiz.gif"
+            category="org.eclipse.wst.web.ui"
+            class="org.eclipse.jst.servlet.ui.internal.wizard.AddListenerWizard"
+            id="org.eclipse.jst.servlet.ui.internal.wizard.AddListenerWizard">
+         <description>
+            %ListenerWebRegionWizard.description
+         </description>
+      </wizard>
     </extension>
       
    <extension
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 20e2799..4151250 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
@@ -47,6 +47,17 @@
 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. 
+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
+ADD_LISTENER_WIZARD_LIFECYCLE=Lifecycle
+ADD_LISTENER_WIZARD_CHANGES_TO_ATTRIBUTES=Changes to attributes
+ADD_LISTENER_WIZARD_SESSION_MIGRATION=Session migration
+ADD_LISTENER_WIZARD_OBJECT_BINDING=Object binding
+
 ADD_BUTTON_LABEL=Add...
 EDIT_BUTTON_LABEL=Edit...
 REMOVE_BUTTON_LABEL=Remove
@@ -84,6 +95,8 @@
 VALUE_LABEL=Value
 BROWSE_BUTTON_LABEL=Browse...
 REMOVE_BUTTON=Remove
+SELECT_ALL_BUTTON=Select &All
+CLEAR_BUTTON=&Clear
 
 NEW_JAVA_CLASS_DESTINATION_WIZARD_PAGE_DESC=Specify class file destination.
 NEW_JAVA_CLASS_OPTIONS_WIZARD_PAGE_DESC=Specify modifiers, interfaces to implement, and method stubs to generate.
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 7b837f7..a771722 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
@@ -103,12 +103,25 @@
 	public static String WEB_CONT_PAGE_DESCRIPTION;
 	public static String JAVA_CLASS_INTERFACES_LABEL;
 	public static String WEBCONTENT;
+	public static String SELECT_ALL_BUTTON;
+	public static String CLEAR_BUTTON;
 	
 	public static String Compressed_Libraries;
 	public static String Compressed_JavaResources;
 	
 	public static String ConvertToWebTitle;
 	public static String SelectWebVersion;
+	
+	public static String ADD_LISTENER_WIZARD_WINDOW_TITLE;
+	public static String ADD_LISTENER_WIZARD_PAGE_TITLE;
+	public static String ADD_LISTENER_WIZARD_PAGE_DESC;
+	public static String ADD_LISTENER_WIZARD_SERVLET_CONTEXT_EVENTS;
+	public static String ADD_LISTENER_WIZARD_HTTP_SESSION_EVENTS;
+	public static String ADD_LISTENER_WIZARD_SERVLET_REQUEST_EVENTS;
+	public static String ADD_LISTENER_WIZARD_LIFECYCLE;
+	public static String ADD_LISTENER_WIZARD_CHANGES_TO_ATTRIBUTES;
+	public static String ADD_LISTENER_WIZARD_SESSION_MIGRATION;
+	public static String ADD_LISTENER_WIZARD_OBJECT_BINDING;
 
 	static {
 		NLS.initializeMessages(BUNDLE_NAME, WEBUIMessages.class);
diff --git a/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/AddListenerWizard.java b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/AddListenerWizard.java
new file mode 100644
index 0000000..dddba84
--- /dev/null
+++ b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/AddListenerWizard.java
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+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.project.J2EEProjectUtilities;
+import org.eclipse.jst.j2ee.internal.web.operations.NewListenerClassDataModelProvider;
+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 application lifecycle listener wizard
+ */
+public class AddListenerWizard extends NewWebWizard {
+	private static final String PAGE_ONE = "pageOne"; //$NON-NLS-1$
+	private static final String PAGE_TWO = "pageTwo"; //$NON-NLS-1$
+	/**
+	 * @param model
+	 */
+	public AddListenerWizard(IDataModel model) {
+		super(model);
+		setWindowTitle(IWebWizardConstants.ADD_LISTENER_WIZARD_WINDOW_TITLE);
+		setDefaultPageImageDescriptor(getListenerWizBan());
+	}
+	
+	public AddListenerWizard() {
+	    this(null);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.Wizard#addPages()
+	 */
+	public void doAddPages() {
+		NewListenerClassWizardPage page1 = new NewListenerClassWizardPage(
+				getDataModel(), 
+				PAGE_ONE,
+				IWebWizardConstants.NEW_JAVA_CLASS_DESTINATION_WIZARD_PAGE_DESC,
+				IWebWizardConstants.ADD_LISTENER_WIZARD_PAGE_TITLE, J2EEProjectUtilities.DYNAMIC_WEB);
+//		page1.setInfopopID(IWebUIContextIds.WEBEDITOR_SERVLET_PAGE_ADD_SERVLET_WIZARD_1);
+		addPage(page1);
+		AddListenerWizardPage page2 = new AddListenerWizardPage(getDataModel(), PAGE_TWO);
+//		page2.setInfopopID(IWebUIContextIds.WEBEDITOR_SERVLET_PAGE_ADD_SERVLET_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();
+	}
+	
+	protected void postPerformFinish() throws InvocationTargetException {
+		//open new listener class in java editor
+		WebArtifactEdit artifactEdit = null;
+		try {
+			String className = getDataModel().getStringProperty(INewJavaClassDataModelProperties.QUALIFIED_CLASS_NAME);
+			IProject p = (IProject) getDataModel().getProperty(INewJavaClassDataModelProperties.PROJECT);
+			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);
+					}
+				}
+			});
+		}
+	}
+
+	protected IDataModelProvider getDefaultProvider() {
+		return new NewListenerClassDataModelProvider();
+	}
+	
+	private ImageDescriptor getListenerWizBan() {
+		URL url = (URL) J2EEPlugin.getDefault().getImage("newlistener_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/AddListenerWizardPage.java b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/AddListenerWizardPage.java
new file mode 100644
index 0000000..21151b8
--- /dev/null
+++ b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/AddListenerWizardPage.java
@@ -0,0 +1,202 @@
+package org.eclipse.jst.servlet.ui.internal.wizard;
+
+import org.eclipse.jdt.internal.ui.JavaPluginImages;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jst.j2ee.internal.web.operations.INewListenerClassDataModelProperties;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+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.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
+import org.eclipse.wst.common.frameworks.internal.datamodel.ui.DataModelWizardPage;
+
+public class AddListenerWizardPage extends DataModelWizardPage {
+	
+	private static final Image IMG_INTERFACE = JavaPluginImages.get(JavaPluginImages.IMG_OBJS_INTERFACE);
+	
+	public AddListenerWizardPage(IDataModel model, String pageName) {
+		super(model, pageName);
+		setDescription(IWebWizardConstants.ADD_LISTENER_WIZARD_PAGE_DESC);
+		setTitle(IWebWizardConstants.ADD_LISTENER_WIZARD_PAGE_TITLE);
+	}
+
+	@Override
+	protected Composite createTopLevelComposite(Composite parent) {
+		Composite composite = new Composite(parent, SWT.NONE);
+		composite.setLayout(new GridLayout(1, false));
+		GridData data = new GridData(GridData.FILL_BOTH);
+		data.widthHint = 300;
+		composite.setLayoutData(data);
+		
+		createServletContextEvents(composite);
+		createHttpSessionEvents(composite);
+		createServletRequestEvents(composite);
+		createSelectAllGroup(composite);
+		
+		Dialog.applyDialogFont(composite);
+		
+		return composite;
+	}
+
+	@Override
+	protected String[] getValidationPropertyNames() {
+		return new String[] { 
+				INewListenerClassDataModelProperties.SERVLET_CONTEXT_LISTENER, 
+				INewListenerClassDataModelProperties.SERVLET_CONTEXT_ATTRIBUTE_LISTENER, 
+				INewListenerClassDataModelProperties.HTTP_SESSION_LISTENER, 
+				INewListenerClassDataModelProperties.HTTP_SESSION_ATTRIBUTE_LISTENER, 
+				INewListenerClassDataModelProperties.HTTP_SESSION_ACTIVATION_LISTENER, 
+				INewListenerClassDataModelProperties.HTTP_SESSION_BINDING_LISTENER, 
+				INewListenerClassDataModelProperties.SERVLET_REQUEST_LISTENER, 
+				INewListenerClassDataModelProperties.SERVLET_REQUEST_ATTRIBUTE_LISTENER
+		};
+	}
+	
+	private void createServletContextEvents(Composite parent) {
+		Group group = createGroup(parent, IWebWizardConstants.ADD_LISTENER_WIZARD_SERVLET_CONTEXT_EVENTS);
+
+		createEventListenerRow(group, 
+				IWebWizardConstants.ADD_LISTENER_WIZARD_LIFECYCLE, 
+				"javax.servlet.ServletContextListener", //$NON-NLS-1$
+				INewListenerClassDataModelProperties.SERVLET_CONTEXT_LISTENER);
+
+		createEventListenerRow(group, 
+				IWebWizardConstants.ADD_LISTENER_WIZARD_CHANGES_TO_ATTRIBUTES, 
+				"javax.servlet.ServletContextAttributeListener", //$NON-NLS-1$
+				INewListenerClassDataModelProperties.SERVLET_CONTEXT_ATTRIBUTE_LISTENER);
+	}
+	
+	private void createHttpSessionEvents(Composite parent) {
+		Group group = createGroup(parent, IWebWizardConstants.ADD_LISTENER_WIZARD_HTTP_SESSION_EVENTS);
+		
+		createEventListenerRow(group, 
+				IWebWizardConstants.ADD_LISTENER_WIZARD_LIFECYCLE, 
+				"javax.servlet.http.HttpSessionListener", //$NON-NLS-1$
+				INewListenerClassDataModelProperties.HTTP_SESSION_LISTENER);
+		
+		createEventListenerRow(group, 
+				IWebWizardConstants.ADD_LISTENER_WIZARD_CHANGES_TO_ATTRIBUTES, 
+				"javax.servlet.http.HttpSessionAttributeListener", //$NON-NLS-1$
+				INewListenerClassDataModelProperties.HTTP_SESSION_ATTRIBUTE_LISTENER);
+		
+		createEventListenerRow(group, 
+				IWebWizardConstants.ADD_LISTENER_WIZARD_SESSION_MIGRATION, 
+				"javax.servlet.http.HttpSessionActivationListener", //$NON-NLS-1$
+				INewListenerClassDataModelProperties.HTTP_SESSION_ACTIVATION_LISTENER);
+		
+		createEventListenerRow(group, 
+				IWebWizardConstants.ADD_LISTENER_WIZARD_OBJECT_BINDING, 
+				"javax.servlet.http.HttpSessionBindingListener", //$NON-NLS-1$
+				INewListenerClassDataModelProperties.HTTP_SESSION_BINDING_LISTENER);
+	}
+	
+	private void createServletRequestEvents(Composite parent) {
+		Group group = createGroup(parent, IWebWizardConstants.ADD_LISTENER_WIZARD_SERVLET_REQUEST_EVENTS);
+		
+		createEventListenerRow(group, 
+				IWebWizardConstants.ADD_LISTENER_WIZARD_LIFECYCLE, 
+				"javax.servlet.http.ServletRequestListener", //$NON-NLS-1$
+				INewListenerClassDataModelProperties.SERVLET_REQUEST_LISTENER);
+
+		createEventListenerRow(group, 
+				IWebWizardConstants.ADD_LISTENER_WIZARD_CHANGES_TO_ATTRIBUTES, 
+				"javax.servlet.http.ServletRequestAttributeListener", //$NON-NLS-1$
+				INewListenerClassDataModelProperties.SERVLET_REQUEST_ATTRIBUTE_LISTENER);
+	}
+	
+	private Group createGroup(Composite parent, String text) {
+		Group group = new Group(parent, SWT.NONE);
+		
+		group.setLayout(new GridLayout(3, false));
+		group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		group.setText(text);
+		
+		return group;
+	}
+	
+	private void createEventListenerRow(Composite parent, String event, String listener, String property) {
+		createCheckbox(parent, event, property);
+		createInterfaceIcon(parent);
+		createInterfaceLabel(parent, listener);
+	}
+	
+	private Button createCheckbox(Composite parent, String text, String property) {
+		Button button = new Button(parent, SWT.CHECK);
+		
+		button.setText(text);
+		button.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));
+		synchHelper.synchCheckbox(button, property, null);
+		
+		return button;
+	}
+	
+	private Label createInterfaceIcon(Composite parent) {
+		GridData data = new GridData();
+		data.horizontalIndent = 50;
+
+		Label label = new Label(parent, SWT.RIGHT);
+		label.setImage(IMG_INTERFACE);
+		label.setLayoutData(data);
+		
+		return label;
+	}
+	
+	private Label createInterfaceLabel(Composite parent, String text) {
+		Label label = new Label(parent, SWT.LEFT);
+		
+		label.setText(text);
+		
+		return label;
+	}
+
+	private void createSelectAllGroup(Composite parent) {
+		Composite composite = new Composite(parent, SWT.NONE);
+		composite.setLayout(new GridLayout(2, false));
+		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		
+		Button selectAll = new Button(composite, SWT.PUSH);
+		selectAll.setText(IWebWizardConstants.SELECT_ALL_BUTTON);
+		selectAll.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				handleSelectAll();
+			}
+		});
+		
+		Button clear = new Button(composite, SWT.PUSH);
+		clear.setText(IWebWizardConstants.CLEAR_BUTTON);
+		clear.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				handleSelectNone();
+			}
+		});
+	}
+
+	private void handleSelectAll() {
+		model.setBooleanProperty(INewListenerClassDataModelProperties.SERVLET_CONTEXT_LISTENER, true);
+		model.setBooleanProperty(INewListenerClassDataModelProperties.SERVLET_CONTEXT_ATTRIBUTE_LISTENER, true);
+		model.setBooleanProperty(INewListenerClassDataModelProperties.HTTP_SESSION_LISTENER, true);
+		model.setBooleanProperty(INewListenerClassDataModelProperties.HTTP_SESSION_ATTRIBUTE_LISTENER, true);
+		model.setBooleanProperty(INewListenerClassDataModelProperties.HTTP_SESSION_ACTIVATION_LISTENER, true);
+		model.setBooleanProperty(INewListenerClassDataModelProperties.HTTP_SESSION_BINDING_LISTENER, true);
+		model.setBooleanProperty(INewListenerClassDataModelProperties.SERVLET_REQUEST_LISTENER, true);
+		model.setBooleanProperty(INewListenerClassDataModelProperties.SERVLET_REQUEST_ATTRIBUTE_LISTENER, true);
+	}
+
+	private void handleSelectNone() {
+		model.setBooleanProperty(INewListenerClassDataModelProperties.SERVLET_CONTEXT_LISTENER, false);
+		model.setBooleanProperty(INewListenerClassDataModelProperties.SERVLET_CONTEXT_ATTRIBUTE_LISTENER, false);
+		model.setBooleanProperty(INewListenerClassDataModelProperties.HTTP_SESSION_LISTENER, false);
+		model.setBooleanProperty(INewListenerClassDataModelProperties.HTTP_SESSION_ATTRIBUTE_LISTENER, false);
+		model.setBooleanProperty(INewListenerClassDataModelProperties.HTTP_SESSION_ACTIVATION_LISTENER, false);
+		model.setBooleanProperty(INewListenerClassDataModelProperties.HTTP_SESSION_BINDING_LISTENER, false);
+		model.setBooleanProperty(INewListenerClassDataModelProperties.SERVLET_REQUEST_LISTENER, false);
+		model.setBooleanProperty(INewListenerClassDataModelProperties.SERVLET_REQUEST_ATTRIBUTE_LISTENER, false);
+	}
+
+}
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 592c6dc..9f8e710 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
@@ -36,6 +36,18 @@
 	public final static String SERVLET_PACKAGE_LABEL = WEBUIMessages.SERVLET_PACKAGE_LABEL;
 	public final static String SERVLET_NAME_LABEL = WEBUIMessages.SERVLET_NAME_LABEL;
 
+	// AddListenerWizard
+	public final static String ADD_LISTENER_WIZARD_WINDOW_TITLE = WEBUIMessages.ADD_LISTENER_WIZARD_WINDOW_TITLE;
+	public final static String ADD_LISTENER_WIZARD_PAGE_TITLE = WEBUIMessages.ADD_LISTENER_WIZARD_PAGE_TITLE;
+	public final static String ADD_LISTENER_WIZARD_PAGE_DESC = WEBUIMessages.ADD_LISTENER_WIZARD_PAGE_DESC;
+	
+	public final static String ADD_LISTENER_WIZARD_SERVLET_CONTEXT_EVENTS = WEBUIMessages.ADD_LISTENER_WIZARD_SERVLET_CONTEXT_EVENTS;
+	public final static String ADD_LISTENER_WIZARD_HTTP_SESSION_EVENTS = WEBUIMessages.ADD_LISTENER_WIZARD_HTTP_SESSION_EVENTS;
+	public final static String ADD_LISTENER_WIZARD_SERVLET_REQUEST_EVENTS = WEBUIMessages.ADD_LISTENER_WIZARD_SERVLET_REQUEST_EVENTS;
+	public final static String ADD_LISTENER_WIZARD_LIFECYCLE = WEBUIMessages.ADD_LISTENER_WIZARD_LIFECYCLE;
+	public final static String ADD_LISTENER_WIZARD_CHANGES_TO_ATTRIBUTES = WEBUIMessages.ADD_LISTENER_WIZARD_CHANGES_TO_ATTRIBUTES;
+	public final static String ADD_LISTENER_WIZARD_SESSION_MIGRATION = WEBUIMessages.ADD_LISTENER_WIZARD_SESSION_MIGRATION;
+	public final static String ADD_LISTENER_WIZARD_OBJECT_BINDING = WEBUIMessages.ADD_LISTENER_WIZARD_OBJECT_BINDING;
 	
 	// common
 	public final static String ADD_BUTTON_LABEL = WEBUIMessages.ADD_BUTTON_LABEL;
@@ -76,6 +88,9 @@
 	public final static String EMPTY_STRING = ""; //$NON-NLS-1$
 	public final static String BROWSE_BUTTON_LABEL = WEBUIMessages.BROWSE_BUTTON_LABEL;
 	public static final String REMOVE_BUTTON = WEBUIMessages.REMOVE_BUTTON;
+	public final static String SELECT_ALL_BUTTON = WEBUIMessages.SELECT_ALL_BUTTON;
+	public final static String CLEAR_BUTTON = WEBUIMessages.CLEAR_BUTTON;
+	
     
 	public final static String NEW_JAVA_CLASS_DESTINATION_WIZARD_PAGE_DESC = WEBUIMessages.NEW_JAVA_CLASS_DESTINATION_WIZARD_PAGE_DESC;
 	public final static String NEW_JAVA_CLASS_OPTIONS_WIZARD_PAGE_DESC = WEBUIMessages.NEW_JAVA_CLASS_OPTIONS_WIZARD_PAGE_DESC;
diff --git a/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/NewListenerClassWizardPage.java b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/NewListenerClassWizardPage.java
new file mode 100644
index 0000000..29a33d0
--- /dev/null
+++ b/plugins/org.eclipse.jst.servlet.ui/servlet_ui/org/eclipse/jst/servlet/ui/internal/wizard/NewListenerClassWizardPage.java
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * 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 org.eclipse.core.resources.IProject;
+import org.eclipse.jem.util.emf.workbench.ProjectUtilities;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jst.j2ee.internal.common.operations.INewJavaClassDataModelProperties;
+import org.eclipse.jst.j2ee.internal.war.ui.util.WebListenerGroupItemProvider;
+import org.eclipse.jst.j2ee.internal.web.operations.INewListenerClassDataModelProperties;
+import org.eclipse.jst.j2ee.internal.wizard.NewJavaClassWizardPage;
+import org.eclipse.jst.j2ee.webapplication.WebApp;
+import org.eclipse.jst.servlet.ui.internal.navigator.CompressedJavaProject;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
+
+public class NewListenerClassWizardPage extends NewJavaClassWizardPage {
+
+//	private AnnotationsStandaloneGroup annotationsGroup = null;
+	private Button existingClassButton;
+	private Label existingClassLabel;
+	private Text existingClassText;
+	private Button existingButton;
+	private final static String[] JSPEXTENSIONS = { "jsp" }; //$NON-NLS-1$
+	
+	
+	public NewListenerClassWizardPage(IDataModel model, String pageName, String pageDesc, String pageTitle, String moduleType) {
+		super(model, pageName, pageDesc, pageTitle, moduleType);
+	}
+	
+	/**
+	 * Create annotations group and set default enablement
+	 */
+//	private void createAnnotationsGroup(Composite parent) {
+//		if (isWebDocletProject()) {
+//			annotationsGroup = new AnnotationsStandaloneGroup(parent, model, J2EEProjectUtilities.EJB.equals(projectType),
+//					J2EEProjectUtilities.DYNAMIC_WEB.equals(projectType));
+//			if (!model.isPropertySet(IArtifactEditOperationDataModelProperties.PROJECT_NAME))
+//				return;
+//			IProject project = ProjectUtilities.getProject(model.getStringProperty(IArtifactEditOperationDataModelProperties.PROJECT_NAME));
+//			annotationsGroup.setEnablement(project);
+//			// annotationsGroup.setUseAnnotations(true);
+//		} else {
+//			// not a Web Doclet project - make sure that the USE_ANNOTATIONS property is off
+//			model.setProperty(IAnnotationsDataModel.USE_ANNOTATIONS, false);
+//		}
+//	}
+	
+	protected Composite createTopLevelComposite(Composite parent) {
+		Composite composite = super.createTopLevelComposite(parent);
+		addSeperator(composite,3);
+		createUseExistingGroup(composite);
+//		createAnnotationsGroup(composite);
+		
+		Dialog.applyDialogFont(composite);
+		
+		return composite;
+	}
+
+	private void createUseExistingGroup(Composite composite) {
+		existingButton = new Button(composite, SWT.CHECK);
+		existingButton.setText(IWebWizardConstants.USE_EXISTING_SERVLET_CLASS);
+		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+		data.horizontalSpan = 3;
+		existingButton.setLayoutData(data);
+		synchHelper.synchCheckbox(existingButton, INewListenerClassDataModelProperties.USE_EXISTING_CLASS, null);
+		existingButton.setEnabled(false);
+		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 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 void handleClassButtonSelected() {
+//		getControl().setCursor(new Cursor(getShell().getDisplay(), SWT.CURSOR_WAIT));
+//		IProject project = (IProject) model.getProperty(INewJavaClassDataModelProperties.PROJECT);
+//		IVirtualComponent component = ComponentCore.createComponent(project);
+//		ListenerMultiSelectFilteredFileSelectionDialog ms = new ListenerMultiSelectFilteredFileSelectionDialog(
+//				getShell(),
+//				IWebWizardConstants.NEW_SERVLET_WIZARD_WINDOW_TITLE,
+//				IWebWizardConstants.CHOOSE_SERVLET_CLASS, 
+//				JSPEXTENSIONS, 
+//				false, 
+//				project);
+//		IContainer root = component.getRootFolder().getUnderlyingFolder();
+//		ms.setInput(root);
+//		ms.open();
+//		if (ms.getReturnCode() == Window.OK) {
+//			String qualifiedClassName = ""; //$NON-NLS-1$
+////			if (ms.getSelectedItem() == MultiSelectFilteredFileSelectionDialog.JSP) {
+////				Object obj = ms.getFirstResult();
+////				if (obj != null) {
+////					if (obj instanceof IFile) {
+////						IFile file = (IFile) obj;
+////						IPath pFull = file.getFullPath();
+////						IPath pBase = root.getFullPath();
+////						IPath path = pFull.removeFirstSegments(pBase.segmentCount());
+////						qualifiedClassName = path.makeAbsolute().toString();
+////						model.setProperty(INewServletClassDataModelProperties.IS_SERVLET_TYPE, new Boolean(false));
+////					}
+////				}
+////			} 
+////			else {
+//				IType type = (IType) ms.getFirstResult();
+//				if (type != null) {
+//					qualifiedClassName = type.getFullyQualifiedName();
+////					model.setProperty(INewServletClassDataModelProperties.IS_SERVLET_TYPE, new Boolean(true));
+//				}
+////			}
+//			existingClassText.setText(qualifiedClassName);
+//		}
+//		getControl().setCursor(null);
+	}
+	
+	protected IProject getExtendedSelectedProject(Object selection) {
+		if (selection instanceof WebListenerGroupItemProvider) {
+			WebApp webApp = (WebApp)((WebListenerGroupItemProvider)selection).getParent();
+			return ProjectUtilities.getProject(webApp);
+		}
+		else if (selection instanceof CompressedJavaProject) {
+			return ((CompressedJavaProject)selection).getProject().getProject();
+		}
+		return super.getExtendedSelectedProject(selection);
+	}
+	
+//	private boolean isWebDocletProject() {
+//		String projectName = model.getStringProperty(IArtifactEditOperationDataModelProperties.PROJECT_NAME);
+//		if(projectName != null && !"".equals(projectName.trim())){
+//			IProject project = ProjectUtilities.getProject(projectName);
+//			try {
+//				IFacetedProject facetedProject = ProjectFacetsManager.create(project);
+//				return facetedProject.hasProjectFacet(WebFacetUtils.WEB_XDOCLET_FACET);
+//			} catch (CoreException e) {
+//				Logger.getLogger().log(e);
+//			}
+//		}
+//		return false;
+//	}
+}