Author: hibou
Date: Sun Jan  5 10:41:19 2014
New Revision: 1555479

URL: http://svn.apache.org/r1555479
Log:
add support for source artifacts in buildobr task

Added:
    ant/ivy/core/trunk/test/java/org/apache/ivy/osgi/obr/OBRXMLWriterTest.java  
 (with props)
Modified:
    ant/ivy/core/trunk/CHANGES.txt
    ant/ivy/core/trunk/doc/use/buildobr.html
    ant/ivy/core/trunk/src/java/org/apache/ivy/ant/BuildOBRTask.java
    ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/obr/xml/OBRXMLWriter.java
    
ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/repo/AbstractFSManifestIterable.java
    
ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/repo/ArtifactReportManifestIterable.java
    
ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/repo/ManifestAndLocation.java
    
ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/repo/ResolverManifestIterable.java

Modified: ant/ivy/core/trunk/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/ant/ivy/core/trunk/CHANGES.txt?rev=1555479&r1=1555478&r2=1555479&view=diff
==============================================================================
--- ant/ivy/core/trunk/CHANGES.txt (original)
+++ ant/ivy/core/trunk/CHANGES.txt Sun Jan  5 10:41:19 2014
@@ -158,6 +158,7 @@ for detailed view of each issue, please 
 - IMPROVEMENT: add support for source URI from OBR repositories
 - IMPROVEMENT: Also copy original metadata artifact (e.g. POM) on ivy:install 
(IVY-1431) (Thanks to Erwin Tratar)
 - IMPROVEMENT: useOrigin will do avoid copy with url resolvers configured with 
a 'file:/' URL
+- IMPROVEMENT: add support for source artifacts in buildobr task
 
 - FIX: In IvyDE, Ivy fails to parse ivy-settings.xml file if it contains <pgp> 
element (thanks to Gregory Amerson) (IVY-1441)
 - FIX: ParseException when "Bundle-Description" is present in OSGi MANIFEST.MF 
(IVY-1438)

Modified: ant/ivy/core/trunk/doc/use/buildobr.html
URL: 
http://svn.apache.org/viewvc/ant/ivy/core/trunk/doc/use/buildobr.html?rev=1555479&r1=1555478&r2=1555479&view=diff
==============================================================================
--- ant/ivy/core/trunk/doc/use/buildobr.html (original)
+++ ant/ivy/core/trunk/doc/use/buildobr.html Sun Jan  5 10:41:19 2014
@@ -50,6 +50,7 @@ NB: among every listed files or artifact
     <tr><td>resolverName</td><td>the name of the resolver from which the jars 
should be to gathered</td><td>No</td></tr>
     <tr><td>cacheName</td><td>the name of the cache from which the jars should 
be to gathered</td><td>No</td></tr>
     <tr><td>baseDir</td><td>the folder into which the jars should be gather 
recursively</td><td>No</td></tr>
+    <tr><td>sourceType</td><td>if used as a post resolve task, 'sourceType' 
define the type of artifacts which should be considered as source artifacts 
(defaults to 'source,source,src')</td><td>No</td></tr>
     <tr><td>encoding</td><td>The encoding of the resulting xml 
file</td><td>No. Defaults to <tt>UTF-8</tt></td></tr>
     <tr><td>indent</td><td>Specify if the xml result file should be 
indented</td><td>No. Defaults to <tt>true</tt></td></tr>
     <tr><td>quiet</td><td>Log as debug rather than warning the rejected jars 
as they are illformed</td><td>No. Defaults to <tt>false</tt></td></tr>

Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/ant/BuildOBRTask.java
URL: 
http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/ant/BuildOBRTask.java?rev=1555479&r1=1555478&r2=1555479&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/ant/BuildOBRTask.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/ant/BuildOBRTask.java Sun Jan  5 
10:41:19 2014
@@ -23,7 +23,8 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.text.ParseException;
-import java.util.Iterator;
+import java.util.Arrays;
+import java.util.List;
 
 import javax.xml.transform.TransformerConfigurationException;
 
@@ -60,6 +61,8 @@ public class BuildOBRTask extends IvyCac
 
     private boolean quiet;
 
+    private List<String> sourceTypes = Arrays.asList("source", "sources", 
"src");
+
     public void setResolver(String resolverName) {
         this.resolverName = resolverName;
     }
