[306732] For child modules of a web module in Tomcat publishing, honor the child module's deployPath URI instead of hard coding "WEB-INF/lib" as the location within the web module.  Also handle child jar modules in addition to child project modules, just to be safe.
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/PublishOperation2.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/PublishOperation2.java
index 31567df..ede75bc 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/PublishOperation2.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/PublishOperation2.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2008 IBM Corporation and others.
+ * Copyright (c) 2005, 2010 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
@@ -15,6 +15,8 @@
 import java.util.List;
 
 import org.eclipse.core.runtime.*;
+import org.eclipse.jst.server.core.IJ2EEModule;
+import org.eclipse.jst.server.core.IWebModule;
 import org.eclipse.wst.server.core.IModule;
 import org.eclipse.wst.server.core.IServer;
 import org.eclipse.wst.server.core.model.*;
@@ -74,10 +76,31 @@
 	 */
 	public void execute(IProgressMonitor monitor, IAdaptable info) throws CoreException {
 		List status = new ArrayList();
-		if (module.length == 1) { // web module
+		// If parent web module
+		if (module.length == 1) {
 			publishDir(module[0], status, monitor);
-		} else { // utility module
-			publishJar(status, monitor);
+		}
+		// Else a child module
+		else {
+			// Try to determine the URI for the child module
+			IWebModule webModule = (IWebModule)module[0].loadAdapter(IWebModule.class, monitor);
+			String childURI = null;
+			if (webModule != null) {
+				childURI = webModule.getURI(module[1]);
+			}
+			// Try to determine if child is binary
+			IJ2EEModule childModule = (IJ2EEModule)module[1].loadAdapter(IJ2EEModule.class, monitor);
+			boolean isBinary = false;
+			if (childModule != null) {
+				isBinary = childModule.isBinary();
+			}
+
+			if (isBinary) {
+				publishArchiveModule(childURI, status, monitor);
+			}
+			else {
+				publishJar(childURI, status, monitor);
+			}
 		}
 		throwException(status);
 		server.setModulePublishState2(module, IServer.PUBLISH_STATE_NONE);
@@ -116,16 +139,20 @@
 		}
 	}
 
