[353681] EJB Client creation and removal is too tied to EARs
diff --git a/plugins/org.eclipse.jst.ejb.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.jst.ejb.ui/META-INF/MANIFEST.MF
index eb33eaf..698a1ec 100644
--- a/plugins/org.eclipse.jst.ejb.ui/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.jst.ejb.ui/META-INF/MANIFEST.MF
@@ -9,6 +9,7 @@
 Export-Package: org.eclipse.jst.ejb.ui.context.ids;x-internal:=true,
  org.eclipse.jst.ejb.ui.internal.actions;x-internal:=true,
  org.eclipse.jst.ejb.ui.internal.deployables;x-internal:=true,
+ org.eclipse.jst.ejb.ui.internal.extension;x-internal:=true,
  org.eclipse.jst.ejb.ui.internal.plugin;x-internal:=true,
  org.eclipse.jst.ejb.ui.internal.quickfixes.ejb;x-internal:=true,
  org.eclipse.jst.ejb.ui.internal.util;x-internal:=true,
diff --git a/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/actions/EJBClientCreationAction.java b/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/actions/EJBClientCreationAction.java
index 6082348..6ff01d5 100644
--- a/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/actions/EJBClientCreationAction.java
+++ b/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/actions/EJBClientCreationAction.java
@@ -11,6 +11,9 @@
 
 package org.eclipse.jst.ejb.ui.internal.actions;
 
+import java.util.Iterator;
+import java.util.List;
+
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.Platform;
 import org.eclipse.jdt.core.IJavaProject;
@@ -19,7 +22,10 @@
 import org.eclipse.jface.action.IAction;
 import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.window.Window;
 import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.jst.ejb.ui.internal.extension.EJBClientActionRegistryReader;
+import org.eclipse.jst.ejb.ui.internal.extension.IEJBClientActionExtender;
 import org.eclipse.jst.ejb.ui.internal.plugin.EJBUIPlugin;
 import org.eclipse.jst.ejb.ui.internal.wizard.EJBClientComponentCreationWizard;
 import org.eclipse.jst.j2ee.ejb.EJBJar;