@@ -88,10 +91,24 @@ public class BuildOBRTask extends IvyCac
         this.quiet = quiet;
     }
 
+    public void setSourceType(String sourceType) {
+        this.sourceTypes = Arrays.asList(sourceType.split(","));
+    }
+
     protected void prepareTask() {
+        // if browsing a folder, not need for an Ivy instance
         if (baseDir == null) {
             super.prepareTask();
         }
+        // ensure the configured source type get also resolved
+        if (getType() != null && !getType().equals("*") && sourceTypes != null 
&& !sourceTypes.isEmpty()) {
+            StringBuilder buffer = new StringBuilder(getType());
+            for (String sourceType : sourceTypes) {
+                buffer.append(",");
+                buffer.append(sourceType);
+            }
+            setType(buffer.toString());
+        }
     }
 
     public void doExecute() throws BuildException {
@@ -139,7 +156,7 @@ public class BuildOBRTask extends IvyCac
         } else {
             prepareAndCheck();
             try {
-                it = new ArtifactReportManifestIterable(getArtifactReports());
+                it = new ArtifactReportManifestIterable(getArtifactReports(), 
sourceTypes);
             } catch (ParseException e) {
                 throw new BuildException("Impossible to parse the artifact 
reports: "
                         + e.getMessage(), e);

Modified: 
ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/obr/xml/OBRXMLWriter.java
URL: 
http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/obr/xml/OBRXMLWriter.java?rev=1555479&r1=1555478&r2=1555479&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/obr/xml/OBRXMLWriter.java 
(original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/obr/xml/OBRXMLWriter.java 
Sun Jan  5 10:41:19 2014
@@ -40,6 +40,7 @@ import org.apache.ivy.osgi.obr.xml.OBRXM
 import org.apache.ivy.osgi.obr.xml.OBRXMLParser.RepositoryHandler;
 import org.apache.ivy.osgi.obr.xml.OBRXMLParser.RequireHandler;
 import org.apache.ivy.osgi.obr.xml.OBRXMLParser.ResourceHandler;
+import org.apache.ivy.osgi.obr.xml.OBRXMLParser.ResourceSourceHandler;
 import org.apache.ivy.osgi.repo.ManifestAndLocation;
 import org.apache.ivy.osgi.util.Version;
 import org.apache.ivy.osgi.util.VersionRange;
@@ -75,6 +76,9 @@ public class OBRXMLWriter {
             try {
                 bundleInfo = 
ManifestParser.parseManifest(manifestAndLocation.getManifest());
                 bundleInfo.addArtifact(new BundleArtifact(false, 
manifestAndLocation.getUri(), null));
+                if (manifestAndLocation.getSourceURI() != null) {
+                    bundleInfo.addArtifact(new BundleArtifact(true, 
manifestAndLocation.getSourceURI(), null));
+                }
                 nbOk++;
             } catch (ParseException e) {
                 nbRejected++;
@@ -110,11 +114,21 @@ public class OBRXMLWriter {
         AttributesImpl atts = new AttributesImpl();
         addAttr(atts, ResourceHandler.SYMBOLIC_NAME, 
bundleInfo.getSymbolicName());
         addAttr(atts, ResourceHandler.VERSION, bundleInfo.getRawVersion());
-        if (!bundleInfo.getArtifacts().isEmpty()) {
-            // TODO handle several artifacts
-            addAttr(atts, ResourceHandler.URI, 
bundleInfo.getArtifacts().get(0).getUri().toString());
+        for (BundleArtifact artifact : bundleInfo.getArtifacts()) {
+            if (!artifact.isSource()) {
+                addAttr(atts, ResourceHandler.URI, 
bundleInfo.getArtifacts().get(0).getUri().toString());
+                break;
+            }
         }
         handler.startElement("", ResourceHandler.RESOURCE, 
ResourceHandler.RESOURCE, atts);
+        for (BundleArtifact artifact : bundleInfo.getArtifacts()) {
+            if (artifact.isSource()) {
+                startElement(handler, ResourceSourceHandler.SOURCE);
+                characters(handler, artifact.getUri().toString());
+                endElement(handler, ResourceSourceHandler.SOURCE);
+                break;
+            }
+        }
         for (BundleCapability capability : bundleInfo.getCapabilities()) {
             saxCapability(capability, handler);
         }
@@ -255,4 +269,17 @@ public class OBRXMLWriter {
         }
     }
 
+    private static void startElement(ContentHandler handler, String name) 
throws SAXException {
+        handler.startElement("", name, name, new AttributesImpl());
+    }
+
+    private static void endElement(ContentHandler handler, String name) throws 
SAXException {
+        handler.endElement("", name, name);
+    }
+
+    private static void characters(ContentHandler handler, String value) 
throws SAXException {
+        char[] chars = value.toCharArray();
+        handler.characters(chars, 0, chars.length);
+    }
+
 }

Modified: 
ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/repo/AbstractFSManifestIterable.java
URL: 
http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/repo/AbstractFSManifestIterable.java?rev=1555479&r1=1555478&r2=1555479&view=diff
==============================================================================
--- 
ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/repo/AbstractFSManifestIterable.java
 (original)
+++ 
ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/repo/AbstractFSManifestIterable.java
 Sun Jan  5 10:41:19 2014
@@ -107,7 +107,7 @@ public abstract class AbstractFSManifest
                         Manifest manifest = in.getManifest();
                         if (manifest != null) {
                             next = new ManifestAndLocation(manifest,
-                                    buildBundleURI(bundleCandidate));
+                                    buildBundleURI(bundleCandidate), null);
                         } else {
                             Message.debug("No manifest in jar: " + 
bundleCandidate);
                         }

Modified: 
ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/repo/ArtifactReportManifestIterable.java
URL: 
http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/repo/ArtifactReportManifestIterable.java?rev=1555479&r1=1555478&r2=1555479&view=diff
==============================================================================
--- 
ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/repo/ArtifactReportManifestIterable.java
 (original)
+++ 
ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/repo/ArtifactReportManifestIterable.java
 Sun Jan  5 10:41:19 2014
@@ -21,21 +21,38 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.jar.JarInputStream;
 import java.util.jar.Manifest;
 
+import org.apache.ivy.core.module.id.ModuleRevisionId;
 import org.apache.ivy.core.report.ArtifactDownloadReport;
 import org.apache.ivy.util.Message;
 
 public class ArtifactReportManifestIterable implements 
Iterable<ManifestAndLocation> {
 
-    private final List<ArtifactDownloadReport> artifactReports;
+    private final Map<ModuleRevisionId, List<ArtifactDownloadReport>> 
artifactReports = new HashMap<ModuleRevisionId, List<ArtifactDownloadReport>>();
 
-    public ArtifactReportManifestIterable(List<ArtifactDownloadReport> 
artifactReports) {
-        this.artifactReports = artifactReports;
+    private List<String> sourceTypes;
+
+    public ArtifactReportManifestIterable(List<ArtifactDownloadReport> reports,
+            List<String> sourceTypes) {
+        this.sourceTypes = sourceTypes;
+        for (ArtifactDownloadReport report : reports) {
+            ModuleRevisionId mrid = report.getArtifact().getModuleRevisionId();
+            List<ArtifactDownloadReport> moduleReports = 
artifactReports.get(mrid);
+            if (moduleReports == null) {
+                moduleReports = new ArrayList<ArtifactDownloadReport>();
+                artifactReports.put(mrid, moduleReports);
+            }
+            moduleReports.add(report);
+        }
     }
 
     public Iterator<ManifestAndLocation> iterator() {
@@ -46,31 +63,51 @@ public class ArtifactReportManifestItera
 
         private ManifestAndLocation next = null;
 
-        private Iterator<ArtifactDownloadReport> it;
+        private Iterator<ModuleRevisionId> it;
 
         public ArtifactReportManifestIterator() {
-            it = artifactReports.iterator();
+            it = artifactReports.keySet().iterator();
         }
 
         public boolean hasNext() {
             while (next == null && it.hasNext()) {
-                ArtifactDownloadReport report = (ArtifactDownloadReport) 
it.next();
-                if (report.getUnpackedLocalFile() != null
-                        && report.getUnpackedLocalFile().isDirectory()) {
+                ModuleRevisionId mrid = it.next();
+                List<ArtifactDownloadReport> reports = 
artifactReports.get(mrid);
+                ArtifactDownloadReport jar = null;
+                ArtifactDownloadReport source = null;
+                for (ArtifactDownloadReport report : reports) {
+                    if (sourceTypes != null && 
sourceTypes.contains(report.getArtifact().getType())) {
+                        source = report;
+                    } else {
+                        jar = report;
+                    }
+                }
+                if (jar == null) {
+                    // didn't found any suitable jar
+                    continue;
+                }
+                URI sourceURI = null;
+                if (source != null) {
+                    if (source.getUnpackedLocalFile() != null) {
+                        sourceURI = source.getUnpackedLocalFile().toURI();
+                    } else {
+                        sourceURI = source.getLocalFile().toURI();
+                    }
+                }
+                if (jar.getUnpackedLocalFile() != null && 
jar.getUnpackedLocalFile().isDirectory()) {
                     FileInputStream in = null;
                     try {
-                        in = new FileInputStream(new 
File(report.getUnpackedLocalFile(),
+                        in = new FileInputStream(new 
File(jar.getUnpackedLocalFile(),
                                 "META-INF/MANIFEST.MF"));
-                        next = new ManifestAndLocation(new Manifest(in), report
-                                .getUnpackedLocalFile().toURI());
+                        next = new ManifestAndLocation(new Manifest(in), 
jar.getUnpackedLocalFile()
+                                .toURI(), sourceURI);
                         return true;
                     } catch (FileNotFoundException e) {
                         Message.debug(
-                            "Bundle directory file just removed: " + 
report.getUnpackedLocalFile(),
-                            e);
+                            "Bundle directory file just removed: " + 
jar.getUnpackedLocalFile(), e);
                     } catch (IOException e) {
                         Message.debug("The Manifest in the bundle directory 
could not be read: "
-                                + report.getUnpackedLocalFile(), e);
+                                + jar.getUnpackedLocalFile(), e);
                     } finally {
                         if (in != null) {
                             try {
@@ -82,17 +119,17 @@ public class ArtifactReportManifestItera
                     }
                 } else {
                     File artifact;
-                    if (report.getUnpackedLocalFile() != null) {
-                        artifact = report.getUnpackedLocalFile();
+                    if (jar.getUnpackedLocalFile() != null) {
+                        artifact = jar.getUnpackedLocalFile();
                     } else {
-                        artifact = report.getLocalFile();
+                        artifact = jar.getLocalFile();
                     }
                     JarInputStream in = null;
                     try {
                         in = new JarInputStream(new FileInputStream(artifact));
                         Manifest manifest = in.getManifest();
                         if (manifest != null) {
-                            next = new ManifestAndLocation(manifest, 
artifact.toURI());
+                            next = new ManifestAndLocation(manifest, 
artifact.toURI(), sourceURI);
                             return true;
                         }
                         Message.debug("No manifest in jar: " + artifact);

Modified: 
ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/repo/ManifestAndLocation.java
URL: 
http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/repo/ManifestAndLocation.java?rev=1555479&r1=1555478&r2=1555479&view=diff
==============================================================================
--- 
ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/repo/ManifestAndLocation.java 
(original)
+++ 
ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/repo/ManifestAndLocation.java 
Sun Jan  5 10:41:19 2014
@@ -29,9 +29,15 @@ public class ManifestAndLocation {
      */
     private final URI uri;
 
-    public ManifestAndLocation(Manifest manifest, URI uri) {
+    /**
+     * location of the source jar
+     */
+    private final URI sourceURI;
+
+    public ManifestAndLocation(Manifest manifest, URI uri, URI sourceURI) {
         this.manifest = manifest;
         this.uri = uri;
+        this.sourceURI = sourceURI;
     }
 
     public URI getUri() {
@@ -42,4 +48,7 @@ public class ManifestAndLocation {
         return manifest;
     }
 
+    public URI getSourceURI() {
+        return sourceURI;
+    }
 }

Modified: 
ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/repo/ResolverManifestIterable.java
URL: 
http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/repo/ResolverManifestIterable.java?rev=1555479&r1=1555478&r2=1555479&view=diff
==============================================================================
--- 
ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/repo/ResolverManifestIterable.java
 (original)
+++ 
ant/ivy/core/trunk/src/java/org/apache/ivy/osgi/repo/ResolverManifestIterable.java
 Sun Jan  5 10:41:19 2014
@@ -181,7 +181,7 @@ public class ResolverManifestIterable im
                     Message.debug("No manifest on " + artifact);
                 } else {
                     URI uri = BundleInfoAdapter.buildIvyURI(artifact);
-                    next = new ManifestAndLocation(manifest, uri);
+                    next = new ManifestAndLocation(manifest, uri, null);
                 }
                 artifact = null;
             }

Added: 
ant/ivy/core/trunk/test/java/org/apache/ivy/osgi/obr/OBRXMLWriterTest.java
URL: 
http://svn.apache.org/viewvc/ant/ivy/core/trunk/test/java/org/apache/ivy/osgi/obr/OBRXMLWriterTest.java?rev=1555479&view=auto
==============================================================================
--- ant/ivy/core/trunk/test/java/org/apache/ivy/osgi/obr/OBRXMLWriterTest.java 
(added)
+++ ant/ivy/core/trunk/test/java/org/apache/ivy/osgi/obr/OBRXMLWriterTest.java 
Sun Jan  5 10:41:19 2014
@@ -0,0 +1,95 @@
+/*
+ *  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.ivy.osgi.obr;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.osgi.core.BundleArtifact;
+import org.apache.ivy.osgi.core.BundleInfo;
+import org.apache.ivy.osgi.obr.xml.OBRXMLParser;
+import org.apache.ivy.osgi.obr.xml.OBRXMLWriter;
+import org.apache.ivy.osgi.repo.BundleRepoDescriptor;
+import org.apache.ivy.osgi.repo.ModuleDescriptorWrapper;
+import org.apache.ivy.osgi.util.Version;
+import org.apache.ivy.util.CollectionUtils;
+import org.xml.sax.ContentHandler;
+
+public class OBRXMLWriterTest extends TestCase {
+
+    private static final Version BUNDLE_VERSION = new Version(1, 2, 3, null);
+
+    private static final String BUNDLE_1 = "org.apache.ivy.test";
+
+    private static final String BUNDLE_2 = "org.apache.ivy.test2";
+
+    public void testWriteWithSource() throws Exception {
+        List<BundleInfo> bundles = new ArrayList<BundleInfo>();
+
+        BundleInfo bundle = new BundleInfo(BUNDLE_1, BUNDLE_VERSION);
+        bundle.addArtifact(new BundleArtifact(false, new 
URI("file:///test.jar"), null));
+        bundle.addArtifact(new BundleArtifact(true, new 
URI("file:///test-sources.jar"), null));
+        bundles.add(bundle);
+
+        bundle = new BundleInfo(BUNDLE_2, BUNDLE_VERSION);
+        bundle.addArtifact(new BundleArtifact(false, new 
URI("file:///test2.jar"), null));
+        bundles.add(bundle);
+
+        new File("build/test-files").mkdirs();
+        File obrFile = new File("build/test-files/obr-sources.xml");
+        FileOutputStream out = new FileOutputStream(obrFile);
+        try {
+            ContentHandler hanlder = OBRXMLWriter.newHandler(out, "UTF-8", 
true);
+            OBRXMLWriter.writeBundles(bundles, hanlder);
+        } finally {
+            out.close();
+        }
+
+        FileInputStream in = new FileInputStream(obrFile);
+        BundleRepoDescriptor repo;
+        try {
+            repo = OBRXMLParser.parse(new URI("file:///test"), in);
+        } finally {
+            in.close();
+        }
+        assertEquals(2, CollectionUtils.toList(repo.getModules()).size());
+
+        ModuleDescriptorWrapper bundle1 = repo.findModule(BUNDLE_1, 
BUNDLE_VERSION);
+        assertNotNull(bundle1);
+        Artifact[] artifacts = bundle1.getModuleDescriptor().getAllArtifacts();
+        assertEquals(2, artifacts.length);
+        if (artifacts[0].getType().equals("jar")) {
+            assertEquals("source", artifacts[1].getType());
+        } else {
+            assertEquals("jar", artifacts[1].getType());
+            assertEquals("source", artifacts[0].getType());
+        }
+
+        ModuleDescriptorWrapper bundle2 = repo.findModule(BUNDLE_2, 
BUNDLE_VERSION);
+        assertNotNull(bundle2);
+        assertEquals(1, 
bundle2.getModuleDescriptor().getAllArtifacts().length);
+    }
+
+}

Propchange: 
ant/ivy/core/trunk/test/java/org/apache/ivy/osgi/obr/OBRXMLWriterTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
ant/ivy/core/trunk/test/java/org/apache/ivy/osgi/obr/OBRXMLWriterTest.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: 
ant/ivy/core/trunk/test/java/org/apache/ivy/osgi/obr/OBRXMLWriterTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain


Reply via email to