package org.apache.tomcat.maven.plugin.tomcat8.run;
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import org.apache.catalina.Context;
import org.apache.catalina.WebResource;
import org.apache.catalina.WebResourceRoot;
import org.apache.catalina.WebResourceSet;
import org.apache.catalina.loader.WebappLoader;
import org.apache.catalina.webresources.EmptyResource;
import org.apache.catalina.webresources.FileResource;
import org.apache.catalina.webresources.FileResourceSet;
import org.apache.catalina.webresources.JarResource;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Execute;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.shared.filtering.MavenFileFilterRequest;
import org.apache.maven.shared.filtering.MavenFilteringException;
import org.apache.tomcat.maven.common.run.ClassLoaderEntriesCalculator;
import org.apache.tomcat.maven.common.run.ClassLoaderEntriesCalculatorRequest;
import org.apache.tomcat.maven.common.run.ClassLoaderEntriesCalculatorResult;
import org.apache.tomcat.maven.common.run.TomcatRunException;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
import org.codehaus.plexus.util.xml.Xpp3DomWriter;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * Runs the current project as a dynamic web application using an embedded Tomcat server.
 *
 * @author Olivier Lamy
 * @since 2.0
 */
@Mojo( name = "run", requiresDependencyResolution = ResolutionScope.TEST, threadSafe = true )
@Execute( phase = LifecyclePhase.PROCESS_CLASSES )
public class RunMojo
    extends AbstractRunMojo
{
    // ----------------------------------------------------------------------
    // Mojo Parameters
    // ----------------------------------------------------------------------


    /**
     * The set of dependencies for the web application being run.
     */
    @Parameter( defaultValue = "${project.artifacts}", required = true, readonly = true )
    private Set<Artifact> dependencies;

    /**
     * The web resources directory for the web application being run.
     */
    @Parameter( defaultValue = "${basedir}/src/main/webapp", property = "tomcat.warSourceDirectory" )
    private File warSourceDirectory;


    /**
     * Set the "follow standard delegation model" flag used to configure our ClassLoader.
     *
     * @see http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/loader/WebappLoader.html#setDelegate(boolean)
     * @since 1.0
     */
    @Parameter( property = "tomcat.delegate", defaultValue = "true" )
    private boolean delegate = true;

    /**
     * @since 2.0
     */
    @Component
    private ClassLoaderEntriesCalculator classLoaderEntriesCalculator;

    /**
     * will add /WEB-INF/lib/*.jar and /WEB-INF/classes from war dependencies in the webappclassloader
     *
     * @since 2.0
     */
    @Parameter( property = "maven.tomcat.addWarDependenciesInClassloader", defaultValue = "true" )
    private boolean addWarDependenciesInClassloader;

    /**
     * will use the test classpath rather than the compile one and will add test dependencies too
     *
     * @since 2.0
     */
    @Parameter( property = "maven.tomcat.useTestClasspath", defaultValue = "false" )
    private boolean useTestClasspath;

    /**
     * Additional optional directories to add to the embedded tomcat classpath.
     *
     * @since 2.0
     */
    @Parameter( alias = "additionalClassesDirs" )
    private List<String> additionalClasspathDirs;


    public final File getWarSourceDirectory()
    {
        return warSourceDirectory;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected File getDocBase()
        throws IOException
    {
        // https://issues.apache.org/jira/browse/MTOMCAT-239
        // when running a jar docBase doesn't exists so create a fake one
        if ( !warSourceDirectory.exists() )
        {
            // we create a temporary file in build.directory
            final File tempDocBase = createTempDirectory( new File( project.getBuild().getDirectory() ) );
            Runtime.getRuntime().addShutdownHook( new Thread()
            {
                @Override
                public void run()
                {
                    try
                    {
                        FileUtils.deleteDirectory( tempDocBase );
                    }
                    catch ( Exception e )
                    {
                        // we can consider as safe to ignore as it's located in build directory
                    }
                }
            } );
            return tempDocBase;
        }
        return warSourceDirectory;
    }

    private static File createTempDirectory( File baseTmpDirectory )
        throws IOException
    {
        final File temp = File.createTempFile( "temp", Long.toString( System.nanoTime() ), baseTmpDirectory );

        if ( !( temp.delete() ) )
        {
            throw new IOException( "Could not delete temp file: " + temp.getAbsolutePath() );
        }

        if ( !( temp.mkdir() ) )
        {
            throw new IOException( "Could not create temp directory: " + temp.getAbsolutePath() );
        }

        return temp;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected File getContextFile()
        throws MojoExecutionException
    {
        File temporaryContextFile = null;

        //----------------------------------------------------------------------------
        // context attributes backgroundProcessorDelay reloadable cannot be modified at runtime.
        // It looks only values from the file are used
        // so here we create a temporary file with values modified
        //----------------------------------------------------------------------------
        FileReader fr = null;
        FileWriter fw = null;
        StringWriter sw = new StringWriter();
        try
        {
            temporaryContextFile = File.createTempFile( "tomcat-maven-plugin", "temp-ctx-file" );
            temporaryContextFile.deleteOnExit();

            // format to modify/create <Context backgroundProcessorDelay="5" reloadable="false">
            if ( contextFile != null && contextFile.exists() )
            {
                MavenFileFilterRequest mavenFileFilterRequest = new MavenFileFilterRequest();
                mavenFileFilterRequest.setFrom( contextFile );
                mavenFileFilterRequest.setTo( temporaryContextFile );
                mavenFileFilterRequest.setMavenProject( project );
                mavenFileFilterRequest.setMavenSession( session );
                mavenFileFilterRequest.setFiltering( true );

                mavenFileFilter.copyFile( mavenFileFilterRequest );

                fr = new FileReader( temporaryContextFile );
                Xpp3Dom xpp3Dom = Xpp3DomBuilder.build( fr );
                xpp3Dom.setAttribute( "backgroundProcessorDelay", Integer.toString( backgroundProcessorDelay ) );
                xpp3Dom.setAttribute( "reloadable", Boolean.toString( isContextReloadable() ) );
                fw = new FileWriter( temporaryContextFile );
                Xpp3DomWriter.write( fw, xpp3Dom );
                Xpp3DomWriter.write( sw, xpp3Dom );
                getLog().debug( " generated context file " + sw.toString() );
            }
            else
            {
                if ( contextReloadable )
                {
                    // don't care about using a complicated xml api to create one xml line :-)
                    StringBuilder sb = new StringBuilder( "<Context " ).append( "backgroundProcessorDelay=\"" ).append(
                        Integer.toString( backgroundProcessorDelay ) ).append( "\"" ).append(
                        " reloadable=\"" + Boolean.toString( isContextReloadable() ) + "\"/>" );

                    getLog().debug( " generated context file " + sb.toString() );
                    fw = new FileWriter( temporaryContextFile );
                    fw.write( sb.toString() );
                }
                else
                {
                    // no user context file and contextReloadable false so no need about creating a hack one
                    return null;
                }
            }
        }
        catch ( IOException e )
        {
            getLog().error( "error creating fake context.xml : " + e.getMessage(), e );
            throw new MojoExecutionException( "error creating fake context.xml : " + e.getMessage(), e );
        }
        catch ( XmlPullParserException e )
        {
            getLog().error( "error creating fake context.xml : " + e.getMessage(), e );
            throw new MojoExecutionException( "error creating fake context.xml : " + e.getMessage(), e );
        }
        catch ( MavenFilteringException e )
        {
            getLog().error( "error filtering context.xml : " + e.getMessage(), e );
            throw new MojoExecutionException( "error filtering context.xml : " + e.getMessage(), e );
        }
        finally
        {
            IOUtil.close( fw );
            IOUtil.close( fr );
            IOUtil.close( sw );
        }

        return temporaryContextFile;
    }

    /**
     * {@inheritDoc}
     *
     * @throws MojoExecutionException
     */
    @Override
    protected WebappLoader createWebappLoader()
        throws IOException, MojoExecutionException
    {
        WebappLoader loader = super.createWebappLoader();

        if ( useSeparateTomcatClassLoader )
        {
            loader.setDelegate( delegate );
        }

        return loader;
    }

    @Override
    protected void enhanceContext( final Context context )
        throws MojoExecutionException
    {
        super.enhanceContext( context );

        try
        {
            ClassLoaderEntriesCalculatorRequest request = new ClassLoaderEntriesCalculatorRequest() //
                .setDependencies( dependencies ) //
                .setLog( getLog() ) //
                .setMavenProject( project ) //
                .setAddWarDependenciesInClassloader( addWarDependenciesInClassloader ) //
                .setUseTestClassPath( useTestClasspath );
            final ClassLoaderEntriesCalculatorResult classLoaderEntriesCalculatorResult =
                classLoaderEntriesCalculator.calculateClassPathEntries( request );
            final List<String> classLoaderEntries = classLoaderEntriesCalculatorResult.getClassPathEntries();
            final List<File> tmpDirectories = classLoaderEntriesCalculatorResult.getTmpDirectories();

            final List<String> jarPaths = extractJars( classLoaderEntries );

            List<URL> urls = new ArrayList<URL>( jarPaths.size() );

            for ( String jarPath : jarPaths )
            {
                try
                {
                    urls.add( new File( jarPath ).toURI().toURL() );
                }
                catch ( MalformedURLException e )
                {
                    throw new MojoExecutionException( e.getMessage(), e );
                }
            }

            getLog().debug( "classLoaderEntriesCalculator urls: " + urls );

            final URLClassLoader urlClassLoader = new URLClassLoader( urls.toArray( new URL[urls.size()] ) );

            final ClassRealm pluginRealm = getTomcatClassLoader();

            final WebResourceRoot previous = context.getResources();

            context.setResources(
                new MyDirContext( new File( project.getBuild().getOutputDirectory() ).getAbsolutePath(), //
                                  getPath(), //
                                  getLog() )
                {
                    @Override
                    public WebResource getClassLoaderResource( String path )
                    {

                        log.debug( "RunMojo#getClassLoaderResource: " + path );
                        URL url = urlClassLoader.getResource( StringUtils.removeStart( path, "/" ) );
                        // search in parent (plugin) classloader
                        if ( url == null )
                        {
                            url = pluginRealm.getResource( StringUtils.removeStart( path, "/" ) );
                        }

                        if ( url == null )
                        {
                            // try in reactors
                            List<WebResource> webResources = findResourcesInDirectories( path, //
                                                                                         classLoaderEntriesCalculatorResult.getBuildDirectories() );

                            // so we return the first one
                            if ( !webResources.isEmpty() )
                            {
                                return webResources.get( 0 );
                            }
                        }

                        if ( url == null )
                        {
                            return new EmptyResource( this, getPath() );
                        }

                        return urlToWebResource( url, path );
                    }

                    @Override
                    public WebResource getResource( String path )
                    {
                        log.debug( "RunMojo#getResource: " + path );
                        return super.getResource( path );
                    }

                    @Override
                    public WebResource[] getResources( String path )
                    {
                        log.debug( "RunMojo#getResources: " + path );
                        return super.getResources( path );
                    }

                    @Override
                    protected WebResource[] getResourcesInternal( String path, boolean useClassLoaderResources )
                    {
                        log.debug( "RunMojo#getResourcesInternal: " + path );
                        return super.getResourcesInternal( path, useClassLoaderResources );
                    }

                    @Override
                    public WebResource[] getClassLoaderResources( String path )
                    {
                        try
                        {
                            Enumeration<URL> enumeration =
                                urlClassLoader.findResources( StringUtils.removeStart( path, "/" ) );
                            List<URL> urlsFound = new ArrayList<URL>();
                            List<WebResource> webResources = new ArrayList<WebResource>();
                            while ( enumeration.hasMoreElements() )
                            {
                                URL url = enumeration.nextElement();
                                urlsFound.add( url );
                                webResources.add( urlToWebResource( url, path ) );
                            }
                            log.debug(
                                "RunMojo#getClassLoaderResources: " + path + " found : " + urlsFound.toString() );

                            webResources.addAll( findResourcesInDirectories( path,
                                                                             classLoaderEntriesCalculatorResult.getBuildDirectories() ) );

                            return webResources.toArray( new WebResource[webResources.size()] );

                        }
                        catch ( IOException e )
                        {
                            throw new RuntimeException( e.getMessage(), e );
                        }
                    }


                    private List<WebResource> findResourcesInDirectories( String path, List<String> directories )
                    {
                        try
                        {
                            List<WebResource> webResources = new ArrayList<WebResource>();

                            for ( String directory : directories )
                            {

                                File file = new File( directory, path );
                                if ( file.exists() )
                                {
                                    webResources.add( urlToWebResource( file.toURI().toURL(), path ) );
                                }

                            }

                            return webResources;
                        }
                        catch ( MalformedURLException e )
                        {
                            throw new RuntimeException( e.getMessage(), e );
                        }
                    }


                    private WebResource urlToWebResource( URL url, String path )
                    {
                        JarFile jarFile = null;

                        try
                        {
                            // url.getFile is
                            // file:/Users/olamy/mvn-repo/org/springframework/spring-web/4.0.0.RELEASE/spring-web-4.0.0.RELEASE.jar!/org/springframework/web/context/ContextLoaderListener.class

                            int idx = url.getFile().indexOf( '!' );

                            if ( idx >= 0 )
                            {
                                String filePath = StringUtils.removeStart( url.getFile().substring( 0, idx ), "file:" );

                                jarFile = new JarFile( filePath );

                                JarEntry jarEntry = jarFile.getJarEntry( StringUtils.removeStart( path, "/" ) );

                                return new JarResource( this, //
                                                        getPath(), //
                                                        filePath, //
                                                        url.getPath().substring( 0, idx ), //
                                                        jarEntry, //
                                                        "", //
                                                        null );
                            }
                            else
                            {
                                return new FileResource( this, webAppPath, new File( url.getFile() ), true );
                            }

                        }
                        catch ( IOException e )
                        {
                            throw new RuntimeException( e.getMessage(), e );
                        }
                        finally
                        {
                            IOUtils.closeQuietly( jarFile );
                        }
                    }


                } );

            Runtime.getRuntime().addShutdownHook( new Thread()
            {
                @Override
                public void run()
                {
                    for ( File tmpDir : tmpDirectories )
                    {
                        try
                        {
                            FileUtils.deleteDirectory( tmpDir );
                        }
                        catch ( IOException e )
                        {
                            // ignore
                        }
                    }
                }
            } );

            if ( classLoaderEntries != null )
            {
                WebResourceSet webResourceSet = new FileResourceSet()
                {
                    @Override
                    public WebResource getResource( String path )
                    {

                        if ( StringUtils.startsWithIgnoreCase( path, "/WEB-INF/LIB" ) )
                        {
                            File file = new File( StringUtils.removeStartIgnoreCase( path, "/WEB-INF/LIB" ) );
                            return new FileResource( context.getResources(), getPath(), file, true );
                        }
                        if ( StringUtils.equalsIgnoreCase( path, "/WEB-INF/classes" ) )
                        {
                            return new FileResource( context.getResources(), getPath(),
                                                     new File( project.getBuild().getOutputDirectory() ), true );
                        }

                        File file = new File( project.getBuild().getOutputDirectory(), path );
                        if ( file.exists() )
                        {
                            return new FileResource( context.getResources(), getPath(), file, true );
                        }

                        //if ( StringUtils.endsWith( path, ".class" ) )
                        {
                            // so we search the class file in the jars
                            for ( String jarPath : jarPaths )
                            {
                                File jar = new File( jarPath );
                                if ( !jar.exists() )
                                {
                                    continue;
                                }

                                try
                                {
                                    JarFile jarFile = new JarFile( jar );
                                    JarEntry jarEntry =
                                        (JarEntry) jarFile.getEntry( StringUtils.removeStart( path, "/" ) );
                                    if ( jarEntry != null )
                                    {
                                        return new JarResource( context.getResources(), //
                                                                getPath(),  //
                                                                jarFile.getName(), //
                                                                jar.toURI().toString(), //
                                                                jarEntry, //
                                                                path, //
                                                                jarFile.getManifest() );
                                    }
                                }
                                catch ( IOException e )
                                {
                                    getLog().debug( "skip error building jar file: " + e.getMessage(), e );
                                }

                            }
                        }

                        return new EmptyResource( null, path );
                    }

                    @Override
                    public String[] list( String path )
                    {
                        if ( StringUtils.startsWithIgnoreCase( path, "/WEB-INF/LIB" ) )
                        {
                            return jarPaths.toArray( new String[jarPaths.size()] );
                        }
                        if ( StringUtils.equalsIgnoreCase( path, "/WEB-INF/classes" ) )
                        {
                            return new String[]{ new File( project.getBuild().getOutputDirectory() ).getPath() };
                        }
                        return super.list( path );
                    }

                    @Override
                    public Set<String> listWebAppPaths( String path )
                    {

                        if ( StringUtils.equalsIgnoreCase( "/WEB-INF/lib/", path ) )
                        {
                            // adding outputDirectory as well?
                            return new HashSet<String>( jarPaths );
                        }

                        File filePath = new File( getWarSourceDirectory(), path );

                        if ( filePath.isDirectory() )
                        {
                            Set<String> paths = new HashSet<String>();

                            String[] files = filePath.list();
                            if ( files == null )
                            {
                                return paths;
                            }

                            for ( String file : files )
                            {
                                paths.add( file );
                            }

                            return paths;

                        }
                        else
                        {
                            return Collections.emptySet();
                        }
                    }

                    @Override
                    public boolean mkdir( String path )
                    {
                        return super.mkdir( path );
                    }

                    @Override
                    public boolean write( String path, InputStream is, boolean overwrite )
                    {
                        return super.write( path, is, overwrite );
                    }

                    @Override
                    protected void checkType( File file )
                    {
                        //super.checkType( file );
                    }


                };

                context.getResources().addJarResources( webResourceSet );
            }

        }
        catch ( TomcatRunException e )
        {
            throw new MojoExecutionException( e.getMessage(), e );
        }

    }


    /**
     * extract List of path which are files (removing directories from the initial list)
     *
     * @param classLoaderEntries
     * @return
     */
    private List<String> extractJars( List<String> classLoaderEntries )
        throws MojoExecutionException
    {

        List<String> jarPaths = new ArrayList<String>();

        try
        {
            for ( String classLoaderEntry : classLoaderEntries )
            {
                URI uri = new URI( classLoaderEntry );
                File file = new File( uri );
                if ( !file.isDirectory() )
                {
                    jarPaths.add( file.getAbsolutePath() );
                }
            }
        }
        catch ( URISyntaxException e )
        {
            throw new MojoExecutionException( e.getMessage(), e );
        }

        return jarPaths;

    }
}