@@ -74,7 +80,34 @@
 
     private boolean checkEARProject(Shell shell) {
         if (!hasEARProject()) {
-            MessageDialog.openError(shell, EJBCreationResourceHandler.EJB_Client_JAR_Creation_Error_, EJBCreationResourceHandler.Cannot_Be_StandAlone_Project_For_Client_); 
+            // if this is an EJB project that is not in an EAR project, check to see if an extension allows for its creation
+        	IProject project = getSelectedProject();
+            
+        	List<IEJBClientActionExtender> ejbClientCreationExtensions = EJBClientActionRegistryReader.getInstance().getEJBClientActionExtenders();
+			Iterator<IEJBClientActionExtender> i = ejbClientCreationExtensions.iterator();
+			IEJBClientActionExtender current = null;
+			int wizardRet;
+			boolean done = false;
+			// iterate through the extenders.  If the first way to create the EJB Client jar is not correct, the user can press cancel and the next wizard will be created.
+			while (i.hasNext() && !done)
+			{
+				current = i.next();
+				if (current.allowEJBClientCreation(project))
+				{
+					// if the extension allows its creation, then launch whatever wizard is applicable
+					wizardRet = current.showEJBClientCreationWizard(shell, project);
+					if (wizardRet == Window.OK)
+					{
+						done = true;
+					}
+				}
+			}
+
+			// if no extenders can create an EJB Client project, display the usual error message
+			if (!done)
+			{
+				MessageDialog.openError(shell, EJBCreationResourceHandler.EJB_Client_JAR_Creation_Error_, EJBCreationResourceHandler.Cannot_Be_StandAlone_Project_For_Client_);
+			}
             return false;
         }
         return true;		
diff --git a/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/actions/EJBClientRemovalAction.java b/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/actions/EJBClientRemovalAction.java
index 575f36e..311a6c3 100644
--- a/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/actions/EJBClientRemovalAction.java
+++ b/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/actions/EJBClientRemovalAction.java
@@ -13,6 +13,8 @@
 
 import java.lang.reflect.InvocationTargetException;
 import java.text.MessageFormat;
+import java.util.Iterator;
+import java.util.List;
 
 import org.eclipse.core.commands.ExecutionException;
 import org.eclipse.core.resources.IProject;
@@ -28,12 +30,15 @@
 import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.jface.dialogs.ProgressMonitorDialog;
 import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jst.ejb.ui.internal.extension.EJBClientActionRegistryReader;
+import org.eclipse.jst.ejb.ui.internal.extension.IEJBClientActionExtender;
 import org.eclipse.jst.ejb.ui.internal.plugin.EJBUIPlugin;
 import org.eclipse.jst.j2ee.ejb.componentcore.util.EJBArtifactEdit;
 import org.eclipse.jst.j2ee.internal.ejb.archiveoperations.EjbClientProjectRemovalDataModelProvider;
 import org.eclipse.jst.j2ee.internal.ejb.archiveoperations.IEjbClientProjectRemovalDataModelProperties;
 import org.eclipse.jst.j2ee.internal.plugin.J2EEUIPlugin;
 import org.eclipse.jst.j2ee.project.EJBUtilities;
+import org.eclipse.jst.j2ee.project.EarUtilities;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.ui.progress.UIJob;
 import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
@@ -80,30 +85,48 @@
 //		ValidatorManager validatorMgr = ValidatorManager.getManager();
 		try{
 				//validatorMgr.suspendAllValidation(true);
-				
-				Job clientRemoveJob = new UIJob("Removing EJB Client Project"){ //$NON-NLS-1$
-					@Override
-					public IStatus runInUIThread(IProgressMonitor monitor) {
-						
-						UIOperationHandler opHandler = new UIOperationHandler(shell);
-						IDataModel model = DataModelFactory.createDataModel( new EjbClientProjectRemovalDataModelProvider() );
-						model.setProperty(IEjbClientProjectRemovalDataModelProperties.EJB_PROJECT, ejbProject);
-						model.setProperty(IEjbClientProjectRemovalDataModelProperties.EJB_CLIENT_VIEW_PROJECT, clientProject);
-						model.setProperty(IEjbClientProjectRemovalDataModelProperties.OP_HANDLER, opHandler );
-						
-						IStatus status = Status.OK_STATUS;
-						try {
-							status = model.getDefaultOperation().execute(monitor, null);
-						} catch (ExecutionException e) {
-							EJBUIPlugin.logError(e);
+				if (!EarUtilities.isStandaloneProject(ejbProject))
+				{
+					Job clientRemoveJob = new UIJob("Removing EJB Client Project"){ //$NON-NLS-1$
+						@Override
+						public IStatus runInUIThread(IProgressMonitor monitor) {
+							
+							UIOperationHandler opHandler = new UIOperationHandler(shell);
+							IDataModel model = DataModelFactory.createDataModel( new EjbClientProjectRemovalDataModelProvider() );
+							model.setProperty(IEjbClientProjectRemovalDataModelProperties.EJB_PROJECT, ejbProject);
+							model.setProperty(IEjbClientProjectRemovalDataModelProperties.EJB_CLIENT_VIEW_PROJECT, clientProject);
+							model.setProperty(IEjbClientProjectRemovalDataModelProperties.OP_HANDLER, opHandler );
+							
+							IStatus status = Status.OK_STATUS;
+							try {
+								status = model.getDefaultOperation().execute(monitor, null);
+							} catch (ExecutionException e) {
+								EJBUIPlugin.logError(e);
+							}
+							return status;
 						}
-						return status;
+					};
+			
+					clientRemoveJob.setRule(ResourcesPlugin.getWorkspace().getRoot());
+					clientRemoveJob.setUser(true);
+					clientRemoveJob.schedule();
+				}
+				else
+				{
+					List<IEJBClientActionExtender> ejbClientActionExtensions = EJBClientActionRegistryReader.getInstance().getEJBClientActionExtenders();
+					Iterator<IEJBClientActionExtender> i = ejbClientActionExtensions.iterator();
+					IEJBClientActionExtender current = null;
+					IStatus status = null;
+					// iterate through the extenders to find if any allow for the removal of the EJB Client jar
+					while (i.hasNext() && (status == null || !status.isOK()))
+					{
+						current = i.next();
+						if (current.allowEJBClientRemoval(ejbProject))
+						{
+							status = current.performEJBClientRemoval(shell, ejbProject);
+						}
 					}
-				};
-		
-				clientRemoveJob.setRule(ResourcesPlugin.getWorkspace().getRoot());
-				clientRemoveJob.setUser(true);
-				clientRemoveJob.schedule();
+				}
 
 		}finally {
 //			validatorMgr.suspendAllValidation(false);
@@ -204,9 +227,25 @@
 	@Override
 	public void selectionChanged(IAction action, ISelection selection) {
 		super.selectionChanged(action, selection);
-		if (EJBUtilities.hasEJBClientJARProject(getProject()))
+		IProject project = getProject();
+		if (EJBUtilities.hasEJBClientJARProject(project))
 			action.setEnabled(true);
-		else 
-			action.setEnabled(false);
+		else
+		{
+			List<IEJBClientActionExtender> ejbClientActionExtensions = EJBClientActionRegistryReader.getInstance().getEJBClientActionExtenders();
+			Iterator<IEJBClientActionExtender> i = ejbClientActionExtensions.iterator();
+			IEJBClientActionExtender current = null;
+			boolean allow = false;
+			// iterate through the extenders to find if any allow for the removal of the EJB Client jar
+			while (i.hasNext() && !allow)
+			{
+				current = i.next();
+				if (current.allowEJBClientRemoval(project))
+				{
+					allow = true;
+				}
+			}
+			action.setEnabled(allow);
+		}
 	}    
 }
diff --git a/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/extension/EJBClientActionExtension.java b/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/extension/EJBClientActionExtension.java
new file mode 100644
index 0000000..879dcaa
--- /dev/null
+++ b/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/extension/EJBClientActionExtension.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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.ejb.ui.internal.extension;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.jst.ejb.ui.internal.plugin.EJBUIPlugin;
+
+public class EJBClientActionExtension {
+	public static final String EJB_CLIENT_CREATION_EXTENSION = "ejbClientActionExtension"; //$NON-NLS-1$
+	public static final String ATT_ID = "id"; //$NON-NLS-1$
+	public static final String ATT_CLASS = "class"; //$NON-NLS-1$
+	public static final String ACTION = "action"; //$NON-NLS-1$
+	private String id = null;
+	private IConfigurationElement element;
+	private IEJBClientActionExtender instance;
+	private boolean errorCondition = false;
+
+	public EJBClientActionExtension(IConfigurationElement newExtension) {
+		if (!ACTION.equals(newExtension.getName()))
+		{
+			throw new IllegalArgumentException("Extensions must be of the type \"" + ACTION + "\".");  //$NON-NLS-1$//$NON-NLS-2$
+		}
+		element = newExtension;
+		init();
+	}
+
+	private void init() {
+		id = element.getAttribute(ATT_ID);
+	}
+
+	public String getId()
+	{
+		return id;
+	}
+
+	public IEJBClientActionExtender getInstance()
+	{
+		try
+		{
+			if (instance == null && !errorCondition)
+			{
+				instance = (IEJBClientActionExtender) element.createExecutableExtension(ATT_CLASS);
+			}
+		}
+		catch (Throwable e)
+		{
+			EJBUIPlugin.logError(e);
+			errorCondition = true;
+		}
+		return instance;
+	}
+}
diff --git a/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/extension/EJBClientActionRegistryReader.java b/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/extension/EJBClientActionRegistryReader.java
new file mode 100644
index 0000000..a74fc85
--- /dev/null
+++ b/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/extension/EJBClientActionRegistryReader.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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.ejb.ui.internal.extension;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.jst.ejb.ui.internal.plugin.EJBUIPlugin;
+import org.eclipse.wst.common.core.util.RegistryReader;
+
+public class EJBClientActionRegistryReader extends RegistryReader {
+	private static EJBClientActionRegistryReader instance;
+	private List<EJBClientActionExtension> ejbClientCreationExtensions;
+
+	public EJBClientActionRegistryReader() {
+		super(EJBUIPlugin.PLUGIN_ID, EJBClientActionExtension.EJB_CLIENT_CREATION_EXTENSION);
+	}
+
+	@Override
+	public boolean readElement(IConfigurationElement element) {
+		if (EJBClientActionExtension.ACTION.equals(element.getName()))
+		{
+			addExtension(element);
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Sets the extension point.
+	 * 
+	 * @param extensions
+	 *            The extensions to set
+	 */
+	protected void addExtension(IConfigurationElement newExtension) {
+		getEJBClientActionExtensions().add(new EJBClientActionExtension(newExtension));
+	}
+
+	/**
+	 * @return Returns the handlerExtensions.
+	 */
+	protected List<EJBClientActionExtension> getEJBClientActionExtensions()
+	{
+		if (ejbClientCreationExtensions == null)
+		{
+			ejbClientCreationExtensions = new ArrayList<EJBClientActionExtension>();
+		}
+		return ejbClientCreationExtensions;
+	}
+
+	public List<IEJBClientActionExtender> getEJBClientActionExtenders()
+	{
+		List<IEJBClientActionExtender> retVal = new ArrayList<IEJBClientActionExtender>();
+		Iterator<EJBClientActionExtension> i = getEJBClientActionExtensions().iterator();
+		IEJBClientActionExtender current = null;
+		while (i.hasNext())
+		{
+			current = i.next().getInstance();
+			if (current != null)
+			{
+				retVal.add(current);
+			}
+		}
+		
+		return retVal;
+	}
+
+	/**
+	 * Gets the instance.
+	 * 
+	 * @return Returns an EJBClientCreationRegistryReader
+	 */
+	public static EJBClientActionRegistryReader getInstance()
+	{
+		if (instance == null)
+		{
+			instance = new EJBClientActionRegistryReader();
+			instance.readRegistry();
+		}
+		return instance;
+	}
+}
diff --git a/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/extension/IEJBClientActionExtender.java b/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/extension/IEJBClientActionExtender.java
new file mode 100644
index 0000000..3feb508
--- /dev/null
+++ b/plugins/org.eclipse.jst.ejb.ui/ejb_ui/org/eclipse/jst/ejb/ui/internal/extension/IEJBClientActionExtender.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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.ejb.ui.internal.extension;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.swt.widgets.Shell;
+
+public interface IEJBClientActionExtender {
+	/**
+	 * Check to see if an extension is capable of creating an EJB Client jar project for the selected EJB project
+	 * 
+	 * @param project - the EJB Project for which an EJB Client is to be created
+	 * @return true if the extender can create an EJB Client jar project for this EJB project
+	 */
+	boolean allowEJBClientCreation(IProject project);
+
+	/**
+	 * Launch the appropriate wizard (or action if no UI) to create an EJB Client jar for the selected EJB project
+	 * 
+	 * @param shell - the current shell
+	 * @param project - the EJB Project for which an EJB Client is to be created
+	 * @return Window.OK if the wizard completed successfully
+	 */
+	int showEJBClientCreationWizard(Shell shell, IProject project);
+
+	/**
+	 * Check to see if an extension is capable of removing an EJB Client jar project from the selected EJB project
+	 * 
+	 * @param project - the EJB Project for which an EJB Client is to be removed
+	 * @return true if the extender can remove an EJB Client jar project from this EJB project
+	 */
+	boolean allowEJBClientRemoval(IProject project);
+
+	/**
+	 * Launch the appropriate wizard (or action if no UI) to remove an EJB Client jar from the selected EJB project
+	 * 
+	 * @param shell - the current shell
+	 * @param project - the EJB Project from which an EJB Client is to be removed
+	 * @return Window.OK if the wizard completed successfully
+	 */
+	IStatus performEJBClientRemoval(Shell shell, IProject project);
+}
diff --git a/plugins/org.eclipse.jst.ejb.ui/plugin.xml b/plugins/org.eclipse.jst.ejb.ui/plugin.xml
index ff92688..397a604 100644
--- a/plugins/org.eclipse.jst.ejb.ui/plugin.xml
+++ b/plugins/org.eclipse.jst.ejb.ui/plugin.xml
@@ -390,5 +390,10 @@
             markerType="org.eclipse.jst.jee.ejb3.nobeans">
       </markerResolutionGenerator>
    </extension>
-       
+
+<!-- ====================================================== -->
+<!--           EJB Client Extension                         -->
+<!-- ====================================================== -->
+
+	<extension-point id="ejbClientActionExtension" name ="EjbClientAction" schema="schema/ejbClientAction.exsd"/>       
 </plugin>
diff --git a/plugins/org.eclipse.jst.ejb.ui/schema/ejbClientAction.exsd b/plugins/org.eclipse.jst.ejb.ui/schema/ejbClientAction.exsd
new file mode 100644
index 0000000..8c62317
--- /dev/null
+++ b/plugins/org.eclipse.jst.ejb.ui/schema/ejbClientAction.exsd
@@ -0,0 +1,116 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.jst.ejb.ui" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.jst.ejb.ui" id="ejbClientActionExtension" name="Ejb Client Action"/>
+      </appInfo>
+      <documentation>
+         This is for adopters to extend the creation of EJB Clients via the Java EE Tools -&gt; Create EJB Client jar action and/or the removal of EJB Clients via the Java EE Tools -&gt; Remove EJB Client jar action
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <annotation>
+         <appInfo>
+            <meta.element />
+         </appInfo>
+      </annotation>
+      <complexType>
+         <sequence>
+            <element ref="action"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="action">
+      <annotation>
+         <documentation>
+            The action that will both test
+         </documentation>
+      </annotation>
+      <complexType>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  The qualified name of the class that implements org.eclipse.jst.ejb.ui.internal.extensions.IEBJClientActionExtender
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn=":org.eclipse.jst.ejb.ui.internal.extension.IEJBClientActionExtender"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         This extension point is part of an interim API that is still under development and expected to change significantly before reaching stability. It is being made available at this early stage to solicit feedback from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken (repeatedly) as the API evolves.
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         [Enter extension point usage example here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiinfo"/>
+      </appInfo>
+      <documentation>
+         [Enter API information here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         [Enter information about supplied implementation of this extension point.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2011 IBM Corporation and others.&lt;br&gt;
+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 &lt;a
+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>