JCRVLT-249 add parameter for internal install hook (#51)

diff --git a/pom.xml b/pom.xml
index 17449a2..1bfdfdb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -432,6 +432,13 @@
             <artifactId>maven-shared-utils</artifactId>
             <version>3.3.3</version>
         </dependency>
+        
+        <dependency>
+            <groupId>org.eclipse.aether</groupId>
+            <artifactId>aether-api</artifactId>
+            <version>${aether.version}</version>
+            <scope>compile</scope>
+        </dependency>
 
         <!-- testing -->
         <dependency>
@@ -471,12 +478,6 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.eclipse.aether</groupId>
-            <artifactId>aether-api</artifactId>
-            <version>${aether.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-aether-provider</artifactId>
             <version>${maven.version}</version>
diff --git a/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/AbstractMetadataPackageMojo.java b/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/AbstractMetadataPackageMojo.java
index ac1dc06..888bbd0 100644
--- a/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/AbstractMetadataPackageMojo.java
+++ b/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/AbstractMetadataPackageMojo.java
@@ -30,6 +30,7 @@
 import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.project.MavenProject;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * Common ancestor of all mojos dealing with package metadata.
@@ -151,18 +152,18 @@
      */
     Map<String, File> getEmbeddedFilesMap() {
         Map<String, File> map = getEmbeddedFilesMap(PROPERTIES_EMBEDDEDFILESMAP_KEY + classifier);
-        if (map.isEmpty()) {
+        if (map == null) {
             getLog().debug("Using regular embedded files map as classifier specific one does not exist!");
             map = getEmbeddedFilesMap(PROPERTIES_EMBEDDEDFILESMAP_KEY);
         }
-        return map;
+        return map == null ? Collections.emptyMap() : map;
     }
 
     @SuppressWarnings("unchecked")
-    private Map<String, File> getEmbeddedFilesMap(String key) {
+    private @Nullable Map<String, File> getEmbeddedFilesMap(String key) {
         Object value = getPluginContext().get(key);
         if (value == null) {
-            return Collections.emptyMap();
+            return null;
         } else {
             if (value instanceof Map<?,?>) {
                 return (Map<String, File>) value;
diff --git a/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/ArtifactCoordinates.java b/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/ArtifactCoordinates.java
new file mode 100644
index 0000000..29b7ee7
--- /dev/null
+++ b/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/ArtifactCoordinates.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.jackrabbit.filevault.maven.packaging;
+
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.artifact.DefaultArtifact;
+
+/**
+ * Coordinates addressing a Maven artifact. 
+ * Can generate an Aether artifact which can be used to retrieve it from a local or remote repository.
+ */
+public class ArtifactCoordinates {
+
+    private String coordinates;
+    
+    public ArtifactCoordinates() {
+        
+    }
+    
+    /**
+     * 
+     * @param coordinates The artifact coordinates in the format {@code <groupId>:<artifactId>[:<extension>[:<classifier>]]:<version>}, must not be {@code null}.
+     */
+    public ArtifactCoordinates(String coordinates) {
+        this.coordinates = coordinates;
+    }
+
+    // default set method being called by https://github.com/eclipse/sisu.plexus/blob/4a43cdd39acf8a9f8a128d0f08204e98639e0c4b/org.eclipse.sisu.plexus/src/org/eclipse/sisu/plexus/CompositeBeanHelper.java#L74
+    public void set(String coordinates) {
+        this.coordinates = coordinates;
+    }
+
+    Artifact toArtifact() {
+        return new DefaultArtifact(coordinates);
+    }
+}
diff --git a/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/GenerateMetadataMojo.java b/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/GenerateMetadataMojo.java
index f0beb6c..e8c8886 100644
--- a/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/GenerateMetadataMojo.java
+++ b/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/GenerateMetadataMojo.java
@@ -33,6 +33,7 @@
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
@@ -80,6 +81,12 @@
 import org.codehaus.plexus.util.FileUtils;
 import org.codehaus.plexus.util.IOUtil;
 import org.codehaus.plexus.util.StringUtils;
+import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.repository.RemoteRepository;
+import org.eclipse.aether.resolution.ArtifactRequest;
+import org.eclipse.aether.resolution.ArtifactResolutionException;
+import org.eclipse.aether.resolution.ArtifactResult;
 import org.sonatype.plexus.build.incremental.BuildContext;
 
 import aQute.bnd.header.Attrs;
@@ -402,6 +409,22 @@
             required = true)
     boolean allowIndexDefinitions;
 
+    @Component
+    private RepositorySystem repoSystem;
+
+    @Parameter( defaultValue = "${repositorySystemSession}", readonly = true, required = true )
+    private RepositorySystemSession repoSession;
+
+    @Parameter( defaultValue = "${project.remoteProjectRepositories}", readonly = true, required = true )
+    private List<RemoteRepository> repositories;
+
+    /**
+     * A list of artifact coordinates in the format {@code <groupId>:<artifactId>[:<extension>[:<classifier>]]:<version>}.
+     * The resolved artifacts are embedded as <a href="http://jackrabbit.apache.org/filevault/installhooks.html">internal install hooks</a> in the resulting content package.
+     */
+    @Parameter(defaultValue="")
+    List<ArtifactCoordinates> installHooks;
+
     // take the first "-" followed by a digit as separator between version suffix and rest
     private static final Pattern FILENAME_PATTERN_WITHOUT_VERSION_IN_GROUP1 = Pattern.compile("((?!-\\d).*-)\\d.*");
 
@@ -488,6 +511,15 @@
             // calculate the embeddeds and subpackages
             Map<String, File> embeddedFiles = getEmbeddeds();
             embeddedFiles.putAll(getSubPackages());
+            
+            // embed install hooks
+            if (installHooks != null && !installHooks.isEmpty()) {
+                for (ArtifactCoordinates installHook : installHooks) {
+                    File installHookFile = resolveArtifact(installHook.toArtifact());
+                    embeddedFiles.put(Constants.META_DIR + "/" + Constants.HOOKS_DIR + "/" + installHookFile.getName(), installHookFile);
+                    getLog().info("Embed install hook " + installHookFile);
+                }
+            }
             setEmbeddedFilesMap(embeddedFiles);
 
             String dependenciesString = computeDependencies();
@@ -1199,4 +1231,15 @@
             }
         }
     }
+    
+    private File resolveArtifact(org.eclipse.aether.artifact.Artifact artifact) throws MojoExecutionException {
+        ArtifactRequest req = new ArtifactRequest(artifact, this.repositories, null);
+        ArtifactResult resolutionResult;
+        try {
+            resolutionResult = this.repoSystem.resolveArtifact( this.repoSession, req );
+            return resolutionResult.getArtifact().getFile();
+        } catch( ArtifactResolutionException e ) {
+            throw new MojoExecutionException( "Artifact " + artifact + " could not be resolved.", e );
+        }
+    }
 }