-	private void publishJar(List status, IProgressMonitor monitor) throws CoreException {
+	private void publishJar(String jarURI, List status, IProgressMonitor monitor) throws CoreException {
 		IPath path = server.getModuleDeployDirectory(module[0]);
-		path = path.append("WEB-INF").append("lib");
-		IPath jarPath = path.append(module[1].getName() + ".jar");
+		if (jarURI == null) {
+			jarURI = "WEB-INF/lib/" + module[1].getName() + ".jar";
+		}
+		IPath jarPath = path.append(jarURI);
+		path = jarPath.removeLastSegments(1);
 		
 		// Remove if requested or if previously published and are now serving without publishing
 		if (kind == IServer.PUBLISH_CLEAN || deltaKind == ServerBehaviourDelegate.REMOVED
 				|| server.getTomcatServer().isServeModulesWithoutPublish()) {
-			if (jarPath.toFile().exists())
-				jarPath.toFile().delete();
+			File file = jarPath.toFile();
+			if (file.exists())
+				file.delete();
 			
 			if (deltaKind == ServerBehaviourDelegate.REMOVED
 					|| server.getTomcatServer().isServeModulesWithoutPublish())
@@ -141,12 +168,49 @@
 		// make directory if it doesn't exist
 		if (!path.toFile().exists())
 			path.toFile().mkdirs();
-		
+
 		IModuleResource[] mr = server.getResources(module);
 		IStatus[] stat = helper.publishZip(mr, jarPath, monitor);
 		addArrayToList(status, stat);
 	}
 
+	private void publishArchiveModule(String jarURI, List status, IProgressMonitor monitor) {
+		IPath path = server.getModuleDeployDirectory(module[0]);
+		if (jarURI == null) {
+			jarURI = "WEB-INF/lib/" + module[1].getName();
+		}
+		IPath jarPath = path.append(jarURI);
+		path = jarPath.removeLastSegments(1);
+
+		// Remove if requested or if previously published and are now serving without publishing
+		if (kind == IServer.PUBLISH_CLEAN || deltaKind == ServerBehaviourDelegate.REMOVED
+				|| server.getTomcatServer().isServeModulesWithoutPublish()) {
+			File file = jarPath.toFile();
+			if (file.exists()) {
+				file.delete();
+			}
+			
+			if (deltaKind == ServerBehaviourDelegate.REMOVED
+					|| server.getTomcatServer().isServeModulesWithoutPublish())
+				return;
+		}
+		
+		if (kind == IServer.PUBLISH_CLEAN || kind == IServer.PUBLISH_FULL) {
+			IModuleResource[] mr = server.getResources(module);
+			IStatus[] stat = helper.publishFull(mr, path, monitor);
+			addArrayToList(status, stat);
+			return;
+		}
+		
+		IModuleResourceDelta[] delta = server.getPublishedResourceDelta(module);
+		
+		int size = delta.length;
+		for (int i = 0; i < size; i++) {
+			IStatus[] stat = helper.publishDelta(delta[i], path, monitor);
+			addArrayToList(status, stat);
+		}
+	}
+
 	/**
 	 * Utility method to throw a CoreException based on the contents of a list of
 	 * error and warning status.
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatServerBehaviour.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatServerBehaviour.java
index 4323ea1..6c96d8d 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatServerBehaviour.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatServerBehaviour.java
@@ -27,6 +27,8 @@
 import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
 import org.eclipse.jdt.launching.IVMInstall;
 import org.eclipse.jdt.launching.JavaRuntime;
+import org.eclipse.jst.server.core.IJ2EEModule;
+import org.eclipse.jst.server.core.IWebModule;
 import org.eclipse.osgi.util.NLS;
 
 import org.eclipse.wst.server.core.*;
@@ -275,10 +277,32 @@
 		}
 		
 		PublishHelper helper = new PublishHelper(getRuntimeBaseDirectory().append("temp").toFile());
-		if (moduleTree.length == 1) // web module
+		// If parent web module
+		if (moduleTree.length == 1) {
 			publishDir(deltaKind, p, moduleTree, helper, monitor);
-		else // utility jar
-			publishJar(kind, deltaKind, p, moduleTree, helper, monitor);
+		}
+		// Else a child module
+		else {
+			// Try to determine the URI for the child module
+			IWebModule webModule = (IWebModule)moduleTree[0].loadAdapter(IWebModule.class, monitor);
+			String childURI = null;
+			if (webModule != null) {
+				childURI = webModule.getURI(moduleTree[1]);
+			}
+			// Try to determine if child is binary
+			IJ2EEModule childModule = (IJ2EEModule)moduleTree[1].loadAdapter(IJ2EEModule.class, monitor);
+			boolean isBinary = false;
+			if (childModule != null) {
+				isBinary = childModule.isBinary();
+			}
+
+			if (isBinary) {
+				publishArchiveModule(childURI, kind, deltaKind, p, moduleTree, helper, monitor);
+			}
+			else {
+				publishJar(childURI, kind, deltaKind, p, moduleTree, helper, monitor);
+			}
+		}
 		
 		setModulePublishState(moduleTree, IServer.PUBLISH_STATE_NONE);
 		
@@ -320,11 +344,23 @@
 			IPath path = getModuleDeployDirectory(module[0]);
 			IModuleResource[] mr = getResources(module);
 			IPath [] jarPaths = null;
+			IWebModule webModule = (IWebModule)module[0].loadAdapter(IWebModule.class, monitor);
 			IModule [] childModules = getServer().getChildModules(module, monitor);
 			if (childModules != null && childModules.length > 0) {
 				jarPaths = new IPath[childModules.length];
 				for (int i = 0; i < childModules.length; i++) {
-					jarPaths[i] = new Path("WEB-INF/lib").append(childModules[i].getName() + ".jar");
+					if (webModule != null) {
+						jarPaths[i] = new Path(webModule.getURI(childModules[i]));
+					}
+					else {
+						IJ2EEModule childModule = (IJ2EEModule)childModules[i].loadAdapter(IJ2EEModule.class, monitor);
+						if (childModule != null && childModule.isBinary()) {
+							jarPaths[i] = new Path("WEB-INF/lib").append(childModules[i].getName());
+						}
+						else {
+							jarPaths[i] = new Path("WEB-INF/lib").append(childModules[i].getName() + ".jar");
+						}
+					}
 				}
 			}
 			IStatus[] stat = helper.publishSmart(mr, path, jarPaths, monitor);
@@ -343,7 +379,7 @@
 	 * @param monitor
 	 * @throws CoreException
 	 */
-	private void publishJar(int kind, int deltaKind, Properties p, IModule[] module, PublishHelper helper, IProgressMonitor monitor) throws CoreException {
+	private void publishJar(String jarURI, int kind, int deltaKind, Properties p, IModule[] module, PublishHelper helper, IProgressMonitor monitor) throws CoreException {
 		// Remove if requested or if previously published and are now serving without publishing
 		if (deltaKind == REMOVED || getTomcatServer().isServeModulesWithoutPublish()) {
 			try {
@@ -357,8 +393,11 @@
 			}
 		} else {
 			IPath path = getModuleDeployDirectory(module[0]);
-			path = path.append("WEB-INF").append("lib");
-			IPath jarPath = path.append(module[1].getName() + ".jar");
+			if (jarURI == null) {
+				jarURI = "WEB-INF/lib" + module[1].getName() + ".jar";
+			}
+			IPath jarPath = path.append(jarURI);
+			path = jarPath.removeLastSegments(1);
 			if (!path.toFile().exists()) {
 				path.toFile().mkdirs();
 			} else {
@@ -380,6 +419,46 @@
 		}
 	}
 
+	private void publishArchiveModule(String jarURI, int kind, int deltaKind, Properties p, IModule[] module, PublishHelper helper, IProgressMonitor monitor) throws CoreException {
+		// Remove if requested or if previously published and are now serving without publishing
+		if (deltaKind == REMOVED || getTomcatServer().isServeModulesWithoutPublish()) {
+			try {
+				String publishPath = (String) p.get(module[1].getId());
+				if (publishPath != null) {
+					new File(publishPath).delete();
+					p.remove(module[1].getId());
+				}
+			} catch (Exception e) {
+				throw new CoreException(new Status(IStatus.WARNING, TomcatPlugin.PLUGIN_ID, 0, "Could not remove archive module", e));
+			}
+		} else {
+			List status = new ArrayList();
+			IPath path = getModuleDeployDirectory(module[0]);
+			if (jarURI == null) {
+				jarURI = "WEB-INF/lib" + module[1].getName();
+			}
+			IPath jarPath = path.append(jarURI);
+			path = jarPath.removeLastSegments(1);
+			if (!path.toFile().exists()) {
+				path.toFile().mkdirs();
+			} else {
+				// If file still exists and we are not forcing a new one to be built
+				if (jarPath.toFile().exists() && kind != IServer.PUBLISH_CLEAN && kind != IServer.PUBLISH_FULL) {
+					// avoid changes if no changes to module since last publish
+					IModuleResourceDelta[] delta = getPublishedResourceDelta(module);
+					if (delta == null || delta.length == 0)
+						return;
+				}
+			}
+			
+			IModuleResource[] mr = getResources(module);
+			IStatus[] stat = helper.publishFull(mr, path, monitor);
+			PublishOperation2.addArrayToList(status, stat);
+			PublishOperation2.throwException(status);
+			p.put(module[1].getId(), jarPath.toOSString());
+		}
+	}
+
 	protected void publishFinish(IProgressMonitor monitor) throws CoreException {
 		IStatus status;
 		IPath baseDir = getRuntimeBaseDirectory();