protected void enhanceContext()

in tomcat8-maven-plugin/src/main/java/org/apache/tomcat/maven/plugin/tomcat8/run/RunMojo.java [308:672]


    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<>( 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();

            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<>();
                            List<WebResource> webResources = new ArrayList<>();
                            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<>();

                            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<>( jarPaths );
                        }

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

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

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

                            for ( String file : files )
                            {
                                paths.add( path + 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 );
        }

    }