You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by cs...@apache.org on 2013/09/30 10:05:37 UTC

svn commit: r1527477 - in /karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features: AbstractFeatureMojo.java AddToRepositoryMojo.java ExportFeatureMetaDataMojo.java

Author: cschneider
Date: Mon Sep 30 08:05:37 2013
New Revision: 1527477

URL: http://svn.apache.org/r1527477
Log:
KARAF-2491 Create extra karaf maven plugin command for meta data export and optionally eliminate duplicates

Added:
    karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/AbstractFeatureMojo.java   (with props)
    karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/ExportFeatureMetaDataMojo.java   (with props)
Modified:
    karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/AddToRepositoryMojo.java

Added: karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/AbstractFeatureMojo.java
URL: http://svn.apache.org/viewvc/karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/AbstractFeatureMojo.java?rev=1527477&view=auto
==============================================================================
--- karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/AbstractFeatureMojo.java (added)
+++ karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/AbstractFeatureMojo.java Mon Sep 30 08:05:37 2013
@@ -0,0 +1,271 @@
+/**
+ *
+ * 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.karaf.tooling.features;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.karaf.tooling.features.model.BundleRef;
+import org.apache.karaf.tooling.features.model.Feature;
+import org.apache.karaf.tooling.features.model.Repository;
+import org.apache.karaf.tooling.utils.MojoSupport;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.resolver.AbstractArtifactResolutionException;
+import org.apache.maven.plugin.MojoExecutionException;
+
+/**
+ * Common functionality for mojos that need to reolve features
+ */
+public abstract class AbstractFeatureMojo extends MojoSupport {
+
+    protected static final String KARAF_CORE_STANDARD_FEATURE_URL = "mvn:org.apache.karaf.features/standard/%s/xml/features";
+    protected static final String KARAF_CORE_ENTERPRISE_FEATURE_URL = "mvn:org.apache.karaf.features/enterprise/%s/xml/features";
+    /**
+     * @parameter
+     */
+    protected List<String> descriptors;
+    
+    protected Set<Artifact> descriptorArtifacts;
+    
+    /**
+     * @parameter
+     */
+    protected List<String> features;
+
+    /**
+     * the target karaf version used to resolve Karaf core features descriptors
+     *
+     * @parameter
+     */
+    protected String karafVersion;
+    /**
+     * @parameter
+     */
+    protected boolean addTransitiveFeatures = true;
+    /**
+     * @parameter
+     */
+    private boolean includeMvnBasedDescriptors = false;
+    /**
+     * @parameter
+     */
+    private boolean failOnArtifactResolutionError = true;
+    /**
+     * @parameter
+     */
+    private boolean resolveDefinedRepositoriesRecursively = true;
+    
+    /**
+     * @parameter
+     */
+    protected boolean skipNonMavenProtocols = true;
+
+    /**
+     * The start level exported when no explicit start level is set for a bundle
+     * @parameter 
+     */
+    private int defaultStartLevel = 80;
+
+    /**
+     * Internal counter for garbage collection
+     */
+    private int resolveCount = 0;
+
+    public AbstractFeatureMojo() {
+        super();
+        descriptorArtifacts = new HashSet<Artifact>();
+    }
+
+    protected void addFeatureRepo(String featureUrl) throws MojoExecutionException {
+        Artifact featureDescArtifact = resourceToArtifact(featureUrl, true);
+        if (featureDescArtifact == null) {
+            return;
+        }
+        try {
+            resolveArtifact(featureDescArtifact, remoteRepos);
+            descriptors.add(0, featureUrl);
+        } catch (Exception e) {
+            getLog().warn("Can't add " + featureUrl + " in the descriptors set");
+            getLog().debug(e);
+        }
+    }
+
+    protected void retrieveDescriptorsRecursively(String uri, Set<String> bundles, Map<String, Feature> featuresMap) {
+        // let's ensure a mvn: based url is sitting in the local repo before we try reading it
+        Artifact descriptor;
+        try {
+            descriptor = resourceToArtifact(uri, true);
+        } catch (MojoExecutionException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+        if (descriptor != null) {
+            resolveArtifact(descriptor, remoteRepos);
+            descriptorArtifacts.add(descriptor);
+        }
+        if (includeMvnBasedDescriptors) {
+            bundles.add(uri);
+        }
+        URI repoURI = URI.create(translateFromMaven(uri.replaceAll(" ", "%20")));
+        Repository repo = new Repository(repoURI, defaultStartLevel);
+        for (Feature f : repo.getFeatures()) {
+            featuresMap.put(f.getName() + "/" + f.getVersion(), f);
+        }
+        if (resolveDefinedRepositoriesRecursively) {
+            for (String r : repo.getDefinedRepositories()) {
+                retrieveDescriptorsRecursively(r, bundles, featuresMap);
+            }
+        }
+    }
+
+    /**
+     * Resolves and copies the given artifact to the repository path.
+     * Prefers to resolve using the repository of the artifact if present.
+     * 
+     * @param artifact
+     * @param remoteRepos
+     */
+    @SuppressWarnings("deprecation")
+    protected void resolveArtifact(Artifact artifact, List<ArtifactRepository> remoteRepos) {
+        try {
+            List<ArtifactRepository> usedRemoteRepos = artifact.getRepository() != null ? 
+                    Collections.singletonList(artifact.getRepository())
+                    : remoteRepos;
+            resolver.resolve(artifact, usedRemoteRepos, localRepo);
+        } catch (AbstractArtifactResolutionException e) {
+            if (failOnArtifactResolutionError) {
+                throw new RuntimeException("Can't resolve bundle " + artifact, e);
+            }
+            getLog().error("Can't resolve bundle " + artifact, e);
+        }
+    }
+
+
+    /**
+     * Populate the features by traversing the listed features and their
+     * dependencies if transitive is true
+     *  
+     * @param featureNames
+     * @param features
+     * @param featuresMap
+     * @param transitive
+     */
+    protected void addFeatures(List<String> featureNames, Set<Feature> features, Map<String, Feature> featuresMap, boolean transitive) {
+        for (String feature : featureNames) {
+            Feature f = getMatchingFeature(featuresMap, feature);
+            features.add(f);
+            if (transitive) {
+            	addFeatures(f.getDependencies(), features, featuresMap, true);
+            }
+        }
+    }
+
+    private Feature getMatchingFeature(Map<String, Feature> featuresMap, String feature) {
+        // feature could be only the name or name/version
+        int delimIndex = feature.indexOf('/');
+        String version = null;
+        if (delimIndex > 0) {
+            version = feature.substring(delimIndex + 1);
+            feature = feature.substring(0, delimIndex);
+        }
+        Feature f = null;
+        if (version != null) {
+            // looking for a specific feature with name and version
+            f = featuresMap.get(feature + "/" + version);
+        } else {
+            // looking for the first feature name (whatever the version is)
+            for (String key : featuresMap.keySet()) {
+                String[] nameVersion = key.split("/");
+                if (feature.equals(nameVersion[0])) {
+                    f = featuresMap.get(key);
+                    break;
+                }
+            }
+        }
+        if (f == null) {
+            throw new IllegalArgumentException("Unable to find the feature '" + feature + "'");
+        }
+        return f;
+    }
+
+    protected Set<Feature> resolveFeatures() throws MojoExecutionException {
+        Set<Feature> featuresSet = new HashSet<Feature>();
+        if (karafVersion == null) {
+            Package p = Package.getPackage("org.apache.karaf.tooling.features");
+            karafVersion = p.getImplementationVersion();
+        }
+    
+        addFeatureRepo(String.format(KARAF_CORE_ENTERPRISE_FEATURE_URL, karafVersion));
+        addFeatureRepo(String.format(KARAF_CORE_STANDARD_FEATURE_URL, karafVersion));
+        addFeatureRepo(String.format(KARAF_CORE_STANDARD_FEATURE_URL, karafVersion));
+    
+        try {
+            Set<String> artifactsToCopy = new HashSet<String>();
+            Map<String, Feature> featuresMap = new HashMap<String, Feature>();
+            for (String uri : descriptors) {
+                retrieveDescriptorsRecursively(uri, artifactsToCopy, featuresMap);
+            }
+    
+            // no features specified, handle all of them
+            if (features == null) {
+                features = new ArrayList<String>(featuresMap.keySet());
+            }
+            
+            addFeatures(features, featuresSet, featuresMap, addTransitiveFeatures);
+    
+            getLog().info("Base repo: " + localRepo.getUrl());
+            for (Feature feature : featuresSet) {
+                resolveBundles(feature.getBundles());
+            }            
+        } catch (Exception e) {
+            throw new MojoExecutionException("Error populating repository", e);
+        }
+        return featuresSet;
+    }
+    
+    private void resolveBundles(List<BundleRef> bundleRefs) throws MojoExecutionException {
+        for (BundleRef bundle : bundleRefs) {
+            Artifact artifact = resourceToArtifact(bundle.getUrl(), skipNonMavenProtocols);
+            if (artifact != null) {
+                // Store artifact in bundle for later export
+                bundle.setArtifact(artifact);
+                resolveArtifact(artifact, remoteRepos);
+            }
+            checkDoGarbageCollect();
+        }
+    }
+    
+    /**
+     * Maven ArtifactResolver leaves file handles around so need to clean up
+     * or we will run out of file descriptors
+     */
+    protected void checkDoGarbageCollect() {
+        if (this.resolveCount++ % 100 == 0) {
+            System.gc();
+            System.runFinalization();
+        }
+    }
+
+
+}
\ No newline at end of file

Propchange: karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/AbstractFeatureMojo.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/AddToRepositoryMojo.java
URL: http://svn.apache.org/viewvc/karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/AddToRepositoryMojo.java?rev=1527477&r1=1527476&r2=1527477&view=diff
==============================================================================
--- karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/AddToRepositoryMojo.java (original)
+++ karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/AddToRepositoryMojo.java Mon Sep 30 08:05:37 2013
@@ -18,23 +18,12 @@
 package org.apache.karaf.tooling.features;
 
 import java.io.File;
-import java.io.FileOutputStream;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 
 import org.apache.karaf.tooling.features.model.BundleRef;
 import org.apache.karaf.tooling.features.model.Feature;
-import org.apache.karaf.tooling.features.model.Repository;
-import org.apache.karaf.tooling.utils.MojoSupport;
 import org.apache.maven.artifact.Artifact;
-import org.apache.maven.artifact.repository.ArtifactRepository;
-import org.apache.maven.artifact.resolver.AbstractArtifactResolutionException;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
 
@@ -48,257 +37,54 @@ import org.apache.maven.plugin.MojoFailu
  * @inheritByDefault true
  * @description Add the features to the repository
  */
-public class AddToRepositoryMojo extends MojoSupport {
-
-    private final static String KARAF_CORE_STANDARD_FEATURE_URL =
-        "mvn:org.apache.karaf.features/standard/%s/xml/features";
-    private final static String KARAF_CORE_ENTERPRISE_FEATURE_URL =
-        "mvn:org.apache.karaf.features/enterprise/%s/xml/features";
-
-    /**
-     * @parameter
-     */
-    private List<String> descriptors;
-
-    /**
-     * @parameter
-     */
-    private List<String> features;
+public class AddToRepositoryMojo extends AbstractFeatureMojo {
 
     /**
      * @parameter expression="${project.build.directory}/features-repo"
      */
-    private File repository;
-
-    /**
-     * the target karaf version used to resolve Karaf core features descriptors
-     *
-     * @parameter
-     */
-    private String karafVersion;
+    protected File repository;
 
     /**
-     * @parameter
-     */
-    private boolean includeMvnBasedDescriptors = false;
-
-    /**
-     * @parameter
-     */
-    private List<CopyFileBasedDescriptor> copyFileBasedDescriptors;
-
-    /**
-     * @parameter
-     */
-    private boolean skipNonMavenProtocols = true;
-
-    /**
-     * @parameter
-     */
-    private boolean failOnArtifactResolutionError = true;
-
-    /**
-     * @parameter
-     */
-    private boolean resolveDefinedRepositoriesRecursively = true;
-
-    /**
-     * @parameter
-     */
-    private boolean addTransitiveFeatures = true;
-    
-    /**
      * If set to true the exported bundles will be directly copied into the repository dir.
      * If set to false the default maven repository layout will be used
      * @parameter
      */
     private boolean flatRepoLayout;
-    
+
     /**
-     * If set to true then the resolved features and bundles will be exported into a single xml file.
-     * This is intended to allow further build scripts to create configs for OSGi containers
      * @parameter
      */
-    private boolean exportMetaData;
-    
-    /**
-     * Name of the file for exported feature meta data
-     * 
-     * @parameter expression="${project.build.directory}/features.xml"
-     */
-    private File metaDataFile;
-    
-    /**
-     * The start level exported when no explicit start level is set for a bundle
-     * @parameter 
-     */
-    private int defaultStartLevel = 80;
-    
-    /**
-     * Internal counter for garbage collection
-     */
-    private int resolveCount = 0;
+    protected List<CopyFileBasedDescriptor> copyFileBasedDescriptors;
 
     public void execute() throws MojoExecutionException, MojoFailureException {
-        if (karafVersion == null) {
-            Package p = Package.getPackage("org.apache.karaf.tooling.features");
-            karafVersion = p.getImplementationVersion();
+        Set<Feature> featuresSet = resolveFeatures();
+        
+        for (Artifact descriptor : descriptorArtifacts) {
+            copy(descriptor, repository);
         }
 
-        addFeatureRepo(String.format(KARAF_CORE_ENTERPRISE_FEATURE_URL, karafVersion));
-        addFeatureRepo(String.format(KARAF_CORE_STANDARD_FEATURE_URL, karafVersion));
-        addFeatureRepo(String.format(KARAF_CORE_STANDARD_FEATURE_URL, karafVersion));
-
-        try {
-            Set<String> artifactsToCopy = new HashSet<String>();
-            Map<String, Feature> featuresMap = new HashMap<String, Feature>();
-            for (String uri : descriptors) {
-                retrieveDescriptorsRecursively(uri, artifactsToCopy, featuresMap);
-            }
-
-            // no features specified, handle all of them
-            if (features == null) {
-                features = new ArrayList<String>(featuresMap.keySet());
-            }
-            
-            Set<Feature> featuresSet = new HashSet<Feature>();
-            
-            addFeatures(features, featuresSet, featuresMap, addTransitiveFeatures);
-
-            getLog().info("Base repo: " + localRepo.getUrl());
-            for (Feature feature : featuresSet) {
-            	copyBundlesToDestRepository(feature.getBundles());
-            	copyArtifactsToDestRepository(feature.getConfigFiles());
-            }
-            
-            copyFileBasedDescriptorsToDestRepository();
-            
-            if (exportMetaData) {
-            	exportMetaData(featuresSet, metaDataFile);
-            }
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error populating repository", e);
-        }
-    }
-
-    private void exportMetaData(Set<Feature> featuresSet, File metaDataFile) {
-        try {
-            FeatureMetaDataExporter exporter = new FeatureMetaDataExporter(new FileOutputStream(metaDataFile));
-            for (Feature feature : featuresSet) {
-                exporter.writeFeature(feature);
-            }
-            exporter.close();
-        } catch (Exception e) {
-            throw new RuntimeException("Error writing feature meta data to " + metaDataFile + ": " + e.getMessage(), e);
-        }
-    }
-
-    private void addFeatureRepo(String featureUrl) throws MojoExecutionException {
-        Artifact featureDescArtifact = resourceToArtifact(featureUrl, true);
-        if (featureDescArtifact == null) {
-            return;
-        }
-        try {
-            resolveAndCopyArtifact(featureDescArtifact, remoteRepos);
-            descriptors.add(0, featureUrl);
-        } catch (Exception e) {
-            getLog().warn("Can't add " + featureUrl + " in the descriptors set");
-            getLog().debug(e);
-        }
-    }
-
-    private void retrieveDescriptorsRecursively(String uri, Set<String> bundles, Map<String, Feature> featuresMap) {
-        // let's ensure a mvn: based url is sitting in the local repo before we try reading it
-        Artifact descriptor;
-        try {
-            descriptor = resourceToArtifact(uri, true);
-        } catch (MojoExecutionException e) {
-            throw new RuntimeException(e.getMessage(), e);
-        }
-        if (descriptor != null) {
-            resolveAndCopyArtifact(descriptor, remoteRepos);
-        }
-        if (includeMvnBasedDescriptors) {
-            bundles.add(uri);
-        }
-        URI repoURI = URI.create(translateFromMaven(uri.replaceAll(" ", "%20")));
-        Repository repo = new Repository(repoURI, defaultStartLevel);
-        for (Feature f : repo.getFeatures()) {
-            featuresMap.put(f.getName() + "/" + f.getVersion(), f);
-        }
-        if (resolveDefinedRepositoriesRecursively) {
-            for (String r : repo.getDefinedRepositories()) {
-                retrieveDescriptorsRecursively(r, bundles, featuresMap);
-            }
-        }
+        for (Feature feature : featuresSet) {
+            copyBundlesToDestRepository(feature.getBundles());
+            copyArtifactsToDestRepository(feature.getConfigFiles());
+        }
+        
+        copyFileBasedDescriptorsToDestRepository();
+        
     }
 
     private void copyBundlesToDestRepository(List<BundleRef> bundleRefs) throws MojoExecutionException {
         for (BundleRef bundle : bundleRefs) {
-            Artifact artifact = resourceToArtifact(bundle.getUrl(), skipNonMavenProtocols);
-            if (artifact != null) {
-                // Store artifact in bundle for later export
-                bundle.setArtifact(artifact);
-                resolveAndCopyArtifact(artifact, remoteRepos);
-            }
-            checkDoGarbageCollect();
-        }
-    }
-
-    private void copyArtifactsToDestRepository(List<String> list) throws MojoExecutionException {
-        for (String bundle : list) {
-            Artifact artifact = resourceToArtifact(bundle, skipNonMavenProtocols);
+            Artifact artifact = bundle.getArtifact();
             if (artifact != null) {
-                resolveAndCopyArtifact(artifact, remoteRepos);
-            }
-            checkDoGarbageCollect();
-        }
-    }
-    
-    /**
-     * Maven ArtifactResolver leaves file handles around so need to clean up
-     * or we will run out of file descriptors
-     */
-    private void checkDoGarbageCollect() {
-        if (this.resolveCount++ % 100 == 0) {
-            System.gc();
-            System.runFinalization();
-        }
-    }
-
-    private void copyFileBasedDescriptorsToDestRepository() {
-        if (copyFileBasedDescriptors != null) {
-            for (CopyFileBasedDescriptor fileBasedDescriptor : copyFileBasedDescriptors) {
-                File destDir = new File(repository, fileBasedDescriptor.getTargetDirectory());
-                File destFile = new File(destDir, fileBasedDescriptor.getTargetFileName());
-                copy(fileBasedDescriptor.getSourceFile(), destFile);
+                copy(artifact, repository);
             }
         }
     }
 
-    /**
-     * Resolves and copies the given artifact to the repository path.
-     * Prefers to resolve using the repository of the artifact if present.
-     * 
-     * @param artifact
-     * @param remoteRepos
-     */
-    @SuppressWarnings("deprecation")
-    private void resolveAndCopyArtifact(Artifact artifact, List<ArtifactRepository> remoteRepos) {
-        try {
-            getLog().info("Copying artifact: " + artifact);
-            List<ArtifactRepository> usedRemoteRepos = artifact.getRepository() != null ? 
-                    Collections.singletonList(artifact.getRepository())
-                    : remoteRepos;
-            resolver.resolve(artifact, usedRemoteRepos, localRepo);
-            File destFile = new File(repository, getRelativePath(artifact));
-            copy(artifact.getFile(), destFile);
-        } catch (AbstractArtifactResolutionException e) {
-            if (failOnArtifactResolutionError) {
-                throw new RuntimeException("Can't resolve bundle " + artifact, e);
-            }
-            getLog().error("Can't resolve bundle " + artifact, e);
-        }
+    protected void copy(Artifact artifact, File destRepository) {
+        getLog().info("Copying artifact: " + artifact);
+        File destFile = new File(destRepository, getRelativePath(artifact));
+        copy(artifact.getFile(), destFile);
     }
 
     /**
@@ -308,61 +94,30 @@ public class AddToRepositoryMojo extends
      * @return relative path of the given artifact in a default repo layout
      */
     private String getRelativePath(Artifact artifact) {
-    	String dir = (this.flatRepoLayout) ? "" : MavenUtil.getDir(artifact);
+        String dir = (this.flatRepoLayout) ? "" : MavenUtil.getDir(artifact);
         String name = MavenUtil.getFileName(artifact);
         return dir + name;
     }
 
-
-
-
-
-    /**
-     * Populate the features by traversing the listed features and their
-     * dependencies if transitive is true
-     *  
-     * @param featureNames
-     * @param features
-     * @param featuresMap
-     * @param transitive
-     */
-    private void addFeatures(List<String> featureNames, Set<Feature> features,
-            Map<String, Feature> featuresMap, boolean transitive) {
-        for (String feature : featureNames) {
-            Feature f = getMatchingFeature(featuresMap, feature);
-            features.add(f);
-            if (transitive) {
-            	addFeatures(f.getDependencies(), features, featuresMap, true);
+    private void copyArtifactsToDestRepository(List<String> list) throws MojoExecutionException {
+        for (String bundle : list) {
+            Artifact artifact = resourceToArtifact(bundle, skipNonMavenProtocols);
+            if (artifact != null) {
+                resolveArtifact(artifact, remoteRepos);
+                copy(artifact, repository);
             }
+            checkDoGarbageCollect();
         }
     }
-
-    private Feature getMatchingFeature(Map<String, Feature> featuresMap, String feature) {
-        // feature could be only the name or name/version
-        int delimIndex = feature.indexOf('/');
-        String version = null;
-        if (delimIndex > 0) {
-            version = feature.substring(delimIndex + 1);
-            feature = feature.substring(0, delimIndex);
-        }
-        Feature f = null;
-        if (version != null) {
-            // looking for a specific feature with name and version
-            f = featuresMap.get(feature + "/" + version);
-        } else {
-            // looking for the first feature name (whatever the version is)
-            for (String key : featuresMap.keySet()) {
-                String[] nameVersion = key.split("/");
-                if (feature.equals(nameVersion[0])) {
-                    f = featuresMap.get(key);
-                    break;
-                }
+    
+    private void copyFileBasedDescriptorsToDestRepository() {
+        if (copyFileBasedDescriptors != null) {
+            for (CopyFileBasedDescriptor fileBasedDescriptor : copyFileBasedDescriptors) {
+                File destDir = new File(repository, fileBasedDescriptor.getTargetDirectory());
+                File destFile = new File(destDir, fileBasedDescriptor.getTargetFileName());
+                copy(fileBasedDescriptor.getSourceFile(), destFile);
             }
         }
-        if (f == null) {
-            throw new IllegalArgumentException("Unable to find the feature '" + feature + "'");
-        }
-        return f;
     }
 
 }

Added: karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/ExportFeatureMetaDataMojo.java
URL: http://svn.apache.org/viewvc/karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/ExportFeatureMetaDataMojo.java?rev=1527477&view=auto
==============================================================================
--- karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/ExportFeatureMetaDataMojo.java (added)
+++ karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/ExportFeatureMetaDataMojo.java Mon Sep 30 08:05:37 2013
@@ -0,0 +1,125 @@
+/**
+ *
+ * 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.karaf.tooling.features;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.karaf.tooling.features.model.BundleRef;
+import org.apache.karaf.tooling.features.model.Feature;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.osgi.framework.Version;
+
+/**
+ * Export meta data about features
+ *
+ * @goal features-export-meta-data
+ * @phase compile
+ * @execute phase="compile"
+ * @requiresDependencyResolution runtime
+ * @inheritByDefault true
+ * @description Export meta data about features
+ */
+public class ExportFeatureMetaDataMojo extends AbstractFeatureMojo {
+    
+    /**
+     * If set to true then all bundles will be merged into one combined feature.
+     * In this case duplicates will be eliminated
+     * 
+     * @parameter
+     */
+    private boolean mergedFeature;
+    
+    /**
+     * If set to true then for each bundle symbolic name only the highest version will be used
+     * @parameter
+     */
+    protected boolean oneVersion;
+
+    /**
+     * Name of the file for exported feature meta data
+     * 
+     * @parameter expression="${project.build.directory}/features.xml"
+     */
+    private File metaDataFile;
+    
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        Set<Feature> featuresSet = resolveFeatures();
+        if (mergedFeature) {
+            Feature feature = oneVersion ? mergeFeatureOneVersion(featuresSet) : mergeFeature(featuresSet);
+            featuresSet = new HashSet<Feature>();
+            featuresSet.add(feature);
+        }
+        try {
+            metaDataFile.getParentFile().mkdirs();
+            FeatureMetaDataExporter exporter = new FeatureMetaDataExporter(new FileOutputStream(metaDataFile));
+            for (Feature feature : featuresSet) {
+                exporter.writeFeature(feature);
+            }
+            exporter.close();
+        } catch (Exception e) {
+            throw new RuntimeException("Error writing feature meta data to " + metaDataFile + ": " + e.getMessage(), e);
+        }
+    }
+
+    private Feature mergeFeature(Set<Feature> featuresSet) {
+        Feature merged = new Feature("merged");
+        Set<String> bundleIds = new HashSet<String>();
+        for (Feature feature : featuresSet) {
+            for (BundleRef bundle : feature.getBundles()) {
+                bundle.readManifest();
+                String bundleId = bundle.getBundleSymbolicName() + ":" + bundle.getBundleVersion();
+                if (!bundleIds.contains(bundleId)) {
+                    bundleIds.add(bundleId);
+                    merged.getBundles().add(bundle);
+                }
+            }
+        }
+        return merged;
+    }
+    
+    private Feature mergeFeatureOneVersion(Set<Feature> featuresSet) {
+        Feature merged = new Feature("merged");
+        Map<String, BundleRef> bundleVersions = new HashMap<String, BundleRef>();
+        for (Feature feature : featuresSet) {
+            for (BundleRef bundle : feature.getBundles()) {
+                bundle.readManifest();
+                BundleRef existingBundle = bundleVersions.get(bundle.getBundleSymbolicName());
+                if (existingBundle != null) {
+                    Version existingVersion = new Version(existingBundle.getBundleVersion());
+                    Version newVersion = new Version(bundle.getBundleVersion());
+                    if (newVersion.compareTo(existingVersion) > 0) {
+                        bundleVersions.put(bundle.getBundleSymbolicName(), bundle);
+                    }
+                } else {
+                    bundleVersions.put(bundle.getBundleSymbolicName(), bundle);
+                }
+            }
+        }
+        for (BundleRef bundle : bundleVersions.values()) {
+            merged.getBundles().add(bundle);
+        }
+        return merged;
+    }
+
+}

Propchange: karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/ExportFeatureMetaDataMojo.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain