[193629] Optional EAR Libraries classpath container
diff --git a/plugins/org.eclipse.jst.j2ee.ui/.settings/org.eclipse.core.resources.prefs b/plugins/org.eclipse.jst.j2ee.ui/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..04a5d48
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.ui/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Jul 25 14:00:45 EDT 2007
+eclipse.preferences.version=1
+encoding//j2ee_ui/org/eclipse/jst/j2ee/internal/wizard/earlibraries.properties=8859_1
diff --git a/plugins/org.eclipse.jst.j2ee.ui/j2ee_ui/org/eclipse/jst/j2ee/internal/wizard/EARLibrariesContainerPage.java b/plugins/org.eclipse.jst.j2ee.ui/j2ee_ui/org/eclipse/jst/j2ee/internal/wizard/EARLibrariesContainerPage.java
new file mode 100644
index 0000000..b8ca4a9
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.ui/j2ee_ui/org/eclipse/jst/j2ee/internal/wizard/EARLibrariesContainerPage.java
@@ -0,0 +1,67 @@
+package org.eclipse.jst.j2ee.internal.wizard;
+
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.ui.wizards.IClasspathContainerPage;
+import org.eclipse.jdt.ui.wizards.IClasspathContainerPageExtension;
+import org.eclipse.jdt.ui.wizards.NewElementWizardPage;
+import org.eclipse.jst.j2ee.internal.common.classpath.J2EEComponentClasspathContainer;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Text;
+
+public class EARLibrariesContainerPage extends NewElementWizardPage implements IClasspathContainerPage, IClasspathContainerPageExtension {
+
+	protected IClasspathEntry entry = null;
+
+	public EARLibrariesContainerPage() {
+		super("EARLibrariesContainerPage"); //$NON-NLS-1$
+		setTitle(EARLibrariesMessages.EARLibrariesContainerPage_0);
+		setDescription(EARLibrariesMessages.EARLibrariesContainerPage_1);
+	}
+
+	public boolean finish() {
+		return true;
+	}
+
+	public IClasspathEntry getSelection() {
+		return JavaCore.newContainerEntry(J2EEComponentClasspathContainer.CONTAINER_PATH);
+	}
+
+	public void setSelection(IClasspathEntry containerEntry) {
+	}
+
+	public void createControl(Composite parent) {
+		final Composite composite = new Composite(parent, SWT.NONE);
+		composite.setLayout(new GridLayout(1, false));
+
+		final Text text = new Text(composite, SWT.MULTI | SWT.READ_ONLY | SWT.WRAP);
+		text.setText(getDescription());
+		text.setLayoutData(new GridData(GridData.FILL_BOTH));
+		setControl(composite);
+	}
+
+	public void initialize(IJavaProject project, IClasspathEntry[] currentEntries) {
+	}
+
+	
+	public static class EARLibrariesMessages extends NLS {
+		private static final String BUNDLE_NAME = "org.eclipse.jst.j2ee.internal.wizard.earlibraries"; //$NON-NLS-1$
+
+		public static String EARLibrariesContainerPage_0;
+
+		public static String EARLibrariesContainerPage_1;
+		static {
+			// initialize resource bundle
+			NLS.initializeMessages(BUNDLE_NAME, EARLibrariesMessages.class);
+		}
+
+		private EARLibrariesMessages() {
+		}
+	}
+	
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jst.j2ee.ui/j2ee_ui/org/eclipse/jst/j2ee/internal/wizard/earlibraries.properties b/plugins/org.eclipse.jst.j2ee.ui/j2ee_ui/org/eclipse/jst/j2ee/internal/wizard/earlibraries.properties
new file mode 100644
index 0000000..3e9a87b
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee.ui/j2ee_ui/org/eclipse/jst/j2ee/internal/wizard/earlibraries.properties
@@ -0,0 +1,2 @@
+EARLibrariesContainerPage_0=EAR Libraries
+EARLibrariesContainerPage_1=The EAR Libraries classpath container dynamically computes the J2EE project's module classpath dependencies using the META-INF/MANIFEST.MF Class-Path entries.
diff --git a/plugins/org.eclipse.jst.j2ee.ui/plugin.properties b/plugins/org.eclipse.jst.j2ee.ui/plugin.properties
index aeeb90f..14196a6 100644
--- a/plugins/org.eclipse.jst.j2ee.ui/plugin.properties
+++ b/plugins/org.eclipse.jst.j2ee.ui/plugin.properties
@@ -53,3 +53,4 @@
 Web_Project_Settings=Web Project Settings
 update-ear-libraries=Update EAR Libraries
 update-ear-libraries-tooltip=Recompute the contents of the EAR Libraries classpath container.
+earLibrariesContainerName=EAR Libraries
diff --git a/plugins/org.eclipse.jst.j2ee.ui/plugin.xml b/plugins/org.eclipse.jst.j2ee.ui/plugin.xml
index b847a72..c99632e 100644
--- a/plugins/org.eclipse.jst.j2ee.ui/plugin.xml
+++ b/plugins/org.eclipse.jst.j2ee.ui/plugin.xml
@@ -746,4 +746,13 @@
           context="UI"/>
   </extension>
 
+  <extension
+    point="org.eclipse.jdt.ui.classpathContainerPage">
+    <classpathContainerPage
+      name="%earLibrariesContainerName"
+      class="org.eclipse.jst.j2ee.internal.wizard.EARLibrariesContainerPage"
+      id="org.eclipse.jst.j2ee.internal.module.container">
+    </classpathContainerPage>
+  </extension>
+
 </plugin>
diff --git a/plugins/org.eclipse.jst.j2ee/common/org/eclipse/jst/j2ee/internal/common/classpath/J2EEComponentClasspathContainer.java b/plugins/org.eclipse.jst.j2ee/common/org/eclipse/jst/j2ee/internal/common/classpath/J2EEComponentClasspathContainer.java
index 072cf20..4477dfd 100644
--- a/plugins/org.eclipse.jst.j2ee/common/org/eclipse/jst/j2ee/internal/common/classpath/J2EEComponentClasspathContainer.java
+++ b/plugins/org.eclipse.jst.j2ee/common/org/eclipse/jst/j2ee/internal/common/classpath/J2EEComponentClasspathContainer.java
@@ -306,7 +306,19 @@
 		refresh(false);
 	}
 
