Merge branch 'master' of github.com:apache/tomee-patch-plugin into master
diff --git a/tomee-patch-plugin/pom.xml b/tomee-patch-plugin/pom.xml
index 280d7e7..076b4c3 100644
--- a/tomee-patch-plugin/pom.xml
+++ b/tomee-patch-plugin/pom.xml
@@ -36,13 +36,70 @@
     <maven-plugin.prefix>patch</maven-plugin.prefix>
     <plexus-compiler.version>2.8.6</plexus-compiler.version>
     <plexus-java.version>1.0.4</plexus-java.version>
+    <doxiaVersion>1.9.1</doxiaVersion>
+    <doxiaSiteVersion>1.9.2</doxiaSiteVersion>
+    <jettyVersion>9.2.28.v20190418</jettyVersion>
   </properties>
 
   <dependencies>
+
     <dependency>
-      <groupId>org.apache.tomee.patch</groupId>
-      <artifactId>tomee-patch-core</artifactId>
-      <version>${project.version}</version>
+      <groupId>classworlds</groupId>
+      <artifactId>classworlds</artifactId>
+      <version>1.1</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-cli</groupId>
+      <artifactId>commons-cli</artifactId>
+      <version>1.4</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>2.6</version>
+    </dependency>
+    <dependency>
+      <groupId>javax</groupId>
+      <artifactId>javaee-api</artifactId>
+      <version>8.0.1</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.11</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-collections4</artifactId>
+      <version>4.2</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+      <version>3.8.1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.doxia</groupId>
+      <artifactId>doxia-core</artifactId>
+      <version>${doxiaVersion}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.doxia</groupId>
+      <artifactId>doxia-sink-api</artifactId>
+      <version>${doxiaVersion}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.doxia</groupId>
+      <artifactId>doxia-site-renderer</artifactId>
+      <version>${doxiaSiteVersion}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.plugin-testing</groupId>
+      <artifactId>maven-plugin-testing-harness</artifactId>
+      <version>3.2.0</version>
+      <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.maven.plugin-tools</groupId>
@@ -50,30 +107,126 @@
       <version>3.3</version>
     </dependency>
     <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-utils</artifactId>
-      <version>3.0.17</version>
+      <groupId>org.apache.maven.reporting</groupId>
+      <artifactId>maven-reporting-api</artifactId>
+      <version>3.0</version>
     </dependency>
     <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-java</artifactId>
-      <version>${plexus-java.version}</version>
-    </dependency>
-
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-compiler-api</artifactId>
-      <version>${plexus-compiler.version}</version>
+      <groupId>org.apache.maven.reporting</groupId>
+      <artifactId>maven-reporting-impl</artifactId>
+      <version>3.0.0</version>
       <exclusions>
         <exclusion>
-          <groupId>org.codehaus.plexus</groupId>
-          <artifactId>plexus-component-api</artifactId>
+          <artifactId>maven-artifact-manager</artifactId>
+          <groupId>org.apache.maven</groupId>
+        </exclusion>
+        <exclusion>
+          <artifactId>maven-project</artifactId>
+          <groupId>org.apache.maven</groupId>
+        </exclusion>
+        <exclusion>
+          <artifactId>maven-profile</artifactId>
+          <groupId>org.apache.maven</groupId>
+        </exclusion>
+        <exclusion>
+          <artifactId>maven-plugin-registry</artifactId>
+          <groupId>org.apache.maven</groupId>
         </exclusion>
       </exclusions>
     </dependency>
     <dependency>
