| /** |
| * 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 |
| * <p> |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * <p> |
| * 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.apache.winegrower.extension.build.maven; |
| |
| import static java.util.Optional.ofNullable; |
| import static java.util.stream.Collectors.toList; |
| import static org.apache.maven.plugins.annotations.ResolutionScope.RUNTIME_PLUS_SYSTEM; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.lang.reflect.InvocationTargetException; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.net.URLClassLoader; |
| import java.util.Collection; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.concurrent.CountDownLatch; |
| import java.util.function.Predicate; |
| import java.util.stream.Stream; |
| |
| import org.apache.maven.artifact.Artifact; |
| import org.apache.maven.plugin.AbstractMojo; |
| import org.apache.maven.plugins.annotations.Mojo; |
| import org.apache.maven.plugins.annotations.Parameter; |
| import org.apache.maven.project.MavenProject; |
| import org.apache.winegrower.Ripener; |
| import org.apache.winegrower.extension.build.common.Run; |
| import org.apache.winegrower.scanner.manifest.ManifestContributor; |
| |
| @Mojo(name = "pour", requiresDependencyResolution = RUNTIME_PLUS_SYSTEM) |
| public class PourMojo extends AbstractMojo { |
| |
| @Parameter(property = "winegrower.workDir", defaultValue = "${project.build.directory}/winegrower/workdir") |
| private File workDir; |
| |
| @Parameter(property = "winegrower.jarFilter") |
| private String jarFilter; |
| |
| @Parameter(property = "winegrower.scanningIncludes") |
| private Collection<String> scanningIncludes; |
| |
| @Parameter(property = "winegrower.scanningExcludes") |
| private Collection<String> scanningExcludes; |
| |
| @Parameter(property = "winegrower.manifestContributors") |
| private Collection<String> manifestContributors; |
| |
| @Parameter(property = "winegrower.dependencyScopes", defaultValue = "provided,compile,system,runtime") |
| private Collection<String> dependencyScopes; |
| |
| @Parameter(property = "winegrower.prioritizedBundles") |
| private List<String> prioritizedBundles; |
| |
| @Parameter(property = "winegrower.systemVariables") |
| private Map<String, String> systemVariables; |
| |
| @Parameter(property = "winegrower.waitOnSystemIn", defaultValue = "true") |
| private boolean waitOnSystemIn; // if you use the shell this breaks it if set to true |
| |
| @Parameter(defaultValue = "${project}", readonly = true, required = true) |
| private MavenProject project; |
| |
| @Override |
| public void execute() { |
| final Thread thread = Thread.currentThread(); |
| final ClassLoader loader = thread.getContextClassLoader(); |
| final ClassLoader appLoader = createClassLoader(loader); |
| thread.setContextClassLoader(appLoader); |
| try { |
| new Run(createConfiguration(), systemVariables) { |
| |
| @Override |
| protected void waitForExit() { |
| if (waitOnSystemIn) { |
| super.waitForExit(); |
| } else { // just block |
| try { |
| new CountDownLatch(1).await(); |
| } catch (final InterruptedException e) { |
| Thread.currentThread().interrupt(); |
| } |
| } |
| } |
| }.run(); |
| } finally { |
| if (appLoader != loader) { |
| try { |
| URLClassLoader.class.cast(appLoader).close(); |
| } catch (final IOException e) { |
| getLog().warn(e.getMessage(), e); |
| } |
| } |
| thread.setContextClassLoader(loader); |
| } |
| } |
| |
| private ClassLoader createClassLoader(final ClassLoader parent) { |
| final List<URL> urls = Stream.concat( |
| project.getArtifacts().stream() |
| .filter(a -> !((dependencyScopes == null |
| && !(Artifact.SCOPE_COMPILE.equals(a.getScope()) || Artifact.SCOPE_RUNTIME.equals(a.getScope()))) |
| || (dependencyScopes != null && !dependencyScopes.contains(a.getScope())))) |
| .map(Artifact::getFile), |
| Stream.of(project.getBuild().getOutputDirectory()).map(File::new).filter(File::exists)).map(file -> { |
| try { |
| return file.toURI().toURL(); |
| } catch (final MalformedURLException e) { |
| throw new IllegalArgumentException(e); |
| } |
| }).collect(toList()); |
| return urls.isEmpty() ? parent : new URLClassLoader(urls.toArray(new URL[0]), parent) { |
| |
| @Override |
| public boolean equals(final Object obj) { |
| return super.equals(obj) || parent.equals(obj); |
| } |
| }; |
| } |
| |
| private Ripener.Configuration createConfiguration() { |
| final Ripener.Configuration configuration = new Ripener.Configuration(); |
| ofNullable(workDir).ifPresent(configuration::setWorkDir); |
| ofNullable(prioritizedBundles).filter(it -> !it.isEmpty()).ifPresent(configuration::setPrioritizedBundles); |
| ofNullable(scanningIncludes).filter(it -> !it.isEmpty()).ifPresent(configuration::setScanningIncludes); |
| ofNullable(scanningExcludes).filter(it -> !it.isEmpty()).ifPresent(configuration::setScanningIncludes); |
| ofNullable(manifestContributors).filter(it -> !it.isEmpty()).ifPresent(contributors -> { |
| configuration.setManifestContributors(manifestContributors.stream().map(clazz -> { |
| try { |
| return Thread.currentThread().getContextClassLoader().loadClass(clazz).getConstructor().newInstance(); |
| } catch (final InstantiationException | NoSuchMethodException | IllegalAccessException |
| | ClassNotFoundException e) { |
| throw new IllegalArgumentException(e); |
| } catch (final InvocationTargetException e) { |
| throw new IllegalArgumentException(e.getTargetException()); |
| } |
| }).map(ManifestContributor.class::cast).collect(toList())); |
| }); |
| ofNullable(jarFilter).ifPresent(filter -> { |
| try { |
| configuration.setJarFilter((Predicate<String>) Thread.currentThread().getContextClassLoader().loadClass(filter) |
| .getConstructor().newInstance()); |
| } catch (final InstantiationException | NoSuchMethodException | IllegalAccessException | ClassNotFoundException e) { |
| throw new IllegalArgumentException(e); |
| } catch (final InvocationTargetException e) { |
| throw new IllegalArgumentException(e.getTargetException()); |
| } |
| }); |
| return configuration; |
| } |
| } |