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/08/09 19:20:51 UTC

svn commit: r1512407 - in /karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features: AddToRepositoryMojo.java FeatureMetaDataExporter.java MavenUtil.java model/BundleRef.java model/Feature.java model/Repository.java

Author: cschneider
Date: Fri Aug  9 17:20:50 2013
New Revision: 1512407

URL: http://svn.apache.org/r1512407
Log:
KARAF-2439 Allow to export meta data for bundles

Added:
    karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/FeatureMetaDataExporter.java   (with props)
    karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/BundleRef.java   (with props)
Modified:
    karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/AddToRepositoryMojo.java
    karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/MavenUtil.java
    karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/Feature.java
    karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/Repository.java

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=1512407&r1=1512406&r2=1512407&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 Fri Aug  9 17:20:50 2013
@@ -18,6 +18,7 @@
 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;
@@ -27,6 +28,7 @@ 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;
@@ -104,6 +106,32 @@ public class AddToRepositoryMojo extends
      * @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;
+    
+    /**
+     * Internal counter for garbage collection
+     */
+    private int resolveCount = 0;
 
     public void execute() throws MojoExecutionException, MojoFailureException {
         if (karafVersion == null) {
@@ -116,64 +144,46 @@ public class AddToRepositoryMojo extends
         addFeatureRepo(String.format(KARAF_CORE_STANDARD_FEATURE_URL, karafVersion));
 
         try {
-            Set<String> bundles = new HashSet<String>();
+            Set<String> artifactsToCopy = new HashSet<String>();
             Map<String, Feature> featuresMap = new HashMap<String, Feature>();
             for (String uri : descriptors) {
-                retrieveDescriptorsRecursively(uri, bundles, featuresMap);
+                retrieveDescriptorsRecursively(uri, artifactsToCopy, featuresMap);
             }
 
             // no features specified, handle all of them
             if (features == null) {
                 features = new ArrayList<String>(featuresMap.keySet());
             }
-
-            Set<String> featuresBundles = new HashSet<String>();
-            Set<String> transitiveFeatures = new HashSet<String>();
-            addFeatures(features, featuresBundles, transitiveFeatures, featuresMap);
-
-            // add the bundles of the configured features to the bundles list
-            bundles.addAll(featuresBundles);
-
-            // if transitive features are enabled we add the contents of those
-            // features to the bundles list
-            if (addTransitiveFeatures) {
-                for (String feature : transitiveFeatures) {
-                    // transitiveFeatures contains name/version
-                    Feature f = featuresMap.get(feature);
-                    getLog().info("Adding contents of transitive feature: " + feature);
-                    bundles.addAll(f.getBundles());
-                    // Treat the config files as bundles, since it is only copying
-                    bundles.addAll(f.getConfigFiles());
-                }
-            }
+            
+            Set<Feature> featuresSet = new HashSet<Feature>();
+            
+            addFeatures(features, featuresSet, featuresMap, addTransitiveFeatures);
 
             getLog().info("Base repo: " + localRepo.getUrl());
-            int currentBundle = 0;
-            for (String bundle : bundles) {
-                Artifact artifact = resourceToArtifact(bundle, skipNonMavenProtocols);
-
-                // Maven ArtifactResolver leaves file handles around so need to clean up
-                // or we will run out of file descriptors
-                if (currentBundle++ % 100 == 0) {
-                    System.gc();
-                    System.runFinalization();
-                }
-
-                if (artifact == null) {
-                    continue;
-                }
-                resolveAndCopyArtifact(artifact, remoteRepos);
+            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);
+        }
+    }
 
-            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);
-                }
+    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 MojoExecutionException("Error populating repository", e);
+            throw new RuntimeException("Error writing feature meta data to " + metaDataFile + ": " + e.getMessage(), e);
         }
     }
 
@@ -216,6 +226,49 @@ public class AddToRepositoryMojo extends
         }
     }
 
