[151121] Refactoring non-Java src folders does not automatically update component mappings
diff --git a/plugins/org.eclipse.jst.j2ee/refactor/org/eclipse/jst/j2ee/refactor/listeners/J2EEElementChangedListener.java b/plugins/org.eclipse.jst.j2ee/refactor/org/eclipse/jst/j2ee/refactor/listeners/J2EEElementChangedListener.java
index ae14619..a40ec7d 100644
--- a/plugins/org.eclipse.jst.j2ee/refactor/org/eclipse/jst/j2ee/refactor/listeners/J2EEElementChangedListener.java
+++ b/plugins/org.eclipse.jst.j2ee/refactor/org/eclipse/jst/j2ee/refactor/listeners/J2EEElementChangedListener.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005 BEA Systems, Inc.
+ * Copyright (c) 2005-2007 BEA Systems, Inc.
  * 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
@@ -11,9 +11,13 @@
 package org.eclipse.jst.j2ee.refactor.listeners;
 
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResourceDelta;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.resources.WorkspaceJob;
 import org.eclipse.core.runtime.CoreException;
@@ -32,9 +36,13 @@
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jem.util.logger.proxy.Logger;
 import org.eclipse.jst.j2ee.internal.J2EEConstants;
+import org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin;
 import org.eclipse.jst.j2ee.internal.project.J2EEProjectUtilities;
 import org.eclipse.wst.common.componentcore.ComponentCore;
 import org.eclipse.wst.common.componentcore.ModuleCoreNature;
+import org.eclipse.wst.common.componentcore.internal.ComponentResource;
+import org.eclipse.wst.common.componentcore.internal.StructureEdit;
+import org.eclipse.wst.common.componentcore.internal.WorkbenchComponent;
 import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
 import org.eclipse.wst.common.componentcore.resources.IVirtualFolder;
 
