Skip to content

Instantly share code, notes, and snippets.

@kpiwko
Created September 15, 2014 18:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kpiwko/626ed1c04ac28354137d to your computer and use it in GitHub Desktop.
Save kpiwko/626ed1c04ac28354137d to your computer and use it in GitHub Desktop.
Making ShrinkWrap MavenImporter more compatible with JRE/IDE
/*
* JBoss, Home of Professional Open Source
* Copyright 2012, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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 org.jboss.shrinkwrap.resolver.impl.maven.archive.packaging;
import java.io.File;
import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import org.codehaus.plexus.compiler.CompilerConfiguration;
import org.codehaus.plexus.compiler.CompilerException;
import org.codehaus.plexus.compiler.CompilerMessage;
import org.codehaus.plexus.compiler.CompilerResult;
import org.codehaus.plexus.compiler.javac.JavacCompiler;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.resolver.api.maven.MavenResolvedArtifact;
import org.jboss.shrinkwrap.resolver.api.maven.MavenWorkingSession;
import org.jboss.shrinkwrap.resolver.api.maven.ScopeType;
import org.jboss.shrinkwrap.resolver.api.maven.archive.importer.MavenImporterException;
import org.jboss.shrinkwrap.resolver.api.maven.strategy.AcceptScopesStrategy;
import org.jboss.shrinkwrap.resolver.api.maven.strategy.MavenResolutionStrategy;
import org.jboss.shrinkwrap.resolver.impl.maven.archive.plugins.CompilerPluginConfiguration;
import org.jboss.shrinkwrap.resolver.impl.maven.task.AddScopedDependenciesTask;
import org.jboss.shrinkwrap.resolver.impl.maven.util.Validate;
import org.jboss.shrinkwrap.resolver.spi.maven.archive.packaging.PackagingProcessor;
/**
* Packaging processor which is able to compile Java sources
*
* @author <a href="mailto:kpiwko@redhat.com">Karel Piwko</a>
*
* @param <ARCHIVETYPE> Type of the archive produced
*/
public abstract class AbstractCompilingProcessor<ARCHIVETYPE extends Archive<ARCHIVETYPE>> implements
PackagingProcessor<ARCHIVETYPE> {
private static final Logger log = Logger.getLogger(AbstractCompilingProcessor.class.getName());
// this pattern is used to check whether archive name was autogenerated
private static final Pattern UUID4_PATTERN = Pattern.compile("[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}\\.[a-z]+");
protected MavenWorkingSession session;
protected PackagingProcessor<ARCHIVETYPE> configure(MavenWorkingSession session) {
this.session = session;
return this;
}
protected AbstractCompilingProcessor<ARCHIVETYPE> compile(File inputDirectory, File outputDirectory, ScopeType... scopes) {
Validate.notNullAndNoNullValues(scopes, "Cannot compile sources, there were no scopes defined");
Validate.notNull(inputDirectory, "Directory with sources to be compiled must not be null");
Validate.notNull(outputDirectory, "Target directory for compiled sources must not be null");
JavacCompiler compiler = new JavacCompiler();
CompilerConfiguration configuration = getCompilerConfiguration();
if (log.isLoggable(Level.FINE)) {
log.log(Level.FINE, "Compiling sources from {0} directory into {1}",
new Object[] { inputDirectory, outputDirectory });
}
// in order to compile sources, we need to resolve dependencies first
// so we have a classpath available
new AddScopedDependenciesTask(ScopeType.values()).execute(session);
final MavenResolutionStrategy scopeStrategy = new AcceptScopesStrategy(scopes);
final Collection<MavenResolvedArtifact> artifactResults = session.resolveDependencies(scopeStrategy);
for (MavenResolvedArtifact artifact : artifactResults) {
String classpathEntry = artifact.asFile().getAbsolutePath();
configuration.addClasspathEntry(classpathEntry);
if (log.isLoggable(Level.FINER)) {
log.log(Level.FINER, "Adding {0} to compilation classpath", classpathEntry);
}
}
configuration.addSourceLocation(inputDirectory.getPath());
configuration.setOutputLocation(outputDirectory.getPath());
try {
CompilerResult result = compiler.performCompile(configuration);
if (!result.isSuccess()) {
// try to fork compilation process if it wasn't set to fork already
if(!configuration.isFork()) {
log.log(Level.WARNING, "MavenImporter was not able to identify javac compiler, probably JAVA_HOME points to JRE instead of JDK. MavenImporter will try to fork and use javac from $PATH");
configuration.setFork(true);
CompilerResult result2 = compiler.performCompile(configuration);
if(!result2.isSuccess()) {
log.log(Level.WARNING, "Unable to compile project with neither forked nor embedded compiler.");
// throw original exception
throw constructCompilationException(result, inputDirectory);
}
}
else {
throw constructCompilationException(result, inputDirectory);
}
}
} catch (CompilerException e) {
log.log(Level.SEVERE, "Compilation failed with {0}", e.getMessage());
throw new MavenImporterException("Unable to compile source at " + inputDirectory.getPath() + " due to: ", e);
}
return this;
}
private CompilerConfiguration getCompilerConfiguration() {
CompilerPluginConfiguration pluginConfiguration = new CompilerPluginConfiguration(session.getParsedPomFile());
return pluginConfiguration.asCompilerConfiguration();
}
protected static boolean hasGeneratedName(Archive<?> archive) {
String archiveName = archive.getName();
return archiveName != null && UUID4_PATTERN.matcher(archiveName.toLowerCase()).matches();
}
private static MavenImporterException constructCompilationException(CompilerResult result, File sourceDirectory) {
StringBuilder sb = new StringBuilder("Unable to compile sources at ");
sb.append(sourceDirectory.getPath());
sb.append(" due to following reason(s): ");
String delimiter = "";
for (CompilerMessage m : result.getCompilerMessages()) {
sb.append(delimiter).append(m.toString());
delimiter = ", ";
}
log.log(Level.SEVERE, sb.toString());
return new MavenImporterException(sb.toString());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment