/**********************************************************************
 * Copyright (c) 2007, 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:
 *    Igor Fedorenko & Fabrizio Giustina - Initial API and implementation
 *    Matteo TURRA - Support for multiple web resource paths
 **********************************************************************/
package org.eclipse.jst.server.tomcat.core.internal;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jst.server.tomcat.core.internal.wst.IModuleVisitor;
import org.eclipse.jst.server.tomcat.core.internal.xml.Factory;
import org.eclipse.jst.server.tomcat.core.internal.xml.server40.Context;
import org.eclipse.jst.server.tomcat.core.internal.xml.server40.Loader;
import org.eclipse.jst.server.tomcat.core.internal.xml.server40.ServerInstance;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualFile;
import org.eclipse.wst.common.componentcore.resources.IVirtualResource;
import org.eclipse.wst.server.core.IModule;
import org.eclipse.wst.server.core.ServerUtil;

/**
 * Handles "publishing" for servers that can load classes and resources directly
 * from the workspace. Instead of creating and deploying jars to the webapp this
 * simply update the virtual classpath in the context xml file.
 */
public class TomcatPublishModuleVisitor implements IModuleVisitor {

    /**
     * Server base path (Catalina base).
     */
    protected final IPath baseDir;
    
    /**
     * Tomcat version (from "server.info" property in org.apache.catalina.util.ServerInfo.properties).
     */
    protected final String tomcatVersion;
    
    /**
     * Server instance in which to modify the context
     */
    protected final ServerInstance serverInstance;

    /**
     * Catalina.properties loader to add global classpath entries
     */
    protected final String sharedLoader;

    /**
     * 
     */
    protected final boolean enableMetaInfResources;
    
    /**
     * Classpath entries added by ear configurations.
     */
    protected final List earCommonResources = new ArrayList();

    /**
     * List of classpath elements that will be used by the custom tomcat loader.
     * This set should include any class dir from referenced project.
     */
    protected Set virtualClassClasspathElements = new LinkedHashSet();
    protected Set virtualJarClasspathElements = new LinkedHashSet();

    /**
     * Map of resources found in "META-INF/resources" folder of dependent projects
     */
    protected Map virtualDependentResources = new LinkedHashMap();

    /**
     * Instantiate a new TomcatPublishModuleVisitor
     * 
     * @param baseDir catalina base path
     * @param tomcatVersion tomcat version
     * @param serverInstance ServerInstance containing server.xml contents
     * @param sharedLoader string value for shared.loader catalina configuration property
     * @param enableMetaInfResources flag to indicate if Servlet 3.0 "META-INF/resources" feature should be supported
     */
    TomcatPublishModuleVisitor(IPath baseDir, String tomcatVersion, ServerInstance serverInstance, String sharedLoader, boolean enableMetaInfResources) {
        this.baseDir = baseDir;
        this.tomcatVersion = tomcatVersion;
        this.serverInstance = serverInstance;
        this.sharedLoader = sharedLoader;
        this.enableMetaInfResources = enableMetaInfResources;
    }

    /**
     * @see IModuleVisitor#visitWebComponent(IVirtualComponent)
     */
    public void visitWebComponent(IVirtualComponent component)
            throws CoreException {
        // nothing to do, everything is done in endVisitWebComponent
    }

    /**
     * @see IModuleVisitor#visitArchiveComponent(IPath, IPath)
     */
    public void visitArchiveComponent(IPath runtimePath, IPath workspacePath) {
        addVirtualJarResource(runtimePath, workspacePath);
    }

    /**
     * @see IModuleVisitor#visitDependentJavaProject(IJavaProject javaProject)
     */
    public void visitDependentJavaProject(IJavaProject javaProject) {
        // Useful for finding source folders, so do nothing.
    }

    /**
     * @see IModuleVisitor#visitDependentComponent(IPath, IPath)
     */
    public void visitDependentComponent(IPath runtimePath, IPath workspacePath) {
        addVirtualJarResource(runtimePath, workspacePath);
    }