@@ -62,24 +70,63 @@
 		if (kind == IJavaElementDelta.CHANGED) {
 			final int flags = delta.getFlags();
 			final IJavaElement element = delta.getElement();
-			if ((flags & IJavaElementDelta.F_CHILDREN) == IJavaElementDelta.F_CHILDREN) {
-				if (element instanceof IJavaModel) {
+			if (element instanceof IJavaModel) {
+				if ((flags & IJavaElementDelta.F_CHILDREN) == IJavaElementDelta.F_CHILDREN) {
 					final IJavaElementDelta[] children = delta.getChangedChildren();
 					for (int i = 0; i < children.length; i++) {
 						// handle all of the IJavaProject children
 						processJavaElementDelta(children[i]);
-					}					
-				} else if (element instanceof IJavaProject
-						&& (flags & IJavaElementDelta.F_CLASSPATH_CHANGED) != 0) {
-					final IJavaProject jproject = (IJavaProject) element;
-					final IProject project = jproject.getProject();
-					// make certain this is a J2EE project
-					if (ModuleCoreNature.getModuleCoreNature(project) != null) {
-						try {
-							alterMapping(delta.getAffectedChildren(), jproject, project);
-						} catch (CoreException ce) {
-							Logger.getLogger().logError(ce);
+					}
+				}
+			} else if (element instanceof IJavaProject) {
+				final IJavaProject jproject = (IJavaProject) element;
+				final IProject project = jproject.getProject();
+				final List pathsToAdd = new ArrayList();
+				final List pathsToRemove = new ArrayList();
+
+				// make certain this is a J2EE project
+				if (ModuleCoreNature.getModuleCoreNature(project) != null) {
+					IVirtualComponent c = ComponentCore.createComponent(project);
+					try {
+						// Did the classpath change?
+						if ((flags & IJavaElementDelta.F_CHILDREN) == IJavaElementDelta.F_CHILDREN
+								&& (flags & IJavaElementDelta.F_CLASSPATH_CHANGED) != 0) {
+							getJavaSrcMappings(c, delta.getAffectedChildren(), jproject, pathsToAdd, pathsToRemove);
 						}
+
+						// Did a non-Java folder change name?
+						final IResourceDelta[] deltas = delta.getResourceDeltas();
+						if (deltas != null && deltas.length > 0) {
+							getNonJavaFolderMappings(deltas, c, pathsToAdd, pathsToRemove);
+						}
+
+						// If there are corrections to the virtual path mappings, execute them in a Job
+						if (!pathsToAdd.isEmpty() || !pathsToRemove.isEmpty()) {
+							WorkspaceJob job = new WorkspaceJob("J2EEComponentMappingUpdateJob") {							
+								public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
+									for(int i=0;i<pathsToAdd.size(); i++){
+										Object[] toAdd = (Object[]) pathsToAdd.get(i);
+										final IVirtualFolder destFolder = (IVirtualFolder) toAdd[1];
+										final IPath pathToAdd = (IPath) toAdd[0];
+										destFolder.createLink(pathToAdd, 0, monitor);
+									}
+									for(int i=0;i<pathsToRemove.size(); i++){
+										Object[] toRemove = (Object[]) pathsToRemove.get(i);
+										final IVirtualFolder destFolder = (IVirtualFolder) toRemove[1];
+										final IPath pathToRemove = (IPath) toRemove[0];
+										destFolder.removeLink(pathToRemove, 0, monitor);
+									}
+									return Status.OK_STATUS;
+								}
+								public boolean belongsTo(final Object family) {
+									return PROJECT_COMPONENT_UPDATE_JOB_FAMILY.equals(family);
+								}
+							};
+							job.setRule(ResourcesPlugin.getWorkspace().getRoot());
+							job.schedule();
+						}						
+					} catch (CoreException ce) {
+						Logger.getLogger(J2EEPlugin.PLUGIN_ID).logError(ce);
 					}
 				}
 			}
@@ -87,12 +134,15 @@
 	}
 
 	/*
-	 * Adds or removes a resource mapping from the .component file.
-	 */
-	private void alterMapping(final IJavaElementDelta[] children, final IJavaProject jproject,
-			final IProject project) throws CoreException {
-		List pathsToAdd = null;
-		List pathsToRemove = null;
+	 * Computes the virtual component path mapping changes the need to be made due to 
+	 * Java src path changes.
+	 */ 
+	private void getJavaSrcMappings(final IVirtualComponent virtualComp, final IJavaElementDelta[] children, final IJavaProject jproject, final List pathsToAdd, final List pathsToRemove) 
+		throws CoreException {
+		
+		// get the default destination folder
+		final IVirtualFolder defaultDestFolder = getDestinationFolder(virtualComp);
+		
 		for (int i = 0; i < children.length; i++) {
 			final IJavaElementDelta delta = children[i];
 			final IJavaElement element = delta.getElement();
@@ -117,73 +167,89 @@
 					if (delta.getKind() == IJavaElementDelta.ADDED || 
 							(flags & IJavaElementDelta.F_ADDED_TO_CLASSPATH) == IJavaElementDelta.F_ADDED_TO_CLASSPATH) {
 						if (!abortAdd) {
-							if(pathsToAdd == null){
-								pathsToAdd = new ArrayList();
-							}
-							final IPath path = root.getPath().removeFirstSegments(1);
-							pathsToAdd.add(path);
+							final IPath pathToAdd = root.getPath().removeFirstSegments(1);
+							pathsToAdd.add(new Object[]{pathToAdd, defaultDestFolder});
 							// if the added src path was moved from another location, remove any mapping for that
 							// location
 							if ((flags & IJavaElementDelta.F_MOVED_FROM) == IJavaElementDelta.F_MOVED_FROM) {
 								final IJavaElement movedFromElement = delta.getMovedFromElement();
-								if(pathsToRemove == null){
-									pathsToRemove = new ArrayList();
-								}
-								pathsToRemove.add(movedFromElement.getPath().removeFirstSegments(1));
+								final IPath pathToRemove = movedFromElement.getPath().removeFirstSegments(1);
+								pathsToRemove.add(new Object[]{pathToRemove, defaultDestFolder});
 							}
 						}
 					// getting a kind = REMOVED and flags = 0 for removal of the folder (w/o removing the CPE), probably
 				    // should not be generated
 					} else if ((flags & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) == IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) {
-						if(pathsToRemove == null){
-							pathsToRemove = new ArrayList();
-						}
 						IPath path = root.getPath().removeFirstSegments(1);
-						pathsToRemove.add(path);
+						pathsToRemove.add(new Object[]{path, defaultDestFolder});
 					}
 				}
 			}
 		}
-		if(pathsToAdd != null || pathsToRemove != null){
-			final List jobPathsToAdd = pathsToAdd;
-			final List jobPathsToRemove = pathsToRemove;
-			WorkspaceJob job = new WorkspaceJob("J2EEComponentMappingUpdateJob") {							
-				public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
-					IVirtualFolder destFolder = getDestinationFolder(project);
-					IPath path = null;
-					if(jobPathsToAdd != null){
-						for(int i=0;i<jobPathsToAdd.size(); i++){
-							path = (IPath)jobPathsToAdd.get(i);
-							destFolder.createLink(path, 0, monitor);
-						}
-					}
-					if(jobPathsToRemove != null){
-						for(int i=0;i<jobPathsToRemove.size(); i++){
-							path = (IPath)jobPathsToRemove.get(i);
-							destFolder.removeLink(path, 0, monitor);
-						}
-					}
-					return Status.OK_STATUS;
-				}
-				public boolean belongsTo(final Object family) {
-					return PROJECT_COMPONENT_UPDATE_JOB_FAMILY.equals(family);
-				}
-			};
-			job.setRule(ResourcesPlugin.getWorkspace().getRoot());
-			job.schedule();
+	}
+	
+	/*
+	 * Computes the virtual component path mapping changes the need to be made due to changes to
+	 * non-Java folders. 
+	 */ 
+	private void getNonJavaFolderMappings(final IResourceDelta[] deltas, final IVirtualComponent virtualComp, final List pathsToAdd, final List pathsToRemove) throws CoreException {
+		final IVirtualFolder rootFolder = virtualComp.getRootFolder();
+		final Map sourceToRuntime = getResourceMappings(virtualComp.getProject());
+		for (int i = 0; i < deltas.length; i++) {
+			final IResourceDelta delta = deltas[i];
+			processResourceDelta(delta, rootFolder, sourceToRuntime, pathsToAdd, pathsToRemove);
 		}
 	}
 	
+	private void processResourceDelta(final IResourceDelta delta, final IVirtualFolder rootFolder, final Map sourceToRuntime, final List pathsToAdd, final List pathsToRemove) throws CoreException {
+		final int kind = delta.getKind();
+		if (kind == IResourceDelta.CHANGED) {
+			IResourceDelta[] childDeltas = delta.getAffectedChildren();
+			for (int i = 0; i < childDeltas.length; i++) {
+				processResourceDelta(childDeltas[i], rootFolder, sourceToRuntime, pathsToAdd, pathsToRemove);
+			}
+		} else {
+			final int flags = delta.getFlags();
+			if ((flags & IResourceDelta.MOVED_FROM) == IResourceDelta.MOVED_FROM) {
+				final IPath movedFrom = delta.getMovedFromPath().removeFirstSegments(1);
+				final IPath movedTo = delta.getFullPath().removeFirstSegments(1);
+				final IPath runtimePath = (IPath) sourceToRuntime.get(movedFrom);
+				// does the old path have a virtual component mapping?
+				if (runtimePath != null) {
+					final IVirtualFolder folder = rootFolder.getFolder(runtimePath);
+					pathsToRemove.add(new Object[]{movedFrom, folder});
+					pathsToAdd.add(new Object[]{movedTo, folder});
+				}
+			}
+		}
+	}
 	
+	private Map getResourceMappings(final IProject project){
+		final Map sourceToRuntime = new HashMap();
+		StructureEdit core = null;
+		try {
+			core = StructureEdit.getStructureEditForRead(project);
+			final WorkbenchComponent component = core.getComponent();
+			if (null != component) {
+				final List currentResources = component.getResources();
+				for (Iterator iter = currentResources.iterator(); iter.hasNext();) {
+					final ComponentResource resource = (ComponentResource) iter.next();
+					sourceToRuntime.put(resource.getSourcePath().makeRelative(), resource.getRuntimePath());
+				}
+			}
+			return sourceToRuntime;
+		} finally {
+			if (core != null)
+				core.dispose();
+		}
+	}
 
 	/*
 	 * Retrieves the IVirtualFolder to which Java src folders should be mapped
 	 */
-	private IVirtualFolder getDestinationFolder(final IProject project) throws CoreException {
-		final IVirtualComponent c = ComponentCore.createComponent(project);
-		c.create(0, null);
+	private IVirtualFolder getDestinationFolder(final IVirtualComponent c) throws CoreException {
 		final IVirtualFolder root = c.getRootFolder();
-		if (J2EEProjectUtilities.isDynamicWebProject(project)) {
+		if (J2EEProjectUtilities.isDynamicWebProject(c.getProject())) {
 			// web projects map to WEB-INF/classes
 			return root.getFolder(new Path(J2EEConstants.WEB_INF_CLASSES));
 		}