All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.code.play2.plugin.AbstractPlay2EnhanceMojo Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2013-2020 Grzegorz Slowikowski (gslowikowski at gmail dot com)
 *
 * Licensed 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.
 */

package com.google.code.play2.plugin;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;

import com.google.code.sbt.compiler.api.AnalysisProcessor;
import com.google.code.sbt.compiler.api.Compilers;

public abstract class AbstractPlay2EnhanceMojo
    extends AbstractPlay2Mojo
{

    /**
     * Forced SBT version.
*
* Used to automatically select one of the "well known" SBT compilation analysis processors (if no SBT compiler * added explicitly as plugin's dependency). *
* There are two cases possible: *
    *
  • * If {@link #sbtVersion} is specified, {@link AnalysisProcessor} implementation compatible with that SBT version * is selected. *
  • *
  • * If {@link #sbtVersion} is not specified, {@link #playVersion} parameter value is used to indirectly select * {@link AnalysisProcessor} implementation compatible with that Play! Framework version. *
  • *
* * @since 1.0.0 */ @Parameter( property = "sbt.version" ) protected String sbtVersion; /** * List of artifacts this plugin depends on. */ @Parameter( property = "plugin.artifacts", required = true, readonly = true ) private List pluginArtifacts; private static final String SBT_COMPILER_PLUGIN_GROUP_ID = "com.arpnetworking.code.sbt-compiler-maven-plugin"; private static final String SBT_COMPILER_PLUGIN_API_ARTIFACT_ID = "sbt-compiler-api"; /** * Map of SBT compiler implementations. For now only zero or one allowed. */ @Component( role = AnalysisProcessor.class ) private Map analysisProcessors; // SBT compiler resolution for Analysis cache processing // Cached classloaders private static final ConcurrentHashMap SBT_COMPILER_CACHED_CLASS_LOADERS = new ConcurrentHashMap( 2 ); private static ClassLoader getSbtCompilerCachedClassLoader( String compilerId ) { return SBT_COMPILER_CACHED_CLASS_LOADERS.get( compilerId ); } private static void setSbtCompilerCachedClassLoader( String compilerId, ClassLoader classLoader ) { SBT_COMPILER_CACHED_CLASS_LOADERS.put( compilerId, classLoader ); } protected AnalysisProcessor getSbtAnalysisProcessor() throws MojoExecutionException { AnalysisProcessor sbtAnalysisProcessor = null; if ( !analysisProcessors.isEmpty() ) { sbtAnalysisProcessor = getDeclaredSbtAnalysisProcessor(); } else { sbtAnalysisProcessor = getWellKnownSbtAnalysisProcessor(); } return sbtAnalysisProcessor; } private AnalysisProcessor getDeclaredSbtAnalysisProcessor() throws MojoExecutionException { if ( analysisProcessors.size() > 1 ) { throw new MojoExecutionException( "Too many compilers defined. A maximum of one allowed." ); } Map.Entry compilerEntry = analysisProcessors.entrySet().iterator().next(); String compilerId = compilerEntry.getKey(); AnalysisProcessor sbtAnalysisProcessor = compilerEntry.getValue(); getLog().debug( String.format( "Using declared compiler \"%s\".", compilerId ) ); return sbtAnalysisProcessor; } private AnalysisProcessor getWellKnownSbtAnalysisProcessor() throws MojoExecutionException { try { String compilerId = Compilers.getDefaultCompilerId( sbtVersion, playVersion ); ClassLoader compilerClassLoader = getSbtCompilerCachedClassLoader( compilerId ); if ( compilerClassLoader == null ) { getLog().debug( String.format( "Cached classloader for compiler \"%s\" not available.", compilerId ) ); } else { if ( compilerClassLoader.getParent() == Thread.currentThread().getContextClassLoader() ) { getLog().debug( String.format( "Using cached classloader for compiler \"%s\".", compilerId ) ); } else { getLog().debug( String.format( "Invalidated cached classloader for compiler \"%s\". Parent classloader changed from %d to %d.", compilerId, Integer.valueOf( compilerClassLoader.getParent().hashCode() ), Integer.valueOf( Thread.currentThread().getContextClassLoader().hashCode() ) ) ); compilerClassLoader = null; } } if ( compilerClassLoader == null ) { Set compilerArtifacts = getResolvedArtifact( SBT_COMPILER_PLUGIN_GROUP_ID, "sbt-compiler-" + compilerId, getSbtCompilerPluginVersion() ); List classPathFiles = new ArrayList( compilerArtifacts.size()/*compilerDependencies.size() + 2*/ ); for ( Artifact dependencyArtifact : compilerArtifacts/*compilerDependencies*/ ) { classPathFiles.add( dependencyArtifact.getFile() ); } List classPathUrls = new ArrayList( classPathFiles.size() ); for ( File classPathFile : classPathFiles ) { classPathUrls.add( new URL( classPathFile.toURI().toASCIIString() ) ); } compilerClassLoader = new URLClassLoader( classPathUrls.toArray( new URL[classPathUrls.size()] ), Thread.currentThread().getContextClassLoader() ); getLog().debug( String.format( "Setting cached classloader for compiler \"%s\" with parent classloader %d", compilerId, Integer.valueOf( compilerClassLoader.getParent().hashCode() ) ) ); setSbtCompilerCachedClassLoader( compilerId, compilerClassLoader ); } ServiceLoader analysisProcessorServiceLoader = ServiceLoader.load( AnalysisProcessor.class, compilerClassLoader ); // get first (there should be exactly one) AnalysisProcessor sbtAnalysisProcessor = analysisProcessorServiceLoader.iterator().next(); getLog().debug( String.format( "Using autodetected compiler \"%s\".", compilerId ) ); return sbtAnalysisProcessor; } catch ( ArtifactResolutionException e ) { throw new MojoExecutionException( "Compiler autodetection failed", e ); } catch ( MalformedURLException e ) { throw new MojoExecutionException( "Compiler autodetection failed", e ); } } private String getSbtCompilerPluginVersion() throws MojoExecutionException { return getPluginArtifact( SBT_COMPILER_PLUGIN_GROUP_ID, SBT_COMPILER_PLUGIN_API_ARTIFACT_ID, "jar" ).getBaseVersion(); } private/*protected*/ Artifact getPluginArtifact( String groupId, String artifactId, String type ) throws MojoExecutionException { Artifact result = null; for ( Artifact artifact : pluginArtifacts ) { if ( artifact.getGroupId().equals( groupId ) && artifact.getArtifactId().equals( artifactId ) && type.equals( artifact.getType() ) ) { result = artifact; break; } } if ( result == null ) { throw new MojoExecutionException( String.format( "Unable to locate '%s:%s' in the list of plugin artifacts", groupId, artifactId ) ); } return result; } private File defaultAnalysisCacheFile( MavenProject p ) { File classesDirectory = new File( p.getBuild().getOutputDirectory() ); return new File( Compilers.getCacheDirectory( classesDirectory ), "compile" ); } /** * Returns SBT incremental main compilation analysis cache file location for a project. * * @return analysis cache file location */ protected File getAnalysisCacheFile() { return defaultAnalysisCacheFile( project ); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy