Bug 3656: Introducing karaf-plugin 35/22735/1
authorEd Warnicke <hagbard@gmail.com>
Mon, 15 Jun 2015 23:07:29 +0000 (17:07 -0600)
committerEd Warnicke <hagbard@gmail.com>
Tue, 16 Jun 2015 21:22:13 +0000 (15:22 -0600)
This plugin recursively walks down the features files and
installs all related artifacts.

Change-Id: Ie466f22a71945fa7fb19199820196551688d2d6d
Signed-off-by: Ed Warnicke <hagbard@gmail.com>
karaf-plugin/pom.xml [new file with mode: 0644]
karaf-plugin/src/it/settings.xml [new file with mode: 0644]
karaf-plugin/src/it/simple-it/pom.xml [new file with mode: 0644]
karaf-plugin/src/it/simple-it/verify.groovy [new file with mode: 0644]
karaf-plugin/src/main/java/org/opendaylight/odlparent/AetherUtil.java [new file with mode: 0644]
karaf-plugin/src/main/java/org/opendaylight/odlparent/FeatureUtil.java [new file with mode: 0644]
karaf-plugin/src/main/java/org/opendaylight/odlparent/KarafFeaturesDependencyFilter.java [new file with mode: 0644]
karaf-plugin/src/main/java/org/opendaylight/odlparent/MvnToAetherMapper.java [new file with mode: 0644]
karaf-plugin/src/main/java/org/opendaylight/odlparent/PopulateLocalRepoMojo.java [new file with mode: 0644]
pom.xml