+      <groupId>org.apache.maven.shared</groupId>
+      <artifactId>maven-artifact-transfer</artifactId>
+      <version>0.13.1</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.shared</groupId>
+      <artifactId>maven-common-artifact-filters</artifactId>
+      <version>3.2.0</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.shared</groupId>
+      <artifactId>maven-dependency-analyzer</artifactId>
+      <version>1.11.3</version>
+      <exclusions>
+        <exclusion>
+          <artifactId>maven-project</artifactId>
+          <groupId>org.apache.maven</groupId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.shared</groupId>
+      <artifactId>maven-dependency-tree</artifactId>
+      <version>3.0.1</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.shared</groupId>
+      <artifactId>maven-shared-utils</artifactId>
+      <version>3.3.3</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.wagon</groupId>
+      <artifactId>wagon-http-lightweight</artifactId>
+      <version>3.4.0</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-aether-provider</artifactId>
+      <version>${maven.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-artifact</artifactId>
+      <version>${maven.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-compat</artifactId>
+      <version>${maven.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-core</artifactId>
+      <version>${maven.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-model</artifactId>
+      <version>${maven.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-plugin-api</artifactId>
+      <version>${maven.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-repository-metadata</artifactId>
+      <version>${maven.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-settings</artifactId>
+      <version>${maven.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.tomee.patch</groupId>
+      <artifactId>tomee-patch-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
       <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-compiler-manager</artifactId>
+      <artifactId>plexus-archiver</artifactId>
+      <version>4.2.2</version>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-compiler-api</artifactId>
       <version>${plexus-compiler.version}</version>
       <exclusions>
         <exclusion>
@@ -95,58 +248,47 @@
       </exclusions>
     </dependency>
     <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-plugin-api</artifactId>
-      <version>${maven.version}</version>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-compiler-manager</artifactId>
+      <version>${plexus-compiler.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>org.codehaus.plexus</groupId>
+          <artifactId>plexus-component-api</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
     <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-model</artifactId>
-      <version>${maven.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-core</artifactId>
-      <version>${maven.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>commons-cli</groupId>
-      <artifactId>commons-cli</artifactId>
-      <version>1.4</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-artifact</artifactId>
-      <version>${maven.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-compat</artifactId>
-      <version>${maven.version}</version>
-    </dependency>
-
-    <!-- TESTS -->
-    <dependency>
-      <groupId>org.apache.maven.plugin-testing</groupId>
-      <artifactId>maven-plugin-testing-harness</artifactId>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-io</artifactId>
       <version>3.2.0</version>
-      <scope>test</scope>
     </dependency>
-
     <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-aether-provider</artifactId>
-      <version>${maven.version}</version>
-      <scope>test</scope>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-java</artifactId>
+      <version>${plexus-java.version}</version>
     </dependency>
-
     <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>4.11</version>
-      <scope>test</scope>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+      <version>3.3.0</version>
     </dependency>
-
+    <dependency>
+      <groupId>org.eclipse.aether</groupId>
+      <artifactId>aether-api</artifactId>
+      <version>0.9.0.M2</version>
+    </dependency>
+    <dependency>
+      <groupId>org.eclipse.aether</groupId>
+      <artifactId>aether-connector-wagon</artifactId>
+      <version>0.9.0.M2</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.eclipse.aether</groupId>
+      <artifactId>aether-util</artifactId>
+      <version>0.9.0.M2</version>
+    </dependency>
     <dependency>
       <groupId>org.jboss.shrinkwrap</groupId>
       <artifactId>shrinkwrap-api</artifactId>
@@ -159,12 +301,6 @@
       <version>1.2.6</version>
       <scope>test</scope>
     </dependency>
-    <dependency>
-      <groupId>javax</groupId>
-      <artifactId>javaee-api</artifactId>
-      <version>8.0.1</version>
-      <scope>test</scope>
-    </dependency>
   </dependencies>
 </project>
 
diff --git a/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/PatchMojo.java b/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/PatchMojo.java
index d6d4cc2..264eea7 100644
--- a/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/PatchMojo.java
+++ b/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/PatchMojo.java
@@ -17,16 +17,35 @@
 package org.apache.tomee.patch.plugin;
 
 import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.handler.ArtifactHandler;
+import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
+import org.apache.maven.artifact.repository.MavenArtifactRepository;
+import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
 import org.apache.maven.plugins.annotations.Component;
 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.project.DefaultProjectBuildingRequest;
 import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.ProjectBuildingRequest;
 import org.apache.maven.project.artifact.AttachedArtifact;
+import org.apache.maven.repository.RepositorySystem;
+import org.apache.maven.settings.Settings;
+import org.apache.maven.shared.transfer.artifact.ArtifactCoordinate;
+import org.apache.maven.shared.transfer.artifact.DefaultArtifactCoordinate;
+import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResolver;
+import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResolverException;
+import org.apache.maven.shared.transfer.dependencies.DefaultDependableCoordinate;
+import org.apache.maven.shared.transfer.dependencies.DependableCoordinate;
+import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolver;
+import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolverException;
 import org.apache.maven.toolchain.Toolchain;
 import org.apache.maven.toolchain.ToolchainManager;
 import org.apache.tomee.patch.core.Additions;
@@ -41,6 +60,7 @@
 import org.codehaus.plexus.compiler.CompilerResult;
 import org.codehaus.plexus.compiler.manager.CompilerManager;
 import org.codehaus.plexus.compiler.manager.NoSuchCompilerException;
+import org.codehaus.plexus.util.StringUtils;
 import org.tomitribe.jkta.usage.Dir;
 import org.tomitribe.jkta.util.Paths;
 import org.tomitribe.swizzle.stream.StreamBuilder;
@@ -62,6 +82,7 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.function.Predicate;
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -69,6 +90,56 @@
 @Mojo(name = "run", requiresDependencyResolution = ResolutionScope.RUNTIME_PLUS_SYSTEM, defaultPhase = LifecyclePhase.PACKAGE, requiresProject = true, threadSafe = true)
 public class PatchMojo extends AbstractMojo {
 
+    private static final Pattern ALT_REPO_SYNTAX_PATTERN = Pattern.compile("(.+)::(.*)::(.+)");
+
+    @Component
+    private ArtifactResolver artifactResolver;
+
+    @Component
+    private DependencyResolver dependencyResolver;
+
+    @Component
+    private ArtifactHandlerManager artifactHandlerManager;
+
+    /**
+     * Map that contains the layouts.
+     */
+    @Component(role = ArtifactRepositoryLayout.class)
+    private Map<String, ArtifactRepositoryLayout> repositoryLayouts;
+
+    /**
+     * The repository system.
+     */
+    @Component
+    private RepositorySystem repositorySystem;
+
+    /**
+     * Repositories in the format id::[layout]::url or just url, separated by comma. ie.
+     * central::default::https://repo.maven.apache.org/maven2,myrepo::::https://repo.acme.com,https://repo.acme2.com
+     */
+    @Parameter(property = "remoteRepositories")
+    private String remoteRepositories;
+
+    /**
+     *
+     */
+    @Parameter(defaultValue = "${project.remoteArtifactRepositories}", readonly = true, required = true)
+    private List<ArtifactRepository> pomRemoteRepositories;
+
+    /**
+     * Download transitively, retrieving the specified artifact and all of its dependencies.
+     */
+    @Parameter(property = "transitive", defaultValue = "true")
+    private boolean transitive = true;
+
+    /**
+     * Skip plugin execution completely.
+     *
+     * @since 2.7
+     */
+    @Parameter(property = "mdep.skip", defaultValue = "false")
+    private boolean skip;
+
     @Parameter(defaultValue = "${project}", readonly = true, required = true)
     private MavenProject project;
 
@@ -239,7 +310,7 @@
             }
 
             transformation.complete();
-        } catch (IOException e) {
+        } catch (IOException | MojoFailureException e) {
             throw new MojoExecutionException("Error occurred during execution", e);
         }
     }
@@ -342,7 +413,8 @@
         return selected;
     }
 
-    private void compile(final List<File> jars) throws MojoExecutionException, CompilationFailureException {
+    private void compile(final List<File> jars) throws MojoExecutionException, MojoFailureException {
+        final List<File> files = resolve(dependencies);
 
         getLog().debug("Using compiler '" + compilerId + "'.");
 
@@ -417,9 +489,7 @@
                 .map(File::getAbsolutePath)
                 .forEach(compilerConfiguration::addClasspathEntry);
 
-
-        dependencies.stream()
-                .map(Mvn::mvn)
+        files.stream()
                 .map(File::getAbsolutePath)
                 .forEach(compilerConfiguration::addClasspathEntry);
 
@@ -501,6 +571,23 @@
         }
     }
 
+    private List<File> resolve(final List<String> dependencies) throws MojoFailureException, MojoExecutionException {
+        final List<File> resolvedDependencies = new ArrayList<File>();
+        for (final String dependency : dependencies) {
+            final File file = resolve(dependency);
+            resolvedDependencies.add(file);
+        }
+        return resolvedDependencies;
+    }
+
+    private File resolve(final String gav) throws MojoFailureException, MojoExecutionException {
+        try {
+            return Mvn.mvn(gav);
+        } catch (Exception e) {
+            return download(gav);
+        }
+    }
+
     private void copy(final File root, final File src, final File dest) {
         copy:
         for (final File file : src.listFiles()) {
@@ -630,4 +717,135 @@
             super(String.format("No artifacts matched expression '%s'", select));
         }
     }
+
+    public File download(final String gav) throws MojoExecutionException, MojoFailureException {
+
+        final DefaultDependableCoordinate coordinate = mvn(gav);
+
+        ArtifactRepositoryPolicy always =
+                new ArtifactRepositoryPolicy(true, ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS,
+                        ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN);
+
+        List<ArtifactRepository> repoList = new ArrayList<>();
+
+        if (pomRemoteRepositories != null) {
+            repoList.addAll(pomRemoteRepositories);
+        }
+
+        if (remoteRepositories != null) {
+            // Use the same format as in the deploy plugin id::layout::url
+            String[] repos = StringUtils.split(remoteRepositories, ",");
+            for (String repo : repos) {
+                repoList.add(parseRepository(repo, always));
+            }
+        }
+
+        try {
+            ProjectBuildingRequest buildingRequest =
+                    new DefaultProjectBuildingRequest(session.getProjectBuildingRequest());
+
+            Settings settings = session.getSettings();
+            repositorySystem.injectMirror(repoList, settings.getMirrors());
+            repositorySystem.injectProxy(repoList, settings.getProxies());
+            repositorySystem.injectAuthentication(repoList, settings.getServers());
+
+            buildingRequest.setRemoteRepositories(repoList);
+
+            if (transitive) {
+                getLog().info("Resolving " + coordinate + " with transitive dependencies");
+                dependencyResolver.resolveDependencies(buildingRequest, coordinate, null);
+            } else {
+                getLog().info("Resolving " + coordinate);
+                artifactResolver.resolveArtifact(buildingRequest, toArtifactCoordinate(coordinate));
+            }
+        } catch (ArtifactResolverException | DependencyResolverException e) {
+            throw new MojoExecutionException("Couldn't download artifact: " + e.getMessage(), e);
+        }
+
+        return Mvn.mvn(gav);
+    }
+
+    private ArtifactCoordinate toArtifactCoordinate(DependableCoordinate dependableCoordinate) {
+        ArtifactHandler artifactHandler = artifactHandlerManager.getArtifactHandler(dependableCoordinate.getType());
+        DefaultArtifactCoordinate artifactCoordinate = new DefaultArtifactCoordinate();
+        artifactCoordinate.setGroupId(dependableCoordinate.getGroupId());
+        artifactCoordinate.setArtifactId(dependableCoordinate.getArtifactId());
+        artifactCoordinate.setVersion(dependableCoordinate.getVersion());
+        artifactCoordinate.setClassifier(dependableCoordinate.getClassifier());
+        artifactCoordinate.setExtension(artifactHandler.getExtension());
+        return artifactCoordinate;
+    }
+
+    ArtifactRepository parseRepository(String repo, ArtifactRepositoryPolicy policy)
+            throws MojoFailureException {
+        // if it's a simple url
+        String id = "temp";
+        ArtifactRepositoryLayout layout = getLayout("default");
+        String url = repo;
+
+        // if it's an extended repo URL of the form id::layout::url
+        if (repo.contains("::")) {
+            Matcher matcher = ALT_REPO_SYNTAX_PATTERN.matcher(repo);
+            if (!matcher.matches()) {
+                throw new MojoFailureException(repo, "Invalid syntax for repository: " + repo,
+                        "Invalid syntax for repository. Use \"id::layout::url\" or \"URL\".");
+            }
+
+            id = matcher.group(1).trim();
+            if (!StringUtils.isEmpty(matcher.group(2))) {
+                layout = getLayout(matcher.group(2).trim());
+            }
+            url = matcher.group(3).trim();
+        }
+        return new MavenArtifactRepository(id, url, layout, policy, policy);
+    }
+
+    private ArtifactRepositoryLayout getLayout(String id)
+            throws MojoFailureException {
+        ArtifactRepositoryLayout layout = repositoryLayouts.get(id);
+
+        if (layout == null) {
+            throw new MojoFailureException(id, "Invalid repository layout", "Invalid repository layout: " + id);
+        }
+
+        return layout;
+    }
+
+    public static DefaultDependableCoordinate mvn(final String coordinates) {
+        final String[] parts = coordinates.split(":");
+
+        // org.apache.tomee:apache-tomee:zip:plus:7.1.0
+        if (parts.length == 5) {
+            final String group = parts[0];
+            final String artifact = parts[1];
+            final String packaging = parts[2];
+            final String classifier = parts[3];
+            final String version = parts[4];
+            return mvn(group, artifact, version, packaging, classifier);
+        }
+
+        // org.apache.tomee:tomee-util:jar:7.1.0
+        if (parts.length == 4) {
+            final String group = parts[0];
+            final String artifact = parts[1];
+            final String packaging = parts[2];
+            final String version = parts[3];
+            return mvn(group, artifact, version, packaging, null);
+        }
+
+        throw new IllegalArgumentException("Unsupported coordinates (GAV): " + coordinates);
+    }
+
+    private static DefaultDependableCoordinate mvn(final String group, final String artifact,
+                                                   final String version, final String packaging,
+                                                   final String classifier) {
+        final DefaultDependableCoordinate coordinate = new DefaultDependableCoordinate();
+        coordinate.setArtifactId(artifact);
+        coordinate.setClassifier(classifier);
+        coordinate.setGroupId(group);
+        coordinate.setVersion(version);
+        coordinate.setType(packaging);
+        return coordinate;
+    }
+
 }