// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.JarFile;
import java.util.zip.ZipFile;

import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.resource.JarResource;
import org.eclipse.jetty.util.resource.Resource;

/**
 * The Webapp Verifier is a component that can be configured to run and arbitrary number of {@link Rule}s that analyze
 * the contents of a war file and report rule violations.
 */
public class WebappVerifier implements ViolationListener
{
    /**
     * <p>
     * Represents the source webappURI.
     * </p>
     * <p>
     * Can be http, file, jar, etc ...
     * </p>
     * <p>
     * Verification does not occur directly against this URI.
     * </p>
     */
    private URI _webappURI;

    /**
     * Represents the local webapp file directory, often times points to the working (unpacked) webapp directory.
     * 
     * NOTE: if _webappURI is a "file://" access URI, and points to a directory, then the _webappDir will point to the
     * the same place, otherwise it will point to the webapp directory.
     */
    private File _webappDir;
    private File _workdir;
    private List<Rule> _rules;
    private Map<String, List<Violation>> _violations;

    /**
     * Instantiate a WebappVerifier, against the specific webappURI, using the default workdir.
     * 
     * @param webappURI
     *            the webappURI to verify
     */
    public WebappVerifier(URI webappURI)
    {
        this._webappURI = webappURI;
        this._workdir = new File(System.getProperty("java.io.tmpdir"),"jetty-waver");
        this._rules = new ArrayList<Rule>();
        this._violations = new HashMap<String, List<Violation>>();
    }

    public void addRule(Rule rule)
    {
        _rules.add(rule);
        try
        {
            rule.setViolationListener(this);
            rule.initialize();
        }
        catch (Throwable t)
        {
            // Capture any errors out of initialize or setViolationListener() that might occur.
            String msg = String.format("Unable to add rule [%s]: %s",rule.getName(),t.getMessage());
            reportException(Rule.ROOT_PATH,msg,rule,t);
        }
    }

    private String cleanFilename(URI uri)
    {
        // Need a filename to store this download to.
        String destname = uri.getPath();
        int idx = destname.lastIndexOf('/');
        if (idx > 0)
        {
            destname = destname.substring(idx);
        }
        destname = destname.trim().toLowerCase();

        if (destname.length() <= 0)
        {
            // whoops, there's nothing left.
            // could be caused by urls that point to paths.
            destname = new SimpleDateFormat("yyyy-MM-dd_hh-mm-ss").format(new Date());
        }

        // Neuter illegal characters
        char cleaned[] = new char[destname.length()];
        for (int i = 0; i < destname.length(); i++)
        {
            char c = destname.charAt(i);
            if (c == '|' || c == '/' || c == '\\' || c == '*' || c == '?' || c == ':' || c == '#')
            {
                cleaned[i] = '_';
            }
            else
            {
                cleaned[i] = c;
            }
        }

        destname = new String(cleaned);

        if (!destname.endsWith(".war"))
        {
            destname += ".war";
        }

        return destname;
    }

    private File download(URI uri) throws MalformedURLException, IOException
    {
        // Establish destfile
        File destfile = new File(_workdir,cleanFilename(uri));

        InputStream in = null;
        FileOutputStream out = null;
        try
        {
            in = uri.toURL().openStream();
            out = new FileOutputStream(destfile);
            IO.copy(in,out);
        }
        finally
        {
            IO.close(in);
        }
        return destfile;
    }

    private File establishLocalWebappDir() throws URISyntaxException, IOException
    {
        if ("file".equals(_webappURI.getScheme()))
        {
            File path = new File(_webappURI);
            if (path.isDirectory())
            {
                return path;
            }
            return unpack(path);
        }

        File downloadedFile = download(_webappURI);
        return unpack(downloadedFile);
    }

    public List<Rule> getRules()
    {
        return _rules;
    }

    public Collection<Violation> getViolations()
    {
        // TODO: Icky!  I need a better way of getting the list of raw
        // violations, complete, without path mapping in place.
        // Yet, I need path mapping as well, right?
        List<Violation> violations = new ArrayList<Violation>();
        for (List<Violation> pathviol : _violations.values())
        {
            violations.addAll(pathviol);
        }
        return violations;
    }

    public File getWebappDir()
    {
        return _webappDir;
    }

    private String getWebappRelativePath(File dir)
    {
        return _webappDir.toURI().relativize(dir.toURI()).toASCIIString();
    }