    /**
     * @see IModuleVisitor#visitWebResource(IPath, IPath)
     */
    public void visitWebResource(IPath runtimePath, IPath workspacePath) {
        addVirtualClassResource(runtimePath, workspacePath);
    }

    /**
     * @see IModuleVisitor#visitDependentContentResource(IPath, IPath)
     */
    public void visitDependentContentResource(IPath runtimePath, IPath workspacePath) {
    	// Currently, only handle "META-INF/resources" folders if supported
    	if (enableMetaInfResources) {
        	addContentResource(runtimePath, workspacePath);
    	}
    }

    /**
     * @see IModuleVisitor#visitEarResource(IPath, IPath)
     */
    public void visitEarResource(IPath runtimePath, IPath workspacePath) {
        earCommonResources.add(workspacePath.toOSString());
    }

    /**
     * @see IModuleVisitor#endVisitEarComponent(IVirtualComponent)
     */
    public void endVisitEarComponent(IVirtualComponent component)
            throws CoreException {
        if (earCommonResources.size() > 0) {
            try {
                CatalinaPropertiesUtil.addGlobalClasspath(baseDir.append(
                		"conf/catalina.properties").toFile(), sharedLoader,
                		(String[]) earCommonResources.toArray(new String[earCommonResources.size()]));
            } catch (IOException e) {
                Trace.trace(Trace.WARNING, "Unable to add ear path entries to catalina.properties", e);
            } finally {
                earCommonResources.clear();
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    public void endVisitWebComponent(IVirtualComponent component)
            throws CoreException {

        // track context changes, don't rewrite if not needed
        boolean dirty = false;

        IModule module = ServerUtil.getModule(component.getProject());

        // we need this for the user-specified context path
        Context context = findContext(module);
        if (context == null) {
        	String name = module != null ? module.getName() : component.getName();
    		Trace.trace(Trace.SEVERE, "Could not find context for module " + name);
    		throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0,
    				NLS.bind(Messages.errorPublishContextNotFound, name), null));
        }

        String contextName = null;
        boolean reloadable = true;

        contextName = context.getPath();
        reloadable = Boolean.valueOf(context.getReloadable()).booleanValue();

        // now strip initial /
        if (contextName.startsWith("/")) {
            contextName = contextName.substring(1);
        }

        // root context is deployed with the "ROOT" name in tomcat
        if ("".equals(contextName)) {
            contextName = "ROOT";
        }

        // handle project context.xml
        Context projectContext = getProjectContextXml(component);

        if (projectContext != null) {
            // copy configuration to server context
            projectContext.copyChildrenTo(context);

            Map attrs = projectContext.getAttributes();
            Iterator iter = attrs.keySet().iterator();
            while (iter.hasNext()) {
                String name = (String) iter.next();
                if (!name.equalsIgnoreCase("path")
                        && !name.equalsIgnoreCase("docBase")
                        && !name.equalsIgnoreCase("source")) {
                    String value = (String) attrs.get(name);
                    String actualValue = context.getAttributeValue(name);
                    if (!value.equals(actualValue)) {
                        context.setAttributeValue(name, value);
                        dirty = true;
                    }
                }
            }
        }

        // handle changes in docBase
        String docBase = component.getRootFolder().getUnderlyingFolder()
                .getLocation().toOSString();
        if (!docBase.equals(context.getDocBase())) {
            dirty = true;
            context.setDocBase(docBase);
        }

        // handle changes in reloadable flag
        if (reloadable != (Boolean.valueOf((context.getReloadable()))
                .booleanValue())) {
            dirty = true;
            context.setReloadable(Boolean.toString(reloadable));
        }

        String path = (contextName.equals("ROOT") ? "" : "/" + contextName);
        // handle changes in the path
        // PATH is required for tomcat 5.0, but ignored in tomcat 5.5
        if (!path.equals(context.getPath())) {
            dirty = true;
            context.setPath(path);
        }

        context.getResources().setClassName(
                "org.eclipse.jst.server.tomcat.loader.WtpDirContext");

        Loader loader = context.getLoader();

        loader.setClassName("org.eclipse.jst.server.tomcat.loader.WtpWebappLoader");

        // required for tomcat 5.5.20 due to the change in
        // http://issues.apache.org/bugzilla/show_bug.cgi?id=39704
        loader.setUseSystemClassLoaderAsParent(Boolean.FALSE.toString());

        // Build the virtual classPath setting
        StringBuffer vcBuffer = new StringBuffer();
		// Build list of additional resource paths and check for additional jars
		StringBuffer rpBuffer = new StringBuffer();

		boolean isTomcat7 = tomcatVersion.startsWith("7.");
		// Add WEB-INF/classes elements to both settings
		for (Iterator iterator = virtualClassClasspathElements.iterator();
				iterator.hasNext();) {
			Object element = iterator.next();
			if (vcBuffer.length() > 0) {
				vcBuffer.append(";");
			}
			vcBuffer.append(element);
			if (isTomcat7) {
				if (rpBuffer.length() > 0) {
					rpBuffer.append(";");
				}
				// Add to resource paths too, so resource artifacts can be found
				rpBuffer.append("/WEB-INF/classes").append("|").append(element);
			}
        }
        if (vcBuffer.length() > 0 && virtualJarClasspathElements.size() > 0) {
        	vcBuffer.append(";");
        }
        for (Iterator iterator = virtualJarClasspathElements.iterator();
        		iterator.hasNext();) {
        	vcBuffer.append(iterator.next());
        	if (iterator.hasNext()) {
        		vcBuffer.append(";");
        	}
        }
        virtualClassClasspathElements.clear();
        virtualJarClasspathElements.clear();

		Set rtPathsProcessed = new HashSet();
		Set locationsIncluded = new HashSet();
		locationsIncluded.add(docBase);
		Map retryLocations = new HashMap();
		IVirtualResource [] virtualResources = component.getRootFolder().getResources("");
		// Loop over the module's resources
		for (int i = 0; i < virtualResources.length; i++) {
			String rtPath = virtualResources[i].getRuntimePath().toString();
			// Note: The virtual resources returned only know their runtime path.
			// Asking for the project path for this resource performs a lookup
			// that will only return the path for the first mapping for the
			// runtime path.  Thus use of getUnderlyingResources() is necessary.
			// However, this returns matching resources from all mappings so
			// we have to try to keep only those that are mapped directly
			// to the runtime path in the .components file.

			// If this runtime path has not yet been processed
			if (!rtPathsProcessed.contains(rtPath)) {
				// If not a Java related resource
				if (!"/WEB-INF/classes".equals(rtPath)) {
					// Get all resources for this runtime path
					IResource[] underlyingResources = virtualResources[i].getUnderlyingResources();
					// If resource is mapped to "/", then we know it corresponds directly
					// to a mapping in the .components file
					if ("/".equals(rtPath)) {
						for (int j = 0; j < underlyingResources.length; j++) {
							IPath resLoc = underlyingResources[j].getLocation();
							String location = resLoc.toOSString();
							if (!location.equals(docBase)) {
								if (rpBuffer.length() != 0) {
									rpBuffer.append(";");
								}
								// Add this location to extra paths setting
								rpBuffer.append(location);
								// Add to the set of locations included
								locationsIncluded.add(location);
								// Check if this extra content location contains jars
								File webInfLib = resLoc.append("WEB-INF/lib").toFile();
								// If this "WEB-INF/lib" exists and is a directory, add
								// its jars to the virtual classpath
								if (webInfLib.exists() && webInfLib.isDirectory()) {
									String [] jars = webInfLib.list(new FilenameFilter() {
											public boolean accept(File dir, String name) {
												File f = new File(dir, name);
												return f.isFile() && name.endsWith(".jar");
											}
										});
									for (int k = 0; k < jars.length; k++) {
										if (vcBuffer.length() != 0) {
											vcBuffer.append(";");
										}
										vcBuffer.append(webInfLib.getPath() + File.separator + jars[k]);
									}
								}
							}
						}
					}
					// Else this runtime path is something other than "/"
					else {
						int idx = rtPath.lastIndexOf('/');
						// If a "normal" runtime path
						if (idx >= 0) {
							// Get the name of the last segment in the runtime path
							String lastSegment = rtPath.substring(idx + 1);
							// Check the underlying resources to determine which correspond to mappings
							for (int j = 0; j < underlyingResources.length; j++) {
								IPath resLoc = underlyingResources[j].getLocation();
								String location = resLoc.toOSString();
								// If the last segment of the runtime path doesn't match the
								// the last segment of the location, then we have a direct mapping
								// from the .contents file.
								if (!lastSegment.equals(resLoc.lastSegment())) {
									if (rpBuffer.length() != 0) {
										rpBuffer.append(";");
									}
									// Add this location to extra paths setting
									rpBuffer.append(rtPath).append("|").append(location);
									// Add to the set of locations included
									locationsIncluded.add(location);
									// Check if this extra content location contains jars
									File webInfLib = null;
									if ("/WEB-INF".equals(rtPath)) {
										webInfLib = resLoc.append("lib").toFile();
									}
									else if ("/WEB-INF/lib".equals(rtPath)) {
										webInfLib = resLoc.toFile();
									}
									// If this "WEB-INF/lib" exists and is a directory, add
									// its jars to the virtual classpath
									if (webInfLib != null && webInfLib.exists() && webInfLib.isDirectory()) {
										String [] jars = webInfLib.list(new FilenameFilter() {
												public boolean accept(File dir, String name) {
													File f = new File(dir, name);
													return f.isFile() && name.endsWith(".jar");
												}
											});
										for (int k = 0; k < jars.length; k++) {
											if (vcBuffer.length() != 0) {
												vcBuffer.append(";");
											}
											vcBuffer.append(webInfLib.getPath() + File.separator + jars[k]);
										}
									}
								}
								// Else last segment of runtime path did match the last segment
								// of the location.  We likely have a subfolder of a mapping
								// that matches a portion of the runtime path.
								else {
									// Since we can't be sure, save so it can be check again later
									retryLocations.put(location, rtPath);
								}
							}
						}
					}
				}
				// Add the runtime path to those already processed
				rtPathsProcessed.add(rtPath);
			}
		}
		// If there are locations to retry, add any not yet included in extra paths setting
		if (!retryLocations.isEmpty()) {
			// Remove retry locations already included in the extra paths
			for (Iterator iterator = retryLocations.keySet().iterator(); iterator.hasNext();) {
				String location = (String)iterator.next();
				for (Iterator iterator2 = locationsIncluded.iterator(); iterator2.hasNext();) {
					String includedLocation = (String)iterator2.next();
					if (location.equals(includedLocation) || location.startsWith(includedLocation + File.separator)) {
						iterator.remove();
						break;
					}
				}
			}
			// If any entries are left, include them in the extra paths
			if (!retryLocations.isEmpty()) {
				for (Iterator iterator = retryLocations.entrySet().iterator(); iterator.hasNext();) {
					Map.Entry entry = (Map.Entry)iterator.next();
					String location = (String)entry.getKey();
					String rtPath = (String)entry.getValue();
					if (rpBuffer.length() != 0) {
						rpBuffer.append(";");
					}
					rpBuffer.append(rtPath).append("|").append(location);
					// Check if this extra content location contains jars
					File webInfLib = null;
					if ("/WEB-INF".equals(rtPath)) {
						webInfLib = new File(location, "lib");
					}
					else if ("/WEB-INF/lib".equals(rtPath)) {
						webInfLib = new File(location);
					}
					// If this "WEB-INF/lib" exists and is a directory, add
					// its jars to the virtual classpath
					if (webInfLib != null && webInfLib.exists() && webInfLib.isDirectory()) {
						String [] jars = webInfLib.list(new FilenameFilter() {
								public boolean accept(File dir, String name) {
									File f = new File(dir, name);
									return f.isFile() && name.endsWith(".jar");
								}
							});
						for (int k = 0; k < jars.length; k++) {
							if (vcBuffer.length() != 0) {
								vcBuffer.append(";");
							}
							vcBuffer.append(webInfLib.getPath() + File.separator + jars[k]);
						}
					}
				}
			}
		}
		if (!virtualDependentResources.isEmpty()) {
			for (Iterator iterator = virtualDependentResources.entrySet().iterator(); iterator.hasNext();) {
				Map.Entry entry = (Map.Entry)iterator.next();
				String rtPath = (String)entry.getKey();
				List locations = (List)entry.getValue();
				for (Iterator iterator2 = locations.iterator(); iterator2.hasNext();) {
					String location = (String)iterator2.next();
					if (rpBuffer.length() != 0) {
						rpBuffer.append(";");
					}
					if (rtPath.length() > 0) {
						rpBuffer.append(entry.getKey()).append("|").append(location);
					}
					else {
						rpBuffer.append(location);
					}
				}
			}			
		}

        String vcp = vcBuffer.toString();
        String oldVcp = loader.getVirtualClasspath();
        if (!vcp.equals(oldVcp)) {
            // save only if needed
            dirty = true;
            loader.setVirtualClasspath(vcp);
            context.getResources().setVirtualClasspath(vcp);
        }

		String resPaths = rpBuffer.toString();
		String oldResPaths = context.getResources().getExtraResourcePaths();
		if (!resPaths.equals(oldResPaths)) {
			dirty = true;
			context.getResources().setExtraResourcePaths(resPaths);
		}
		
		if (enableMetaInfResources) {
			context.findElement("JarScanner").setAttributeValue("scanAllDirectories", "true");
		}

        if (dirty) {
        	//TODO If writing to separate context XML files, save "dirty" status for later use
        }
    }

    private void addVirtualClassResource(IPath runtimePath, IPath workspacePath) {
        virtualClassClasspathElements.add(workspacePath.toOSString());
    }

    private void addVirtualJarResource(IPath runtimePath, IPath workspacePath) {
        virtualJarClasspathElements.add(workspacePath.toOSString());
    }
    
    private void addContentResource(IPath runtimePath, IPath workspacePath) {
    	String rtPath = runtimePath.toString(); 
    	List locations = (List)virtualDependentResources.get(rtPath);
    	if (locations == null) {
    		locations = new ArrayList();
    		virtualDependentResources.put(rtPath, locations);
    	}
    	locations.add(workspacePath.toOSString());
    }
    
    /**
     * Load a META-INF/context.xml file from project, if available
     * 
     * @param component web component containing the context.xml
     * @return context element containing the context.xml
     * @throws CoreException
     */
    protected Context getProjectContextXml(IVirtualComponent component)
            throws CoreException {

        // load or create module's context.xml document
        IVirtualFile contextFile = (IVirtualFile) component.getRootFolder()
                .findMember("META-INF/context.xml");

        Context contextElement = null;

        if (contextFile != null && contextFile.exists()) {

            Factory factory = new Factory();
            factory.setPackageName("org.eclipse.jst.server.tomcat.core.internal.xml.server40");

            InputStream fis = null;
            try {
                fis = contextFile.getUnderlyingFile().getContents();
                contextElement = (Context) factory.loadDocument(fis);
            } catch (Exception e) {
                Trace.trace(Trace.SEVERE, "Exception reading " + contextFile, e);
            } finally {
                try {
                    fis.close();
                } catch (IOException e) {
                    // ignore
                }
            }
        }
        return contextElement;
    }

    /**
     * Returns the given module from the config.
     * 
     * @param module a web module
     * @return a web module
     */
    protected Context findContext(IModule module) {
        if (module == null) {
            return null;
        }

        String source = module.getId();
        
        Context [] contexts = serverInstance.getContexts();
        for (int i = 0; i < contexts.length; i++) {
        	if (source.equals(contexts[i].getSource()))
        		return contexts[i];
		}
        return null;
    }
}