diff --git a/karaf-plugin/pom.xml b/karaf-plugin/pom.xml
new file mode 100644 (file)
index 0000000..0441d56
--- /dev/null
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>odlparent</artifactId>
+    <groupId>org.opendaylight.odlparent</groupId>
+    <version>1.5.0-SNAPSHOT</version>
+    <relativePath>../odlparent/</relativePath>
+  </parent>
+  <artifactId>karaf-plugin</artifactId>
+  <packaging>maven-plugin</packaging>
+
+  <name>karaf-plugin Maven Plugin</name>
+
+  <!-- FIXME change it to the project's website -->
+  <url>http://maven.apache.org</url>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-plugin-api</artifactId>
+      <version>3.0.3</version>
+    </dependency>
+    <dependency>
+        <groupId>org.ops4j.pax.url</groupId>
+        <artifactId>pax-url-wrap</artifactId>
+        <version>${url.version}</version>
+    </dependency>
+    <dependency>
+        <groupId>org.ops4j.pax.url</groupId>
+        <artifactId>pax-url-aether</artifactId>
+        <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.karaf.features</groupId>
+      <artifactId>org.apache.karaf.features.core</artifactId>
+      <version>${karaf.version}</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.karaf.tooling</groupId>
+      <artifactId>karaf-maven-plugin</artifactId>
+      <version>${karaf.version}</version>
+    </dependency>
+    <dependency>
+       <groupId>com.google.guava</groupId>
+       <artifactId>guava</artifactId>
+      </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-plugin-plugin</artifactId>
+        <version>3.2</version>
+        <configuration>
+          <goalPrefix>karaf-plugin</goalPrefix>
+          <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
+        </configuration>
+        <executions>
+          <execution>
+            <id>mojo-descriptor</id>
+            <goals>
+              <goal>descriptor</goal>
+            </goals>
+          </execution>
+          <execution>
+            <id>help-goal</id>
+            <goals>
+              <goal>helpmojo</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <profiles>
+    <profile>
+      <id>run-its</id>
+      <build>
+
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-invoker-plugin</artifactId>
+            <version>1.7</version>
+            <configuration>
+              <debug>true</debug>
+              <cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo>
+              <pomIncludes>
+                <pomInclude>*/pom.xml</pomInclude>
+              </pomIncludes>
+              <postBuildHookScript>verify</postBuildHookScript>
+              <localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath>
+              <settingsFile>src/it/settings.xml</settingsFile>
+              <goals>
+                <goal>clean</goal>
+                <goal>test-compile</goal>
+              </goals>
+            </configuration>
+            <executions>
+              <execution>
+                <id>integration-test</id>
+                <goals>
+                  <goal>install</goal>
+                  <goal>integration-test</goal>
+                  <goal>verify</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+
+      </build>
+    </profile>
+  </profiles>
+</project>
diff --git a/karaf-plugin/src/it/settings.xml b/karaf-plugin/src/it/settings.xml
new file mode 100644 (file)
index 0000000..c8f77f0
--- /dev/null
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<settings>
+  <profiles>
+    <profile>
+      <id>it-repo</id>
+      <activation>
+        <activeByDefault>true</activeByDefault>
+      </activation>
+      <repositories>
+        <repository>
+          <id>local.central</id>
+          <url>@localRepositoryUrl@</url>
+          <releases>
+            <enabled>true</enabled>
+          </releases>
+          <snapshots>
+            <enabled>true</enabled>
+          </snapshots>
+        </repository>
+      </repositories>
+      <pluginRepositories>
+        <pluginRepository>
+          <id>local.central</id>
+          <url>@localRepositoryUrl@</url>
+          <releases>
+            <enabled>true</enabled>
+          </releases>
+          <snapshots>
+            <enabled>true</enabled>
+          </snapshots>
+        </pluginRepository>
+      </pluginRepositories>
+    </profile>
+  </profiles>
+</settings>
diff --git a/karaf-plugin/src/it/simple-it/pom.xml b/karaf-plugin/src/it/simple-it/pom.xml
new file mode 100644 (file)
index 0000000..c278e14
--- /dev/null
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.opendaylight.odlparent.it</groupId>
+  <artifactId>simple-it</artifactId>
+  <version>1.0-SNAPSHOT</version>
+
+  <description>A simple IT verifying the basic use case.</description>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>@project.groupId@</groupId>
+        <artifactId>@project.artifactId@</artifactId>
+        <version>@project.version@</version>
+        <executions>
+          <execution>
+            <id>touch</id>
+            <phase>validate</phase>
+            <goals>
+              <goal>touch</goal>
+            </goals>
+            <configuration>
+                <featureRepos>
+                    <param>foo</param>
+                </featureRepos>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/karaf-plugin/src/it/simple-it/verify.groovy b/karaf-plugin/src/it/simple-it/verify.groovy
new file mode 100644 (file)
index 0000000..7b307c7
--- /dev/null
@@ -0,0 +1,3 @@
+File touchFile = new File( basedir, "target/touch.txt" );
+
+assert touchFile.isFile()
diff --git a/karaf-plugin/src/main/java/org/opendaylight/odlparent/AetherUtil.java b/karaf-plugin/src/main/java/org/opendaylight/odlparent/AetherUtil.java
new file mode 100644 (file)
index 0000000..61d9fc7
--- /dev/null
@@ -0,0 +1,103 @@
+package org.opendaylight.odlparent;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.aether.DefaultRepositorySystemSession;
+import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.artifact.DefaultArtifact;
+import org.eclipse.aether.collection.CollectRequest;
+import org.eclipse.aether.graph.Dependency;
+import org.eclipse.aether.graph.DependencyFilter;
+import org.eclipse.aether.installation.InstallRequest;
+import org.eclipse.aether.installation.InstallationException;
+import org.eclipse.aether.repository.LocalRepository;
+import org.eclipse.aether.repository.LocalRepositoryManager;
+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.eclipse.aether.resolution.DependencyRequest;
+import org.eclipse.aether.resolution.DependencyResolutionException;
+import org.eclipse.aether.resolution.DependencyResult;
+
+public class AetherUtil {
+
+    private RepositorySystem repoSystem;
+
+    private RepositorySystemSession repoSession;
+
+    private List<RemoteRepository> remoteRepos;
+
+    protected File localRepository;
+
+    public AetherUtil(RepositorySystem repoSystem,RepositorySystemSession repoSession,List<RemoteRepository> remoteRepos, File localRepository) {
+        this.repoSystem = repoSystem;
+        this.repoSession = repoSession;
+        this.remoteRepos = remoteRepos;
+        this.localRepository = localRepository;
+    }
+
+    public Set<Artifact> resolveDependencies(List<Dependency>dependencies,DependencyFilter filter) throws DependencyResolutionException {
+        Set<Artifact> artifacts = new LinkedHashSet<Artifact>();
+        CollectRequest collectRequest = new CollectRequest();
+        collectRequest.setDependencies(dependencies);
+        collectRequest.setRepositories(remoteRepos);
+        DependencyRequest request = new DependencyRequest(collectRequest,filter);
+        DependencyResult results = repoSystem.resolveDependencies(repoSession, request);
+        for(ArtifactResult artifactResult: results.getArtifactResults()) {
+            artifacts.add(artifactResult.getArtifact());
+        }
+        return artifacts;
+    }
+
+    public Artifact resolveArtifact(Artifact artifact) throws ArtifactResolutionException {
+        ArtifactRequest request = new ArtifactRequest(artifact, remoteRepos,null);
+        ArtifactResult result = repoSystem.resolveArtifact(repoSession, request);
+        return result.getArtifact();
+    }
+
+    public Artifact resolveArtifact(String coord) throws ArtifactResolutionException {
+        DefaultArtifact artifact = new DefaultArtifact(coord);
+        return resolveArtifact(artifact);
+    }
+
+    public Set<Artifact> resolveArtifacts(Set<String> coords) throws ArtifactResolutionException {
+        Set<Artifact> result = new LinkedHashSet<Artifact>();
+        for(String coord: coords) {
+            result.add(resolveArtifact(coord));
+        }
+        return result;
+    }
+
+    public Dependency toDependency(String coord) {
+        Artifact artifact = new DefaultArtifact(coord);
+        Dependency dependency = new Dependency(artifact, null);
+        return dependency;
+    }
+
+    public List<Dependency> toDependencies(List<String> coords) {
+        List<Dependency> result = new ArrayList<Dependency>();
+        for(String coord: coords) {
+            result.add(toDependency(coord));
+        }
+        return result;
+    }
+
+    public void installArtifacts(Set<Artifact> artifacts) throws InstallationException {
+        LocalRepository localRepo = new LocalRepository(localRepository);
+        LocalRepositoryManager localManager = repoSystem.newLocalRepositoryManager(repoSession, localRepo);
+        DefaultRepositorySystemSession localSession = new DefaultRepositorySystemSession();
+        localSession.setLocalRepositoryManager(localManager);
+        InstallRequest installRequest = new InstallRequest();
+        for(Artifact featureArtifact : artifacts) {
+            installRequest.addArtifact(featureArtifact);
+        }
+        repoSystem.install(localSession, installRequest);
+    }
+}
diff --git a/karaf-plugin/src/main/java/org/opendaylight/odlparent/FeatureUtil.java b/karaf-plugin/src/main/java/org/opendaylight/odlparent/FeatureUtil.java
new file mode 100644 (file)
index 0000000..2fb4a13
--- /dev/null
@@ -0,0 +1,159 @@
+package org.opendaylight.odlparent;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.karaf.features.internal.model.Bundle;
+import org.apache.karaf.features.internal.model.ConfigFile;
+import org.apache.karaf.features.internal.model.Feature;
+import org.apache.karaf.features.internal.model.Features;
+import org.apache.karaf.features.internal.model.JaxbUtil;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.resolution.ArtifactResolutionException;
+import org.ops4j.pax.url.mvn.Parser;
+
+public class FeatureUtil {
+
+    public static  List<String> toCoord(List<URL> urls) throws MalformedURLException {
+        List<String> result = new ArrayList<String>();
+        for(URL url:urls) {
+            result.add(toCoord(url));
+        }
+        return result;
+    }
+
+    public static String toCoord(URL url) throws MalformedURLException {
+        String repository = url.toString();
+        String unwrappedRepo = repository.replaceFirst("wrap:", "");
+        Parser parser = new Parser(unwrappedRepo);
+        String coord = parser.getGroup().replace("mvn:","") + ":" + parser.getArtifact();
+        if(parser.getType() != null) {
+            coord = coord + ":" + parser.getType();
+        }
+        if(parser.getClassifier() != null) {
+            coord = coord + ":" + parser.getClassifier();
+        }
+        coord = coord + ":" + parser.getVersion().replaceAll("\\$.*$", "");
+        return coord;
+    }
+
+    public static Set<String> mvnUrlsToCoord(List<String> repository) throws MalformedURLException {
+        Set<String> result = new LinkedHashSet<String>();
+        for(String url:repository) {
+            result.add(toCoord(new URL(url)));
+        }
+        return result;
+    }
+
+    public static Set<String> featuresRepositoryToCoords(Features features) throws MalformedURLException {
+        return mvnUrlsToCoord(features.getRepository());
+    }
+
+    public static Set<String> featuresRepositoryToCoords(Set<Features> features) throws MalformedURLException {
+        Set<String> result = new LinkedHashSet<String>();
+        for(Features feature:features) {
+            result.addAll(featuresRepositoryToCoords(feature));
+        }
+        return result;
+    }
+
+    public static Set<String> featureToCoords(Feature feature) throws MalformedURLException {
+        Set<String> result = new LinkedHashSet<String>();
+        if(feature.getBundle() != null) {
+            result.addAll(bundlesToCoords(feature.getBundle()));
+        }
+        if(feature.getConfigfile() != null) {
+            result.addAll(configFilesToCoords(feature.getConfigfile()));
+        }
+        return result;
+    }
+
+    public static Set<String> configFilesToCoords(List<ConfigFile> configfiles) throws MalformedURLException {
+        Set<String> result = new LinkedHashSet<String>();
+        for(ConfigFile configFile: configfiles) {
+            result.add(toCoord(new URL(configFile.getLocation())));
+        }
+        return result;
+    }
+
+    public static Set<String> bundlesToCoords(List<Bundle> bundles) throws MalformedURLException {
+        Set<String> result = new LinkedHashSet<String>();
+        for(Bundle bundle: bundles) {
+            result.add(toCoord(new URL(bundle.getLocation())));
+        }
+        return result;
+    }
+
+    public static Set<String> featuresToCoords(Features features) throws MalformedURLException {
+        Set<String> result = new LinkedHashSet<String>();
+        if(features.getRepository() != null) {
+            result.addAll(featuresRepositoryToCoords(features));
+        }
+        if(features.getFeature() != null) {
+            for(Feature feature: features.getFeature() ) {
+                result.addAll(featureToCoords(feature));
+            }
+        }
+        return result;
+    }
+
+    public static Set<String> featuresToCoords(Set<Features> features) throws MalformedURLException {
+        Set<String> result = new LinkedHashSet<String>();
+        for(Features feature:features) {
+            result.addAll(featuresToCoords(feature));
+        }
+        return result;
+    }
+
+    public static LinkedHashSet<Features> readFeatures(Set<Artifact> featureArtifacts) throws FileNotFoundException {
+        LinkedHashSet<Features> result = new LinkedHashSet<Features>();
+        for(Artifact artifact: featureArtifacts) {
+            result.add(readFeature(artifact));
+        }
+        return result;
+    }
+
+    public static Features readFeature(Artifact artifact) throws FileNotFoundException {
+        Features result;
+        File file = artifact.getFile();
+        FileInputStream stream = new FileInputStream(file);
+        Features features = JaxbUtil.unmarshal(stream, false);
+        result = features;
+        return result;
+    }
+
+    public static Features readFeature(AetherUtil aetherUtil,String coords) throws ArtifactResolutionException, FileNotFoundException {
+        Artifact artifact = aetherUtil.resolveArtifact(coords);
+        return readFeature(artifact);
+    }
+
+    public static Set<Features> findAllFeaturesRecursively(AetherUtil aetherUtil,Features features,Set<String> existingCoords) throws MalformedURLException, FileNotFoundException, ArtifactResolutionException {
+        Set<Features> result = new LinkedHashSet<Features>();
+        Set<String> coords = FeatureUtil.featuresRepositoryToCoords(features);
+        for(String coord : coords) {
+            if(!existingCoords.contains(coord)) {
+                existingCoords.add(coord);
+                Features f = FeatureUtil.readFeature(aetherUtil,coord);
+                result.add(f);
+                result.addAll(findAllFeaturesRecursively(aetherUtil,FeatureUtil.readFeature(aetherUtil,coord), existingCoords));
+            }
+        }
+        return result;
+    }
+
+    public static Set<Features> findAllFeaturesRecursively(AetherUtil aetherUtil,Set<Features> features,Set<String> existingCoords) throws MalformedURLException, FileNotFoundException, ArtifactResolutionException {
+        Set<Features> result = new LinkedHashSet<Features>();
+        for(Features feature: features) {
+            result.addAll(findAllFeaturesRecursively(aetherUtil, feature, existingCoords));
+        }
+        return result;
+    }
+
+}
diff --git a/karaf-plugin/src/main/java/org/opendaylight/odlparent/KarafFeaturesDependencyFilter.java b/karaf-plugin/src/main/java/org/opendaylight/odlparent/KarafFeaturesDependencyFilter.java
new file mode 100644 (file)
index 0000000..2ce05a9
--- /dev/null
@@ -0,0 +1,22 @@
+package org.opendaylight.odlparent;
+
+import java.util.List;
+
+import org.eclipse.aether.graph.DependencyFilter;
+import org.eclipse.aether.graph.DependencyNode;
+
+public class KarafFeaturesDependencyFilter implements DependencyFilter {
+
+    public boolean accept(DependencyNode node, List<DependencyNode> parents) {
+        if(node != null
+                && node.getArtifact() != null
+                && node.getDependency() != null
+                && node.getDependency().getScope() != null
+                && node.getArtifact().getClassifier().equals("features")
+                && node.getArtifact().getExtension().equals("xml")) {
+            return true;
+        }
+        return false;
+    }
+
+}
diff --git a/karaf-plugin/src/main/java/org/opendaylight/odlparent/MvnToAetherMapper.java b/karaf-plugin/src/main/java/org/opendaylight/odlparent/MvnToAetherMapper.java
new file mode 100644 (file)
index 0000000..a9d5927
--- /dev/null
@@ -0,0 +1,30 @@
+package org.opendaylight.odlparent;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.aether.artifact.DefaultArtifact;
+import org.eclipse.aether.artifact.DefaultArtifactType;
+import org.eclipse.aether.graph.Dependency;
+
+public class MvnToAetherMapper {
+
+    public static Dependency toAether(org.apache.maven.model.Dependency dependency) {
+        DefaultArtifact artifact = new DefaultArtifact(dependency.getGroupId(),
+                dependency.getArtifactId(),
+                dependency.getClassifier(),
+                null,
+                dependency.getVersion(),
+                new DefaultArtifactType(dependency.getType()));
+        Dependency result = new Dependency(artifact, null);
+        return result;
+    }
+
+    public static List<Dependency> toAether(List<org.apache.maven.model.Dependency> dependencies) {
+        List<Dependency> result = new ArrayList<Dependency>();
+        for(org.apache.maven.model.Dependency dependency : dependencies) {
+            result.add(toAether(dependency));
+        }
+        return result;
+    }
+}
diff --git a/karaf-plugin/src/main/java/org/opendaylight/odlparent/PopulateLocalRepoMojo.java b/karaf-plugin/src/main/java/org/opendaylight/odlparent/PopulateLocalRepoMojo.java
new file mode 100644 (file)
index 0000000..a8b4fc9
--- /dev/null
@@ -0,0 +1,133 @@
+package org.opendaylight.odlparent;
+
+/*
+ * Copyright 2001-2005 The Apache Software Foundation.
+ *
+ * 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.
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.karaf.features.internal.model.Bundle;
+import org.apache.karaf.features.internal.model.ConfigFile;
+import org.apache.karaf.features.internal.model.Feature;
+import org.apache.karaf.features.internal.model.Features;
+import org.apache.karaf.features.internal.model.JaxbUtil;
+import org.apache.karaf.tooling.url.CustomBundleURLStreamHandlerFactory;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.project.MavenProject;
+import org.eclipse.aether.DefaultRepositorySystemSession;
+import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.artifact.DefaultArtifact;
+import org.eclipse.aether.artifact.DefaultArtifactType;
+import org.eclipse.aether.collection.CollectRequest;
+import org.eclipse.aether.collection.DependencyCollectionException;
+import org.eclipse.aether.graph.Dependency;
+import org.eclipse.aether.installation.InstallRequest;
+import org.eclipse.aether.installation.InstallationException;
+import org.eclipse.aether.repository.LocalRepository;
+import org.eclipse.aether.repository.LocalRepositoryManager;
+import org.eclipse.aether.repository.RemoteRepository;
+import org.eclipse.aether.resolution.ArtifactResolutionException;
+import org.eclipse.aether.resolution.ArtifactResult;
+import org.eclipse.aether.resolution.DependencyRequest;
+import org.eclipse.aether.resolution.DependencyResolutionException;
+import org.eclipse.aether.resolution.DependencyResult;
+import org.ops4j.pax.url.mvn.Parser;
+
+/**
+ * @goal populate-local-repo
+ * @phase prepare-package
+ */
+public class PopulateLocalRepoMojo
+    extends AbstractMojo {
+
+    static {
+        // Static initialization, as we may be invoked multiple times
+        URL.setURLStreamHandlerFactory(new CustomBundleURLStreamHandlerFactory());
+    }
+
+    /**
+     * @component
+     * @required
+     * @readonly
+     */
+    private MavenProject project;
+
+    /**
+     * The entry point to Aether, i.e. the component doing all the work.
+     *
+     * @component
+     */
+    private RepositorySystem repoSystem;
+
+    /**
+     * The current repository/network configuration of Maven.
+     *
+     * @parameter default-value="${repositorySystemSession}"
+     * @readonly
+     */
+    private RepositorySystemSession repoSession;
+
+    /**
+     * The project's remote repositories to use for the resolution of plugins and their dependencies.
+     *
+     * @parameter default-value="${project.remotePluginRepositories}"
+     * @readonly
+     */
+    private List<RemoteRepository> remoteRepos;
+
+    /**
+     * @parameter
+     */
+    private File localRepo;
+
+    private AetherUtil aetherUtil;
+
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        aetherUtil = new AetherUtil(repoSystem, repoSession, remoteRepos,localRepo);
+        try {
+            Set<Artifact> featureArtifacts = new LinkedHashSet<Artifact>();
+            featureArtifacts.addAll(aetherUtil.resolveDependencies(MvnToAetherMapper.toAether(project.getDependencies()),
+                    new KarafFeaturesDependencyFilter()));
+            Set<Features> features = FeatureUtil.readFeatures(featureArtifacts);
+            features.addAll(FeatureUtil.findAllFeaturesRecursively(aetherUtil, features, FeatureUtil.featuresRepositoryToCoords(features)));
+            for(Features feature: features) {
+                getLog().info("Features Repos  discovered recursively: " + feature.getName());
+            }
+            Set<Artifact> artifacts = aetherUtil.resolveArtifacts(FeatureUtil.featuresToCoords(features));
+            artifacts.addAll(featureArtifacts);
+
+            for(Artifact artifact: artifacts) {
+                getLog().info("Artifacts to be installed: " + artifact.toString());
+            }
+            if(localRepo != null) {
+                aetherUtil.installArtifacts(artifacts);
+            }
+        } catch (Exception e) {
+            throw new MojoExecutionException("Failure: ", e);
+        }
+    }
+}
diff --git a/pom.xml b/pom.xml
index 9b61c38572c8131faa62f11fc429b33c8c16a325..e598fbcf302f4ce56f4727b8b2c22702b3fe66c4 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -1,13 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- vi: set et smarttab sw=4 tabstop=4: -->
-<!--
+<!-- vi: set et smarttab sw=4 tabstop=4: --><!--
  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
 
  This program and the accompanying materials are made available under the
  terms of the Eclipse Public License v1.0 which accompanies this distribution,
  and is available at http://www.eclipse.org/legal/epl-v10.html
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+--><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 
     <modelVersion>4.0.0</modelVersion>
 
@@ -30,7 +28,8 @@
         <module>features-parent</module>
         <module>features-test</module>
         <module>odlparent</module>
-    </modules>
+    <module>karaf-plugin</module>
+  </modules>
 
     <build>
         <plugins>
@@ -44,4 +43,4 @@
             </plugin>
         </plugins>
     </build>
-</project>
+</project>
\ No newline at end of file