    public File getWorkDir()
    {
        return _workdir;
    }

    /**
     * Tests a filesystem path for webapp expected files, like "WEB-INF/web.xml"
     */
    private boolean isValidWebapp(File path)
    {
        File webXml = new File(path,"WEB-INF" + File.separator + "web.xml");
        if (!webXml.exists())
        {
            reportViolation(Severity.ERROR,Rule.ROOT_PATH,"Missing WEB-INF/web.xml");
            return false;
        }

        if (!webXml.isFile())
        {
            reportViolation(Severity.ERROR,Rule.ROOT_PATH,"The WEB-INF/web.xml is not a File");
            return false;
        }

        return true;
    }

    private void reportException(String path, String detail, Rule rule, Throwable t)
    {
        Violation viol = new Violation(Severity.ERROR,path,detail,t);
        viol.setVerifierInfo(rule);
        reportViolation(viol);
    }

    public void reportViolation(Severity error, String path, String detail)
    {
        reportViolation(new Violation(error,path,detail));
    }

    public void reportViolation(Violation violation)
    {
        List<Violation> pathviol = _violations.get(violation.getPath());
        if (pathviol == null)
        {
            pathviol = new ArrayList<Violation>();
        }
        pathviol.add(violation);
        _violations.put(violation.getPath(),pathviol);
    }

    public void setRules(Collection<Rule> rules)
    {
        this._rules.clear();
        // Add each rule separately, to establish initialization & listeners
        for (Rule verifier : rules)
        {
            addRule(verifier);
        }
    }

    public void setWorkDir(File workDir)
    {
        this._workdir = workDir;
    }

    private File unpack(File path) throws URISyntaxException, IOException
    {
        String destname = path.getName().substring(0,path.getName().length() - 4);
        File destDir = new File(_workdir,destname);
        URI warURI = new URI("jar",path.toURI() + "!/",null);
        JarResource warResource = (JarResource)Resource.newResource(warURI);
        // Extract the WAR (if needed)
        warResource.copyTo(destDir);
        return destDir;
    }

    public void visitAll()
    {
        try
        {
            _webappDir = establishLocalWebappDir();

            // Issue start.
            for (Rule rule : _rules)
            {
                rule.visitWebappStart(Rule.ROOT_PATH,_webappDir);
            }

            if (isValidWebapp(_webappDir))
            {
                // Iterate through content
                visitContents();
                // Iterate through WEB-INF/classes
                visitWebInfClasses();
                // Iterate through WEB-INF/lib
                visitWebInfLib();
            }

            // Issue end.
            for (Rule rule : _rules)
            {
                rule.visitWebappEnd(Rule.ROOT_PATH,_webappDir);
            }
        }
        catch (IOException e)
        {
            reportViolation(new Violation(Severity.ERROR,Rule.ROOT_PATH,e.getMessage(),e));
        }
        catch (URISyntaxException e)
        {
            reportViolation(new Violation(Severity.ERROR,Rule.ROOT_PATH,e.getMessage(),e));
        }
    }

    private void visitWebInfClasses()
    {
        File classesDir = new File(_webappDir,"WEB-INF" + File.separator + "classes");
        if (!classesDir.exists())
        {
            // skip this path.
            return;
        }

        String classesPath = getWebappRelativePath(classesDir);

        if (!classesDir.isDirectory())
        {
            reportViolation(Severity.ERROR,classesPath,"WEB-INF/classes is not a Directory?");
            return;
        }

        // Issue start.
        for (Rule rule : _rules)
        {
            rule.visitWebInfClassesStart(classesPath,classesDir);
        }

        visitClassesDir(classesDir,classesDir);

        // Issue end.
        for (Rule rule : _rules)
        {
            rule.visitWebInfClassesEnd(classesPath,classesDir);
        }
    }

    private void visitClassesDir(File classesRoot, File classesDir)
    {
        File files[] = classesDir.listFiles();
        for (File file : files)
        {
            if (file.isFile())
            {
                if (file.getName().endsWith(".class"))
                {
                    visitClass(classesRoot,file);
                }
                else
                {
                    visitClassResource(classesRoot,file);
                }
            }
            else if (file.isDirectory())
            {
                // recurse
                visitClassesDir(classesRoot,file);
            }
        }
    }

    private void visitClassResource(File classesRoot, File file)
    {
        String path = getWebappRelativePath(file);
        String resourcePath = classesRoot.toURI().relativize(file.toURI()).toASCIIString();
        for (Rule rule : _rules)
        {
            rule.visitWebInfClassResource(path,resourcePath,file);
        }
    }