+    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);
+            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);
+            }
+        }
+    }
+
     /**
      * Resolves and copies the given artifact to the repository path.
      * Prefers to resolve using the repository of the artifact if present.
@@ -248,54 +301,61 @@ public class AddToRepositoryMojo extends
      * @return relative path of the given artifact in a default repo layout
      */
     private String getRelativePath(Artifact artifact) {
-        String dir = artifact.getGroupId().replace('.', '/') + "/" + artifact.getArtifactId() + "/" + artifact.getBaseVersion() + "/";
-        String name = artifact.getArtifactId() + "-" + artifact.getBaseVersion()
-            + (artifact.getClassifier() != null ? "-" + artifact.getClassifier() : "") + "." + artifact.getType();
+    	String dir = (this.flatRepoLayout) ? "" : MavenUtil.getDir(artifact);
+        String name = MavenUtil.getFileName(artifact);
         return dir + name;
     }
 
-    private void addFeatures(List<String> features, Set<String> featuresBundles, Set<String> transitiveFeatures,
-            Map<String, Feature> featuresMap) {
-        for (String feature : features) {
-
-            // 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 + "'");
+
+
+
+
+    /**
+     * 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);
             }
-            // only add the feature to transitives if it is not
-            // listed in the features list defined by the config
-            if (!this.features.contains(f.getName() + "/" + f.getVersion())) {
-                transitiveFeatures.add(f.getName() + "/" + f.getVersion());
-            } else {
-                // add the bundles of the feature to the bundle set
-                getLog().info("Adding contents for feature: " + f.getName() + "/" + f.getVersion());
-                featuresBundles.addAll(f.getBundles());
-                // Treat the config files as bundles, since it is only copying
-                featuresBundles.addAll(f.getConfigFiles());
+        }
+    }
+
+    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;
+                }
             }
-            addFeatures(f.getDependencies(), featuresBundles, transitiveFeatures, featuresMap);
         }
+        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/FeatureMetaDataExporter.java
URL: http://svn.apache.org/viewvc/karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/FeatureMetaDataExporter.java?rev=1512407&view=auto
==============================================================================
--- karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/FeatureMetaDataExporter.java (added)
+++ karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/FeatureMetaDataExporter.java Fri Aug  9 17:20:50 2013
@@ -0,0 +1,89 @@
+/**
+ *
+ * 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.OutputStream;
+
+import javax.xml.stream.XMLEventFactory;
+import javax.xml.stream.XMLEventWriter;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.StartDocument;
+
+import org.apache.karaf.tooling.features.model.BundleRef;
+import org.apache.karaf.tooling.features.model.Feature;
+
+/**
+ * Export feature meta data as xml into a stream
+ */
+public class FeatureMetaDataExporter {
+
+    private XMLEventWriter writer;
+    private XMLEventFactory factory;
+
+    public FeatureMetaDataExporter(OutputStream out) throws XMLStreamException {
+        XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
+        writer = outputFactory.createXMLEventWriter(out);
+        factory = XMLEventFactory.newInstance();
+        StartDocument startDocument = factory.createStartDocument();
+        writer.add(startDocument);
+        newLine();
+        writer.add(factory.createStartElement("", "", "bundles"));
+        newLine();
+    }
+
+    public void writeFeature(Feature feature) throws XMLStreamException {
+        writer.add(factory.createStartElement("", "", "feature"));
+        writer.add(factory.createAttribute("name", feature.getName()));
+        if (feature.getVersion() != null) {
+            writer.add(factory.createAttribute("version", feature.getVersion()));
+        }
+        newLine();
+        for (BundleRef bundle : feature.getBundles()) {
+            writer.add(factory.createStartElement("", "", "bundle"));
+            if (bundle.getStartLevel() != null) {
+                writer.add(factory.createAttribute("start-level", bundle.getStartLevel().toString()));
+            }
+            if (bundle.getArtifact()!=null) {
+                String name = MavenUtil.getFileName(bundle.getArtifact());
+                writer.add(factory.createAttribute("name", name));
+            }
+            
+            writer.add(factory.createCharacters(bundle.getUrl()));
+            endElement("bundle");
+        }
+        endElement("feature");
+    }
+
+    public void close() throws XMLStreamException {
+        endElement("bundles");
+        writer.add(factory.createEndDocument());
+        writer.close();
+    }
+    
+
+    private void endElement(String elementName) throws XMLStreamException {
+        writer.add(factory.createEndElement("", "", elementName));
+        newLine();
+    }
+
+    private void newLine() throws XMLStreamException {
+        writer.add(factory.createCharacters("\r\n"));
+    }
+
+}

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

Modified: karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/MavenUtil.java
URL: http://svn.apache.org/viewvc/karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/MavenUtil.java?rev=1512407&r1=1512406&r2=1512407&view=diff
==============================================================================
--- karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/MavenUtil.java (original)
+++ karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/MavenUtil.java Fri Aug  9 17:20:50 2013
@@ -216,5 +216,15 @@ public class MavenUtil {
         Writer writer = new FileWriter(target);
         metadataWriter.write(writer, metadata);
     }
+    
+    static String getFileName(Artifact artifact) {
+        String name = artifact.getArtifactId() + "-" + artifact.getBaseVersion()
+            + (artifact.getClassifier() != null ? "-" + artifact.getClassifier() : "") + "." + artifact.getType();
+        return name;
+    }
+    
+    static String getDir(Artifact artifact) {
+        return artifact.getGroupId().replace('.', '/') + "/" + artifact.getArtifactId() + "/" + artifact.getBaseVersion() + "/";
+    }
 
 }

Added: karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/BundleRef.java
URL: http://svn.apache.org/viewvc/karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/BundleRef.java?rev=1512407&view=auto
==============================================================================
--- karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/BundleRef.java (added)
+++ karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/BundleRef.java Fri Aug  9 17:20:50 2013
@@ -0,0 +1,49 @@
+/**
+ *
+ * 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.model;
+
+import org.apache.maven.artifact.Artifact;
+
+public class BundleRef {
+    String url;
+    Integer startLevel;
+    Artifact artifact;
+
+    public BundleRef(String url, Integer startLevel) {
+        super();
+        this.url = url;
+        this.startLevel = startLevel;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public Integer getStartLevel() {
+        return startLevel;
+    }
+
+    public Artifact getArtifact() {
+        return artifact;
+    }
+
+    public void setArtifact(Artifact artifact) {
+        this.artifact = artifact;
+    }
+
+}

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

Modified: karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/Feature.java
URL: http://svn.apache.org/viewvc/karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/Feature.java?rev=1512407&r1=1512406&r2=1512407&view=diff
==============================================================================
--- karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/Feature.java (original)
+++ karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/Feature.java Fri Aug  9 17:20:50 2013
@@ -27,7 +27,7 @@ public class Feature {
     private String name;
     private String version;
     private List<String> dependencies = new ArrayList<String>();
-    private List<String> bundles = new ArrayList<String>();
+    private List<BundleRef> bundles = new ArrayList<BundleRef>();
     private Map<String, Map<String, String>> configs = new HashMap<String, Map<String, String>>();
     private List<String> configFiles = new ArrayList<String>();
 
@@ -51,7 +51,7 @@ public class Feature {
         return dependencies;
     }
 
-    public List<String> getBundles() {
+    public List<BundleRef> getBundles() {
         return bundles;
     }
 
@@ -67,7 +67,7 @@ public class Feature {
         dependencies.add(dependency);
     }
 
-    public void addBundle(String bundle) {
+    public void addBundle(BundleRef bundle) {
         bundles.add(bundle);
     }
 

Modified: karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/Repository.java
URL: http://svn.apache.org/viewvc/karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/Repository.java?rev=1512407&r1=1512406&r2=1512407&view=diff
==============================================================================
--- karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/Repository.java (original)
+++ karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/Repository.java Fri Aug  9 17:20:50 2013
@@ -121,7 +121,13 @@ public class Repository {
                 NodeList bundleNodes = e.getElementsByTagName("bundle");
                 for (int j = 0; j < bundleNodes.getLength(); j++) {
                     Element b = (Element) bundleNodes.item(j);
-                    f.addBundle(b.getTextContent());
+                    Integer startLevel;
+                    try {
+                        startLevel = Integer.parseInt(b.getAttribute("start-level"));
+                    } catch (Exception e1) {
+                        startLevel = null;
+                    }
+                    f.addBundle(new BundleRef(b.getTextContent(), startLevel));
                 }
                 features.add(f);
             }