+	private boolean isUpdating = false;
+	
 	public IClasspathEntry[] getClasspathEntries() {
+		if(!isUpdating){
+			if(this != J2EEComponentClasspathContainerUtils.getInstalledEARLibrariesContainer(javaProject.getProject())){
+				try {
+					isUpdating = true;
+					update();
+				} finally{
+					isUpdating = false;
+				}
+			}
+		}
 		return entries;
 	}
 
diff --git a/plugins/org.eclipse.jst.j2ee/common/org/eclipse/jst/j2ee/internal/common/classpath/J2EEComponentClasspathContainerUtils.java b/plugins/org.eclipse.jst.j2ee/common/org/eclipse/jst/j2ee/internal/common/classpath/J2EEComponentClasspathContainerUtils.java
new file mode 100644
index 0000000..fa1ee27
--- /dev/null
+++ b/plugins/org.eclipse.jst.j2ee/common/org/eclipse/jst/j2ee/internal/common/classpath/J2EEComponentClasspathContainerUtils.java
@@ -0,0 +1,122 @@
+package org.eclipse.jst.j2ee.internal.common.classpath;
+
+import java.util.Properties;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.IClasspathContainer;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jst.common.jdt.internal.classpath.FlexibleProjectContainer;
+import org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin;
+import org.eclipse.wst.common.componentcore.ComponentCore;
+import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
+
+public class J2EEComponentClasspathContainerUtils {
+
+	public final static String EAR_LIBRARIES_PROCESSED = "ear_libraries_processed"; //$NON-NLS-1$
+
+	public final static String WEB_APP_LIBRARIES_PROCESSED = "web_app_libraries_processed"; //$NON-NLS-1$
+
+	public static boolean isWebAppLibrariesProcessed(IProject project) {
+		return isLibraryProcessed(project, WEB_APP_LIBRARIES_PROCESSED);
+	}
+
+	public static boolean isEARLibrariesProcessed(IProject project) {
+		return isLibraryProcessed(project, EAR_LIBRARIES_PROCESSED);
+	}
+
+	private static boolean isLibraryProcessed(IProject project, String propertyName) {
+		IVirtualComponent comp = ComponentCore.createComponent(project);
+		if (comp == null) {
+			return true;
+		}
+		Properties properties = comp.getMetaProperties();
+		String property = properties.getProperty(propertyName);
+		if (property == null) {
+			return false;
+		} else {
+			return parseBoolean(property);
+		}
+	}
+
+	private static boolean parseBoolean(String name) {
+		return ((name != null) && name.equalsIgnoreCase("true")); //$NON-NLS-1$
+	}
+
+	public static void setEARLibrariesProcessed(IProject project, boolean processed) {
+		setLibraryProcessed(project, processed, EAR_LIBRARIES_PROCESSED);
+	}
+
+	public static void setWebAppLibrariesProcessed(IProject project, boolean processed) {
+		setLibraryProcessed(project, processed, WEB_APP_LIBRARIES_PROCESSED);
+	}
+
+	private static void setLibraryProcessed(IProject project, boolean processed, String propertyName) {
+		IVirtualComponent comp = ComponentCore.createComponent(project);
+		String value = processed ? Boolean.TRUE.toString() : Boolean.FALSE.toString();
+		comp.setMetaProperty(propertyName, value);
+	}
+
+	public static boolean getDefaultUseEARLibraries() {
+		return J2EEPlugin.getDefault().getJ2EEPreferences().getUseEARLibraries();
+	}
+
+	public static boolean getDefaultUseWebAppLibraries() {
+		return J2EEPlugin.getDefault().getJ2EEPreferences().getUseWebLibaries();
+	}
+	
+	public static IClasspathContainer getInstalledContainer(IProject project, IPath containerPath) {
+		IJavaProject jproj = JavaCore.create(project);
+		IClasspathEntry entry = getInstalledContainerEntry(jproj, containerPath);
+		IClasspathContainer container = null;
+		if (entry != null) {
+			try {
+				container = JavaCore.getClasspathContainer(containerPath, jproj);
+			} catch (JavaModelException e) {
+				J2EEPlugin.getDefault().getLogger().logError(e);
+			}
+		}
+		return container;
+	}
+
+	public static J2EEComponentClasspathContainer getInstalledEARLibrariesContainer(IProject project) {
+		IClasspathContainer container = getInstalledContainer(project, J2EEComponentClasspathContainer.CONTAINER_PATH);
+		J2EEComponentClasspathContainer earLibrariesContainer = null;
+		if (null != container && container instanceof J2EEComponentClasspathContainer) {
+			earLibrariesContainer = (J2EEComponentClasspathContainer) container;
+		}
+		return earLibrariesContainer;
+	}
+
+	public static FlexibleProjectContainer getInstalledWebAppLibrariesContainer(IProject project){
+		IClasspathContainer container = getInstalledContainer(project, J2EEComponentClasspathUpdater.WEB_APP_LIBS_PATH);
+		FlexibleProjectContainer webAppLibrariesContainer = null;
+		if (null != container && container instanceof FlexibleProjectContainer) {
+			webAppLibrariesContainer = (FlexibleProjectContainer) container;
+		}
+		return webAppLibrariesContainer;
+	}
+	
+	public static IClasspathEntry getInstalledContainerEntry(IJavaProject jproj, IPath classpathContainerPath) {
+		try {
+			IClasspathEntry[] cpes;
+			cpes = jproj.getRawClasspath();
+			for (int j = 0; j < cpes.length; j++) {
+				final IClasspathEntry cpe = cpes[j];
+				if (cpe.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
+					if (cpe.getPath().equals(classpathContainerPath)) {
+						return cpe; // entry found
+					}
+				}
+			}
+		} catch (JavaModelException e) {
+			J2EEPlugin.getDefault().getLogger().logError(e);
+		}
+		// entry not found
+		return null;
+	}
+
+}
diff --git a/plugins/org.eclipse.jst.j2ee/common/org/eclipse/jst/j2ee/internal/common/classpath/J2EEComponentClasspathUpdater.java b/plugins/org.eclipse.jst.j2ee/common/org/eclipse/jst/j2ee/internal/common/classpath/J2EEComponentClasspathUpdater.java
index f980f5a..7efb7f7 100644
--- a/plugins/org.eclipse.jst.j2ee/common/org/eclipse/jst/j2ee/internal/common/classpath/J2EEComponentClasspathUpdater.java
+++ b/plugins/org.eclipse.jst.j2ee/common/org/eclipse/jst/j2ee/internal/common/classpath/J2EEComponentClasspathUpdater.java
@@ -66,11 +66,12 @@
 public class J2EEComponentClasspathUpdater implements IResourceChangeListener, IResourceDeltaVisitor {
 
 	private static J2EEComponentClasspathUpdater instance = null;
+
 	private static boolean updateDependencyGraph = true;
 
 	private int pauseCount = 0;
-	
-	private IPath WEB_APP_LIBS_PATH = new Path("org.eclipse.jst.j2ee.internal.web.container");
+
+	public static IPath WEB_APP_LIBS_PATH = new Path("org.eclipse.jst.j2ee.internal.web.container"); //$NON-NLS-1$
 
 	public static J2EEComponentClasspathUpdater getInstance() {
 		if (instance == null) {
@@ -98,8 +99,8 @@
 	public void resumeUpdates() {
 		resumeUpdates(true);
 	}
-	
-	private void resumeUpdates(boolean scheduleJob){
+
+	private void resumeUpdates(boolean scheduleJob) {
 		synchronized (this) {
 			if (pauseCount > 0) {
 				pauseCount--;
@@ -108,15 +109,15 @@
 				return;
 			}
 		}
-		if(scheduleJob){
+		if (scheduleJob) {
 			moduleUpdateJob.schedule(MODULE_UPDATE_DELAY);
 		}
 	}
-	
-	public void forceUpdate(Collection projects){
+
+	public void forceUpdate(Collection projects) {
 		forceUpdate(projects, true);
 	}
-	
+
 	/**
 	 * Collection of type IProject
 	 * @param projects
@@ -125,20 +126,20 @@
 		try {
 			pauseUpdates();
 			Iterator iterator = projects.iterator();
-			while(iterator.hasNext()){
-				queueUpdate((IProject)iterator.next());
+			while (iterator.hasNext()) {
+				queueUpdate((IProject) iterator.next());
 			}
 		} finally {
 			forceUpdateOnNextRun = true;
 			// the following code is in place of the normal call to
-			// resume updates.  This restores the pauseCount and forces 
-			// the job to be scheduled immediately 
+			// resume updates. This restores the pauseCount and forces
+			// the job to be scheduled immediately
 			synchronized (this) {
 				if (pauseCount > 0) {
 					pauseCount--;
 				}
 			}
-			if(runAsJob){
+			if (runAsJob) {
 				moduleUpdateJob.schedule(0);
 			} else {
 				try
@@ -153,9 +154,9 @@
 			}
 		}
 	}
-	
+
 	private boolean forceUpdateOnNextRun = false;
-	
+
 	public void queueUpdate(IProject project) {
 		if (J2EEProjectUtilities.isEARProject(project)) {
 			queueUpdateEAR(project);
@@ -167,12 +168,12 @@
 
 	public void queueUpdateModule(IProject project) {
 		moduleUpdateJob.queueModule(project);
-		if(!isKnown(project)){
+		if (!isKnown(project)) {
 			IProject[] earProjects = J2EEProjectUtilities.getReferencingEARProjects(project);
 			for (int i = 0; i < earProjects.length; i++) {
 				moduleUpdateJob.queueEAR(earProjects[i]);
 			}
-		} 
+		}
 		synchronized (this) {
 			if (pauseCount > 0) {
 				return;
@@ -190,27 +191,28 @@
 		}
 		moduleUpdateJob.schedule(MODULE_UPDATE_DELAY);
 	}
-	
+
 	public boolean projectsQueued() {
 		return moduleUpdateJob.projectsQueued() || moduleUpdateJob.getState() != Job.NONE;
 	}
-	
+
 	private static final int MODULE_UPDATE_DELAY = 30;
-	public static final String MODULE_UPDATE_JOB_NAME = "EAR Libraries Update Job"; 
+
+	public static final String MODULE_UPDATE_JOB_NAME = "EAR Libraries Update Job";
 
 	private final ModuleUpdateJob moduleUpdateJob = new ModuleUpdateJob();
 
 	public class ModuleUpdateJob extends Job {
 
 		public boolean belongsTo(Object family) {
-			if(family == MODULE_UPDATE_JOB_NAME){
+			if (family == MODULE_UPDATE_JOB_NAME) {
 				return true;
 			}
 			return super.belongsTo(family);
 		}
-		
+
 		// We use the listener list as a thread safe queue.
-		private class Queue extends ListenerList  {
+		private class Queue extends ListenerList {
 			public synchronized Object[] getListeners() {
 				Object[] data = super.getListeners();
 				clear();
@@ -223,7 +225,7 @@
 		private Queue earQueue = new Queue();
 
 		public ModuleUpdateJob() {
-			super(MODULE_UPDATE_JOB_NAME); 
+			super(MODULE_UPDATE_JOB_NAME);
 			setRule(ResourcesPlugin.getWorkspace().getRoot());
 			setSystem(true);
 		}
@@ -235,7 +237,7 @@
 		public void queueModule(IProject project) {
 			moduleQueue.add(project);
 		}
-		
+
 		public boolean projectsQueued() {
 			return !earQueue.isEmpty() || !moduleQueue.isEmpty();
 		}
@@ -247,7 +249,7 @@
 				EARArtifactEdit edit = null;
 				try {
 					edit = EARArtifactEdit.getEARArtifactEditForRead(earProject);
-					if(edit != null){
+					if (edit != null) {
 						IVirtualReference[] refs = edit.getComponentReferences();
 						IVirtualComponent comp = null;
 						for (int j = 0; j < refs.length; j++) {
@@ -263,32 +265,71 @@
 					}
 				}
 				IVirtualComponent earComponent = ComponentCore.createComponent(earProject);
-				if(null != earComponent){
-					EnterpriseBinaryComponentHelper.ArchiveCache.getInstance().clearDisconnectedArchivesInEAR(earComponent);	
+				if (null != earComponent) {
+					EnterpriseBinaryComponentHelper.ArchiveCache.getInstance().clearDisconnectedArchivesInEAR(earComponent);
 				}
 			}
 		}
-		
-		private void processModules(){
+
+		private void processModules() {
 			Object[] projects = moduleQueue.getListeners();
 			for (int i = 0; i < projects.length; i++) {
 				IProject project = (IProject) projects[i];
-				IClasspathContainer container = getWebAppLibrariesContainer(project, false);
-				if (container != null && container instanceof FlexibleProjectContainer) {
-					((FlexibleProjectContainer) container).refresh();
+				if (J2EEProjectUtilities.isDynamicWebProject(project)) {
+					// this block is for Web app Libraries
+
+					IClasspathContainer webAppLibrariesContainer = null;
+					// The Web App Libraries container will only be auto added/removed from the classpath once.
+					// Thereafter the user controls the Web App Librareis container with the JDT UI.
+					boolean shouldConsiderModifyingWebAppLibraries = !J2EEComponentClasspathContainerUtils.isWebAppLibrariesProcessed(project);
+					if (shouldConsiderModifyingWebAppLibraries) {
+						J2EEComponentClasspathContainerUtils.setWebAppLibrariesProcessed(project, true);
+						boolean shouldAddWebAppLibraries = J2EEComponentClasspathContainerUtils.getDefaultUseWebAppLibraries();
+						if (shouldAddWebAppLibraries) {
+							webAppLibrariesContainer = addContainerToModuleIfNecessary(project, WEB_APP_LIBS_PATH);
+						} else {
+							removeContainerFromModuleIfNecessary(project, WEB_APP_LIBS_PATH);
+						}
+					}
+
+					// If the container was not just added, see if it is already present
+					if (null == webAppLibrariesContainer) {
+						webAppLibrariesContainer = J2EEComponentClasspathContainerUtils.getInstalledWebAppLibrariesContainer(project);
+					}
+
+					// If the container is present, refresh it
+					if (webAppLibrariesContainer != null) {
+						((FlexibleProjectContainer) webAppLibrariesContainer).refresh();
+					}
 				}
-				IProject[] earProjects = J2EEProjectUtilities.getReferencingEARProjects(project);
-				if (earProjects.length == 0) {
-					continue;
-				} 
-				
-				container = addContainerToModuleIfNecessary(project);
-				if (container != null && container instanceof J2EEComponentClasspathContainer) {
-					((J2EEComponentClasspathContainer) container).refresh(forceUpdateOnNextRun);
+
+				// ******************** The following is for EAR Libraries
+
+				IClasspathContainer earLibrariesContainer = null;
+				// The EAR Libraries container will only be auto added/removed from the classpath once.
+				// Thereafter the user controls the Ear Librareis container with the JDT UI.
+				boolean shouldConsiderModifyingEARLibraries = !J2EEComponentClasspathContainerUtils.isEARLibrariesProcessed(project);
+				if (shouldConsiderModifyingEARLibraries) {
+					J2EEComponentClasspathContainerUtils.setEARLibrariesProcessed(project, true);
+					boolean shouldAddEARLibraries = J2EEComponentClasspathContainerUtils.getDefaultUseEARLibraries();
+					if (shouldAddEARLibraries) {
+						earLibrariesContainer = addContainerToModuleIfNecessary(project, J2EEComponentClasspathContainer.CONTAINER_PATH);
+					} else {
+						removeContainerFromModuleIfNecessary(project, J2EEComponentClasspathContainer.CONTAINER_PATH);
+					}
+				}
+
+				// If the container was not just added, see if it is already present
+				if (null == earLibrariesContainer) {
+					earLibrariesContainer = J2EEComponentClasspathContainerUtils.getInstalledEARLibrariesContainer(project);
+				}
+
+				// If the container is present, refresh it
+				if (earLibrariesContainer != null) {
+					((J2EEComponentClasspathContainer) earLibrariesContainer).refresh(forceUpdateOnNextRun);
 				}
 			}
 		}
-		
 
 		protected IStatus run(IProgressMonitor monitor) {
 
@@ -304,7 +345,7 @@
 					} finally {
 						forceUpdateOnNextRun = false;
 					}
-					
+
 				}
 			});
 
@@ -317,21 +358,21 @@
 		IClasspathContainer container = null;
 		IClasspathEntry entry = create ? null : getExistingContainer(jproj, WEB_APP_LIBS_PATH);
 		if (entry != null || create) {
-		try {
+			try {
 				container = JavaCore.getClasspathContainer(WEB_APP_LIBS_PATH, jproj);
-		} catch (JavaModelException e) {
+			} catch (JavaModelException e) {
 				J2EEPlugin.getDefault().getLogger().logError(e);
+			}
 		}
-	}
 		return container;
 	}
-	
-	private IClasspathContainer addContainerToModuleIfNecessary(IProject moduleProject) {
+
+	private IClasspathContainer addContainerToModuleIfNecessary(IProject moduleProject, IPath containerPath) {
 		IJavaProject jproj = JavaCore.create(moduleProject);
-		IClasspathEntry entry = getExistingContainer(jproj, J2EEComponentClasspathContainer.CONTAINER_PATH);
+		IClasspathEntry entry = getExistingContainer(jproj, containerPath);
 		if (entry == null) {
 			try {
-				entry = JavaCore.newContainerEntry(J2EEComponentClasspathContainer.CONTAINER_PATH, true);
+				entry = JavaCore.newContainerEntry(containerPath, true);
 				addToClasspath(jproj, entry);
 			} catch (CoreException e) {
 				J2EEPlugin.getDefault().getLogger().logError(e);
@@ -339,13 +380,25 @@
 		}
 		IClasspathContainer container = null;
 		try {
-			container = JavaCore.getClasspathContainer(J2EEComponentClasspathContainer.CONTAINER_PATH, jproj);
+			container = JavaCore.getClasspathContainer(containerPath, jproj);
 		} catch (JavaModelException e) {
 			J2EEPlugin.getDefault().getLogger().logError(e);
 		}
 		return container;
 	}
 
+	private void removeContainerFromModuleIfNecessary(IProject moduleProject, IPath containerPath) {
+		IJavaProject jproj = JavaCore.create(moduleProject);
+		IClasspathEntry entry = getExistingContainer(jproj, containerPath);
+		if (entry != null) {
+			try {
+				removeFromClasspath(jproj, entry);
+			} catch (CoreException e) {
+				J2EEPlugin.getDefault().getLogger().logError(e);
+			}
+		}
+	}
+
 	private void addToClasspath(final IJavaProject jproj, final IClasspathEntry entry) throws CoreException {
 		final IClasspathEntry[] current = jproj.getRawClasspath();
 		final IClasspathEntry[] updated = new IClasspathEntry[current.length + 1];
@@ -354,91 +407,94 @@
 		jproj.setRawClasspath(updated, null);
 	}
 
+	private void removeFromClasspath(final IJavaProject jproj, final IClasspathEntry entry) throws CoreException {
+		final IClasspathEntry[] current = jproj.getRawClasspath();
+		final IClasspathEntry[] updated = new IClasspathEntry[current.length - 1];
+		boolean removed = false;
+		for (int i = 0; i < current.length; i++) {
+			if (!removed) {
+				if (current[i] == entry) {
+					removed = true;
+				} else {
+					updated[i] = current[i];
+				}
+			} else {
+				updated[i - 1] = current[i];
+			}
+		}
+		jproj.setRawClasspath(updated, null);
+	}
+
 	/**
-	 * Returns the existing classpath container if it is already on the
-	 * classpath. This will not create a new container.
+	 * Returns the existing classpath container if it is already on the classpath. This will not
+	 * create a new container.
 	 * 
 	 * @param jproj
 	 * @param classpathContainerID
 	 * @return
 	 */
 	public IClasspathEntry getExistingContainer(IJavaProject jproj, IPath classpathContainerPath) {
-		try {
-			IClasspathEntry[] cpes;
-			cpes = jproj.getRawClasspath();
-			for (int j = 0; j < cpes.length; j++) {
-				final IClasspathEntry cpe = cpes[j];
-				if (cpe.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
-					if (cpe.getPath().equals(classpathContainerPath)) {
-						return cpe; // entry found
-					}
-				}
-			}
-		} catch (JavaModelException e) {
-			J2EEPlugin.getDefault().getLogger().logError(e);
-		}
-		// entry not found
-		return null;
+		return J2EEComponentClasspathContainerUtils.getInstalledContainerEntry(jproj, classpathContainerPath);
 	}
 
 	private Set knownProjects = new HashSet();
-	
-	private boolean isKnown(IProject project){
+
+	private boolean isKnown(IProject project) {
 		return !knownProjects.add(project.getName());
 	}
-	
-	private void forgetProject(IProject project){
+
+	private void forgetProject(IProject project) {
 		knownProjects.remove(project.getName());
 	}
-	
+
 	public void resourceChanged(IResourceChangeEvent event) {
 		boolean scheduleJob = false;
 		try {
 			pauseUpdates();
-			switch (event.getType()){
-				case IResourceChangeEvent.PRE_CLOSE:
-				case IResourceChangeEvent.PRE_DELETE:
-					IResource resource = event.getResource();
-					if(resource.getType() == IResource.PROJECT){
-						if(ModuleCoreNature.isFlexibleProject((IProject) resource)){
-							if(J2EEProjectUtilities.isEARProject((IProject)resource)){
-								IProject earProject = (IProject) resource;
-								EARArtifactEdit edit = null;
-								try {
-									edit = EARArtifactEdit.getEARArtifactEditForRead(earProject);
-									if(edit != null){
-										IVirtualReference[] refs = edit.getComponentReferences();
-										IVirtualComponent comp = null;
-										for (int j = 0; j < refs.length; j++) {
-											comp = refs[j].getReferencedComponent();
-											if (!comp.isBinary()) {
-												queueUpdateModule(comp.getProject());
-											}
+			switch (event.getType()) {
+			case IResourceChangeEvent.PRE_CLOSE:
+			case IResourceChangeEvent.PRE_DELETE:
+				IResource resource = event.getResource();
+				if (resource.getType() == IResource.PROJECT) {
+					if (ModuleCoreNature.isFlexibleProject((IProject) resource)) {
+						if (J2EEProjectUtilities.isEARProject((IProject) resource)) {
+							IProject earProject = (IProject) resource;
+							EARArtifactEdit edit = null;
+							try {
+								edit = EARArtifactEdit.getEARArtifactEditForRead(earProject);
+								if (edit != null) {
+									IVirtualReference[] refs = edit.getComponentReferences();
+									IVirtualComponent comp = null;
+									for (int j = 0; j < refs.length; j++) {
+										comp = refs[j].getReferencedComponent();
+										if (!comp.isBinary()) {
+											queueUpdateModule(comp.getProject());
 										}
 									}
-								} finally {
-									if (edit != null) {
-										edit.dispose();
-									}
 								}
-							} else {
-								IProject[] earProjects = J2EEProjectUtilities.getReferencingEARProjects((IProject)resource);
-								for(int i=0; i<earProjects.length; i++){
-									queueUpdateEAR(earProjects[i]);
+							} finally {
+								if (edit != null) {
+									edit.dispose();
 								}
 							}
-							forgetProject((IProject)resource);
+						} else {
+							IProject[] earProjects = J2EEProjectUtilities.getReferencingEARProjects((IProject) resource);
+							for (int i = 0; i < earProjects.length; i++) {
+								queueUpdateEAR(earProjects[i]);
+							}
 						}
-						EnterpriseBinaryComponentHelper.ArchiveCache.getInstance().clearAllArchivesInProject((IProject)resource);
+						forgetProject((IProject) resource);
 					}
-					break;
-				case IResourceChangeEvent.POST_CHANGE:
-					scheduleJob = true;
-					event.getDelta().accept(this);
-					IResourceDelta[] d = event.getDelta().getAffectedChildren();
-					findNode(d);
-			
-					break;
+					EnterpriseBinaryComponentHelper.ArchiveCache.getInstance().clearAllArchivesInProject((IProject) resource);
+				}
+				break;
+			case IResourceChangeEvent.POST_CHANGE:
+				scheduleJob = true;
+				event.getDelta().accept(this);
+				IResourceDelta[] d = event.getDelta().getAffectedChildren();
+				findNode(d);
+
+				break;
 			}
 		} catch (CoreException e) {
 			J2EEPlugin.getDefault().getLogger().logError(e);
@@ -447,30 +503,28 @@
 			resumeUpdates(scheduleJob);
 		}
 	}
-	
 
 	public static void clearResourceTreeRootCache(WorkbenchComponent aModule) {
 
 		ResourceTreeRootAdapter resourceTreeAdapter = (ResourceTreeRootAdapter) ExtendedEcoreUtil
 				.getAdapter(aModule, aModule.eAdapters(),
 						ResourceTreeRootAdapter.DEPLOY_ADAPTER_TYPE);
-		if(null != resourceTreeAdapter) {
+		if (null != resourceTreeAdapter) {
 			resourceTreeAdapter.setResourceTreeRoot(null);
 		}
 		resourceTreeAdapter = (ResourceTreeRootAdapter) ExtendedEcoreUtil
 				.getAdapter(aModule, aModule.eAdapters(),
 						ResourceTreeRootAdapter.SOURCE_ADAPTER_TYPE);
-		if(null != resourceTreeAdapter){
+		if (null != resourceTreeAdapter) {
 			resourceTreeAdapter.setResourceTreeRoot(null);
 		}
 	}
 
-
 	/*
 	 * Needs to notice changes to MANIFEST.MF in any J2EE projects, changes to
 	 * .component in any J2EE Projects, and any archive changes in EAR projects
 	 */
-	
+
 	public boolean findNode(IResourceDelta[] delta) {
 
 		for (int i = 0; i < delta.length; i++) {
@@ -478,9 +532,9 @@
 				StructureEdit core = StructureEdit
 						.getStructureEditForRead(delta[i].getResource()
 								.getProject());
-				if(null != core){
+				if (null != core) {
 					WorkbenchComponent component = core.getComponent();
-					if(component != null){
+					if (component != null) {
 						clearResourceTreeRootCache(component);
 					}
 				}
@@ -491,7 +545,7 @@
 
 		return true;
 	}
-	
+
 	public boolean visit(IResourceDelta delta) {
 		IResource resource = delta.getResource();
 		switch (resource.getType()) {
@@ -528,7 +582,7 @@
 				try {
 					if (FacetedProjectFramework.hasProjectFacet(resource.getProject(), J2EEProjectUtilities.ENTERPRISE_APPLICATION)) {
 						IVirtualComponent comp = ComponentCore.createComponent(resource.getProject());
-						if(isFolder(resource.getParent(), comp.getRootFolder())){
+						if (isFolder(resource.getParent(), comp.getRootFolder())) {
 							queueUpdateEAR(resource.getProject());
 						}
 					}
@@ -541,7 +595,7 @@
 			return false;
 		}
 	}
-	
+
 	public static boolean endsWithIgnoreCase(String str, String sfx) {
 		return str.regionMatches(true, str.length() - sfx.length(), sfx, 0, sfx.length());
 	}
diff --git a/plugins/org.eclipse.jst.j2ee/earproject/org/eclipse/jst/j2ee/application/internal/operations/RemoveComponentFromEnterpriseApplicationOperation.java b/plugins/org.eclipse.jst.j2ee/earproject/org/eclipse/jst/j2ee/application/internal/operations/RemoveComponentFromEnterpriseApplicationOperation.java
index 7a061ed..2e24d93 100644
--- a/plugins/org.eclipse.jst.j2ee/earproject/org/eclipse/jst/j2ee/application/internal/operations/RemoveComponentFromEnterpriseApplicationOperation.java
+++ b/plugins/org.eclipse.jst.j2ee/earproject/org/eclipse/jst/j2ee/application/internal/operations/RemoveComponentFromEnterpriseApplicationOperation.java
@@ -67,6 +67,10 @@
 				if (list != null && list.size() > 0) {
 					for (int i = 0; i < list.size(); i++) {
 						IVirtualComponent wc = (IVirtualComponent) list.get(i);
+						IVirtualComponent moduleComponent = wc.getComponent();
+						if(!moduleComponent.isBinary()){
+							J2EEComponentClasspathUpdater.getInstance().queueUpdateModule(moduleComponent.getProject());
+						}
 						String moduleURI = getModuleURI(earEdit, wc);
 						removeModule(application, moduleURI); 
 						IVirtualFile vFile = comp.getRootFolder().getFile(moduleURI);
diff --git a/plugins/org.eclipse.jst.j2ee/j2eeplugin/org/eclipse/jst/j2ee/internal/plugin/J2EEPreferences.java b/plugins/org.eclipse.jst.j2ee/j2eeplugin/org/eclipse/jst/j2ee/internal/plugin/J2EEPreferences.java
index d381d03..b720d97 100644
--- a/plugins/org.eclipse.jst.j2ee/j2eeplugin/org/eclipse/jst/j2ee/internal/plugin/J2EEPreferences.java
+++ b/plugins/org.eclipse.jst.j2ee/j2eeplugin/org/eclipse/jst/j2ee/internal/plugin/J2EEPreferences.java
@@ -19,6 +19,8 @@
 import org.eclipse.core.runtime.Plugin;
 import org.eclipse.core.runtime.Preferences;
 import org.eclipse.jst.j2ee.internal.J2EEVersionConstants;
+import org.eclipse.wst.project.facet.IProductConstants;
+import org.eclipse.wst.project.facet.ProductManager;
 
 
 /**
@@ -35,8 +37,8 @@
 		final static String J2EE_VERSION = "org.eclipse.jst.j2ee.ui.preference.j2eeVersion"; //$NON-NLS-1$
 		final static String EJB_CLIENT_JAR_CP_COMPATIBILITY = "org.eclipse.jst.j2ee.preference.clientjar.cp.compatibility"; //$NON-NLS-1$
 		final static String INCREMENTAL_DEPLOYMENT_SUPPORT = "org.eclipse.jst.j2ee.ui.preference.incrementalDeployment"; //$NON-NLS-1$
-
-
+		final static String USE_EAR_LIBRARIES = "org.eclipse.jst.j2ee.preferences.useEARLibraries";//$NON-NLS-1$
+		final static String USE_WEB_APP_LIBRARIES = "org.eclipse.jst.j2ee.preferences.useWebAppLibraries";//$NON-NLS-1$
 	}
 
 	public interface Values {
@@ -50,7 +52,6 @@
 	}
 
 	public interface Defaults {
-
 		final static String J2EE_WEB_CONTENT = Values.J2EE_WEB_CONTENT;
 		final static String STATIC_WEB_CONTENT = Values.STATIC_WEB_CONTENT;
 		final static String JAVA_SOURCE = Values.JAVA_SOURCE;
@@ -78,9 +79,38 @@
 		getPreferences().setDefault(Keys.CREATE_EJB_CLIENT_JAR, Defaults.CREATE_EJB_CLIENT_JAR);
 		getPreferences().setDefault(Keys.EJB_CLIENT_JAR_CP_COMPATIBILITY, Defaults.EJB_CLIENT_JAR_CP_COMPATIBILITY);
 		getPreferences().setDefault(Keys.INCREMENTAL_DEPLOYMENT_SUPPORT, Defaults.INCREMENTAL_DEPLOYMENT_SUPPORT);
-
+		
+		getPreferences().setDefault(Keys.USE_EAR_LIBRARIES, ProductManager.getProperty(IProductConstants.USE_EAR_LIBRARIES));
+		getPreferences().setDefault(Keys.USE_WEB_APP_LIBRARIES, ProductManager.getProperty(IProductConstants.USE_WEB_APP_LIBRARIES));
 	}
 
+	public String getSetting(String key){
+		return getPreferences().getString(key);
+	}
+	
+	public void setSetting(String key, String value){
+		getPreferences().setValue(key, value);
+		firePreferenceChanged();
+	}
+	
+	public boolean getUseEARLibraries() {
+		return getPreferences().getBoolean(Keys.USE_EAR_LIBRARIES);
+	}
+	
+	public void setUseEARLibraries(boolean value) {
+		getPreferences().setValue(Keys.USE_EAR_LIBRARIES, value);
+		firePreferenceChanged();
+	}
+	
+	public boolean getUseWebLibaries() {
+		return getPreferences().getBoolean(Keys.USE_WEB_APP_LIBRARIES);
+	}
+	
+	public void setUseWebLibraries(boolean value) {
+		getPreferences().setValue(Keys.USE_WEB_APP_LIBRARIES, value);
+		firePreferenceChanged();
+	}
+	
 	public String getJ2EEWebContentFolderName() {
 		return getPreferences().getString(Keys.J2EE_WEB_CONTENT);
 	}
diff --git a/plugins/org.eclipse.wst.web/static_web_project/org/eclipse/wst/project/facet/IProductConstants.java b/plugins/org.eclipse.wst.web/static_web_project/org/eclipse/wst/project/facet/IProductConstants.java
index 27b8524..0785472 100644
--- a/plugins/org.eclipse.wst.web/static_web_project/org/eclipse/wst/project/facet/IProductConstants.java
+++ b/plugins/org.eclipse.wst.web/static_web_project/org/eclipse/wst/project/facet/IProductConstants.java
@@ -40,4 +40,10 @@
 	public static final String DEFAULT_RUNTIME_2 = "defaultRuntime2"; //$NON-NLS-1$
 	public static final String DEFAULT_RUNTIME_3 = "defaultRuntime3"; //$NON-NLS-1$
 	
+	/**
+	 * enables/disables EAR Libraries and Web App Libraries classpath containers
+	 */
+	public final static String USE_EAR_LIBRARIES = "use_ear_libraries"; //$NON-NLS-1$
+    public final static String USE_WEB_APP_LIBRARIES = "use_web_app_libraries"; //$NON-NLS-1$
+	
 }
diff --git a/plugins/org.eclipse.wst.web/static_web_project/org/eclipse/wst/project/facet/ProductManager.java b/plugins/org.eclipse.wst.web/static_web_project/org/eclipse/wst/project/facet/ProductManager.java
index 853b6c2..d3d8566 100644
--- a/plugins/org.eclipse.wst.web/static_web_project/org/eclipse/wst/project/facet/ProductManager.java
+++ b/plugins/org.eclipse.wst.web/static_web_project/org/eclipse/wst/project/facet/ProductManager.java
@@ -32,6 +32,8 @@
 							new String[]{IProductConstants.DEFAULT_RUNTIME_1,
 										IProductConstants.DEFAULT_RUNTIME_2,
 										IProductConstants.DEFAULT_RUNTIME_3};
+	private final static String USE_EAR_LIBRARIES = "true";  //$NON-NLS-1$
+	private final static String USE_WEB_APP_LIBRARIES = "true"; //$NON-NLS-1$
 	
 	/**
 	 * Return the value for the associated key from the Platform Product registry or return the
@@ -79,6 +81,10 @@
 				return FINAL_PERSPECTIVE;
 			else if (key.equals(IProductConstants.FINAL_PERSPECTIVE_WEB))
 				return FINAL_PERSPECTIVE;
+			else if (key.equals(IProductConstants.USE_EAR_LIBRARIES))
+				return USE_EAR_LIBRARIES;
+			else if (key.equals(IProductConstants.USE_WEB_APP_LIBRARIES))
+				return USE_WEB_APP_LIBRARIES;
 		}
 		return value;
 	}