    private void visitClass(File classesRoot, File file)
    {
        String path = getWebappRelativePath(file);
        String className = classesRoot.toURI().relativize(file.toURI()).toASCIIString();
        className = className.replace("/",".");
        if (className.endsWith(".class"))
        {
            className = className.substring(0,className.length() - 6);
        }
        for (Rule rule : _rules)
        {
            rule.visitWebInfClass(path,className,file);
        }
    }

    private void visitWebInfLib()
    {
        File libDir = new File(_webappDir,"WEB-INF" + File.separator + "lib");
        if (!libDir.exists())
        {
            // skip this path.
            return;
        }

        String libPath = getWebappRelativePath(libDir);

        if (!libDir.isDirectory())
        {
            reportViolation(Severity.ERROR,libPath,"WEB-INF/lib is not a Directory?");
            return;
        }

        // Issue start.
        for (Rule rule : _rules)
        {
            rule.visitWebInfLibStart(libPath,libDir);
        }

        // Iterator through contents of WEB-INF/lib
        File archives[] = libDir.listFiles();
        for (File archive : archives)
        {
            if (!archive.isFile())
            {
                reportViolation(Severity.WARNING,Rule.ROOT_PATH,"Found non-file in WEB-INF/lib.  Remove it, "
                        + "as it cannot be accessed by the Servlet container or the Webapp: " + archive);
                continue;
            }

            if (archive.getName().toLowerCase().endsWith(".jar"))
            {
                visitWebInfLibJar(libPath,archive);
                continue;
            }

            if (archive.getName().toLowerCase().endsWith(".zip"))
            {
                visitWebInfLibZip(libPath,archive);
                continue;
            }

            reportViolation(Severity.WARNING,Rule.ROOT_PATH,"Found non-archive in WEB-INF/lib.  Remove it, "
                    + "as it cannot be accessed by the Servlet container or the Webapp: " + archive);
        }

        // Issue end.
        for (Rule rule : _rules)
        {
            rule.visitWebInfLibEnd(libPath,libDir);
        }
    }

    private void visitWebInfLibJar(String libPath, File archive)
    {
        String jarPath = libPath + archive.getName();

        // Issue visit on Jar
        for (Rule rule : _rules)
        {
            JarFile jar = null;
            try
            {
                jar = new JarFile(archive);
                rule.visitWebInfLibJar(jarPath,archive,jar);
            }
            catch (Throwable t)
            {
                reportViolation(new Violation(Severity.ERROR,jarPath,t.getMessage(),t));
            }
            finally
            {
                if (jar != null)
                {
                    try
                    {
                        jar.close();
                    }
                    catch (IOException ignore)
                    {
                        /* ignore */
                    }
                }
            }
        }
    }

    private void visitWebInfLibZip(String libPath, File archive)
    {
        String zipPath = libPath + archive.getName();

        // Issue visit on Zip
        for (Rule rule : _rules)
        {
            ZipFile zip = null;
            try
            {
                zip = new ZipFile(archive);
                rule.visitWebInfLibZip(zipPath,archive,zip);
            }
            catch (Throwable t)
            {
                reportViolation(new Violation(Severity.ERROR,zipPath,t.getMessage(),t));
            }
            finally
            {
                if (zip != null)
                {
                    try
                    {
                        zip.close();
                    }
                    catch (IOException ignore)
                    {
                        /* ignore */
                    }
                }
            }
        }
    }

    private void visitContents()
    {
        visitDirectoryRecursively(_webappDir);
    }

    private void visitDirectoryRecursively(File dir)
    {
        String path = getWebappRelativePath(dir);

        // Start Dir
        for (Rule rule : this._rules)
        {
            rule.visitDirectoryStart(path,dir);
        }

        File entries[] = dir.listFiles();

        // Individual Files
        for (File file : entries)
        {
            if (file.isFile())
            {
                String filepath = path + file.getName();
                for (Rule rule : this._rules)
                {
                    rule.visitFile(filepath,dir,file);
                }
            }
        }

        // Sub dirs
        for (File file : entries)
        {
            if (file.isDirectory())
            {
                visitDirectoryRecursively(file);
            }
        }

        // End Dir
        for (Rule rule : this._rules)
        {
            rule.visitDirectoryEnd(path,dir);
        }
    }

}
