/**********************************************************************
 * Copyright (c) 2007, 2014 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 * 
 * 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<String> earCommonResources = new ArrayList<String>();

    /**
     * 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<String> virtualClassClasspathElements = new LinkedHashSet<String>();
    protected Set<String> virtualJarClasspathElements = new LinkedHashSet<String>();

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

    /**
     * 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,
                		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));
        }

		dirty = includeProjectContextXml(component, context);
		dirty = updateDocBaseAndPath(component, context);

        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(); // Filled with classes entries first, then jar entries added
		StringBuffer vcJarBuffer = new StringBuffer(); // Filled with jar enteries only
		// 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);
			}
        }
        for (Iterator iterator = virtualJarClasspathElements.iterator();
        		iterator.hasNext();) {
			vcJarBuffer.append(iterator.next());
        	if (iterator.hasNext()) {
				vcJarBuffer.append(";");
        	}
        }
        virtualClassClasspathElements.clear();
        virtualJarClasspathElements.clear();

		Set<String> rtPathsProcessed = new HashSet<String>();
		Set<String> locationsIncluded = new HashSet<String>();
		String docBase = context.getDocBase();
		locationsIncluded.add(docBase);
		Map<String, String> retryLocations = new HashMap<String, String>();
		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);
								// If a "WEB-INF/classes" exists and is a directory, add to virtual classpath
								File webInfClasses = resLoc.append("WEB-INF/classes").toFile();
								if (webInfClasses.exists() && webInfClasses.isDirectory()) {
									if (vcBuffer.length() != 0) {
										vcBuffer.append(";");
									}
									vcBuffer.append(webInfClasses.getPath());
								}
								// Check if this extra content location contains jars
								File webInfLib = resLoc.append("WEB-INF/lib").toFile();
								// If a "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 (vcJarBuffer.length() != 0) {
											vcJarBuffer.append(";");
										}
										vcJarBuffer.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;
									File webInfClasses = null;
									if ("/WEB-INF".equals(rtPath)) {
										webInfLib = resLoc.append("lib").toFile();
										webInfClasses = resLoc.append("classes").toFile();
									}
									else if ("/WEB-INF/lib".equals(rtPath)) {
										webInfLib = resLoc.toFile();
									}
									else if ("/WEB-INF/classes".equals(rtPath)) {
										webInfClasses = resLoc.toFile();
									}
									// If a "WEB-INF/classes" exists and is a directory, add to virtual classpath
									if (webInfClasses != null && webInfClasses.exists() && webInfClasses.isDirectory()) {
										if (vcBuffer.length() != 0) {
											vcBuffer.append(";");
										}
										vcBuffer.append(webInfClasses.getPath());
									}
									// 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 (vcJarBuffer.length() != 0) {
												vcJarBuffer.append(";");
											}
											vcJarBuffer.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;
					File webInfClasses = null;
					if ("/WEB-INF".equals(rtPath)) {
						webInfLib = new File(location, "lib");
						webInfClasses = new File(location, "classes");
					}
					else if ("/WEB-INF/lib".equals(rtPath)) {
						webInfLib = new File(location);
					}
					else if ("/WEB-INF/classes".equals(rtPath)) {
						webInfClasses = new File(location);
					}
					// If a "WEB-INF/classes" exists and is a directory, add to virtual classpath
					if (webInfClasses != null && webInfClasses.exists() && webInfClasses.isDirectory()) {
						if (vcBuffer.length() != 0) {
							vcBuffer.append(";");
						}
						vcBuffer.append(webInfClasses.getPath());
					}
					// If a "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 (vcJarBuffer.length() != 0) {
								vcJarBuffer.append(";");
							}
							vcJarBuffer.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);
					}
				}
			}			
		}
		virtualDependentResources.clear();

		// Combine the classes and jar virtual classpaths
		if (vcJarBuffer.length() > 0) {
			if (vcBuffer.length() > 0) {
				vcBuffer.append(';');
			}
			vcBuffer.append(vcJarBuffer);
		}

        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<String> locations = virtualDependentResources.get(rtPath);
    	if (locations == null) {
    		locations = new ArrayList<String>();
    		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;
    }

	String getContextName(Context context) {
		String contextName = context.getPath();

		// 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";
		}
		return contextName;
	}

	boolean includeProjectContextXml(IVirtualComponent component, Context context) throws CoreException {
		boolean dirty = false;
		// 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;
					}
				}
			}
		}
		return dirty;
	}

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

		String contextName = getContextName(context);
		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);
		}
		return dirty;
	}
}
