You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 09:25:32 UTC

[sling-org-apache-sling-commons-osgi] 06/19: SLING-5379 - support renaming of bundles in maven-slingstart-plugin. Contributed by David Bosschaert, thanks!

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.commons.osgi-2.4.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-commons-osgi.git

commit 63162f5e1c383d93e099cce6b4d0a4845c852913
Author: Bertrand Delacretaz <bd...@apache.org>
AuthorDate: Mon Dec 21 15:11:26 2015 +0000

    SLING-5379 - support renaming of bundles in maven-slingstart-plugin. Contributed by David Bosschaert, thanks!
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/commons/osgi@1721185 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            |   3 +-
 .../org/apache/sling/commons/osgi/BundleUtil.java  | 103 ++++++++++++++++
 .../apache/sling/commons/osgi/package-info.java    |   2 +-
 .../apache/sling/commons/osgi/BundleUtilTest.java  | 133 +++++++++++++++++++++
 4 files changed, 239 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index 9d92362..35beb9d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,7 +28,7 @@
     </parent>
 
     <artifactId>org.apache.sling.commons.osgi</artifactId>
-    <version>2.3.1-SNAPSHOT</version>
+    <version>2.3.1-SNAPSHOT</version> <!-- next release version should be 2.4 given new BundleUtil -->
     <packaging>bundle</packaging>
 
     <name>Apache Sling Commons OSGi support</name>
@@ -41,6 +41,7 @@
     </scm>
     
     <properties>
+        <sling.java.version>7</sling.java.version>
         <test.jars.folder>${project.build.directory}/testjars</test.jars.folder>
     </properties>
 
diff --git a/src/main/java/org/apache/sling/commons/osgi/BundleUtil.java b/src/main/java/org/apache/sling/commons/osgi/BundleUtil.java
new file mode 100644
index 0000000..a1bcd95
--- /dev/null
+++ b/src/main/java/org/apache/sling/commons/osgi/BundleUtil.java
@@ -0,0 +1,103 @@
+/*
+ * 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.sling.commons.osgi;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+/**
+ * The <code>BundleUtil</code> is a utility class providing some
+ * useful utility methods for bundle handling.
+ * @since 2.4
+ */
+public class BundleUtil {
+    /**
+     * Creates a new OSGi Bundle from a given bundle with the only difference that the
+     * symbolic name is changed. The original symbolic name is recorded in the Manifest
+     * using the {@code X-Original-Bundle-SymbolicName} header.
+     * @param bundleFile The original bundle file. This file will not be modified.
+     * @param newBSN The new Bundle-SymbolicName
+     * @param tempDir The temporary directory to use. This is where the new bundle will be
+     * written. This directory must exist.
+     * @return The new bundle with the altered Symbolic Name.
+     * @throws IOException If something goes wrong reading or writing.
+     */
+    public static File renameBSN(File bundleFile, String newBSN, File tempDir) throws IOException {
+        try (JarInputStream jis = new JarInputStream(new FileInputStream(bundleFile))) {
+            Manifest inputMF = jis.getManifest();
+
+            Attributes inputAttrs = inputMF.getMainAttributes();
+            String bver = inputAttrs.getValue("Bundle-Version");
+            String orgBSN = inputAttrs.getValue("Bundle-SymbolicName");
+            if (bver == null)
+                bver = "0.0.0";
+
+            File newBundle = new File(tempDir, newBSN + "-" + bver + ".jar");
+
+            Manifest newMF = new Manifest(inputMF);
+            Attributes outputAttrs = newMF.getMainAttributes();
+            outputAttrs.putValue("Bundle-SymbolicName", newBSN);
+            outputAttrs.putValue("X-Original-Bundle-SymbolicName", orgBSN);
+
+            try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(newBundle), newMF)) {
+                JarEntry je = null;
+                while ((je = jis.getNextJarEntry()) != null) {
+                    try {
+                        jos.putNextEntry(je);
+                        if (!je.isDirectory())
+                            pumpStream(jis, jos);
+                    } finally {
+                        jos.closeEntry();
+                        jis.closeEntry();;
+                    }
+                }
+            }
+
+            return newBundle;
+        }
+    }
+
+    static void pumpStream(InputStream is, OutputStream os) throws IOException {
+        byte[] bytes = new byte[65536];
+
+        int length = 0;
+        int offset = 0;
+
+        while ((length = is.read(bytes, offset, bytes.length - offset)) != -1) {
+            offset += length;
+
+            if (offset == bytes.length) {
+                os.write(bytes, 0, bytes.length);
+                offset = 0;
+            }
+        }
+        if (offset != 0) {
+            os.write(bytes, 0, offset);
+        }
+    }
+}
diff --git a/src/main/java/org/apache/sling/commons/osgi/package-info.java b/src/main/java/org/apache/sling/commons/osgi/package-info.java
index 243300d..1d589bd 100644
--- a/src/main/java/org/apache/sling/commons/osgi/package-info.java
+++ b/src/main/java/org/apache/sling/commons/osgi/package-info.java
@@ -16,5 +16,5 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-@aQute.bnd.annotation.Version("2.3")
+@aQute.bnd.annotation.Version("2.4")
 package org.apache.sling.commons.osgi;
diff --git a/src/test/java/org/apache/sling/commons/osgi/BundleUtilTest.java b/src/test/java/org/apache/sling/commons/osgi/BundleUtilTest.java
new file mode 100644
index 0000000..9e0fa5c
--- /dev/null
+++ b/src/test/java/org/apache/sling/commons/osgi/BundleUtilTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.sling.commons.osgi;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarInputStream;
+import java.util.jar.Manifest;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class BundleUtilTest {
+    @Test
+    public void testBSNRenaming() throws IOException {
+        File tempDir = new File(System.getProperty("java.io.tmpdir"));
+
+        // Just take any bundle from the maven deps as an example...
+        File originalFile = getMavenArtifactFile(getMavenRepoRoot(), "com.google.guava", "guava", "15.0");
+
+        File generatedFile = BundleUtil.renameBSN(originalFile, "org.acme.baklava.guava", tempDir);
+
+        try {
+            compareJarContents(originalFile, generatedFile);
+
+            try (JarFile jfOrg = new JarFile(originalFile);
+                    JarFile jfNew = new JarFile(generatedFile)) {
+                    Manifest mfOrg = jfOrg.getManifest();
+                    Manifest mfNew = jfNew.getManifest();
+
+                    Attributes orgAttrs = mfOrg.getMainAttributes();
+                    Attributes newAttrs = mfNew.getMainAttributes();
+                    for (Object key : orgAttrs.keySet()) {
+                        String orgVal = orgAttrs.getValue(key.toString());
+                        String newVal = newAttrs.getValue(key.toString());
+
+                        if ("Bundle-SymbolicName".equals(key.toString())) {
+                            assertEquals("Should have recorded the original Bundle-SymbolicName",
+                                    orgVal, newAttrs.getValue("X-Original-Bundle-SymbolicName"));
+
+                            assertEquals("org.acme.baklava.guava", newVal);
+                        } else {
+                            assertEquals("Different keys: " + key, orgVal, newVal);
+                        }
+                    }
+                }
+
+        } finally {
+            assertTrue("Unable to delete temporary file", generatedFile.delete());
+        }
+    }
+
+    private static void compareJarContents(File orgJar, File actualJar) throws IOException {
+        try (JarInputStream jis1 = new JarInputStream(new FileInputStream(orgJar));
+            JarInputStream jis2 = new JarInputStream(new FileInputStream(actualJar))) {
+            JarEntry je1 = null;
+            while ((je1 = jis1.getNextJarEntry()) != null) {
+                if (je1.isDirectory())
+                    continue;
+
+                JarEntry je2 = null;
+                while((je2 = jis2.getNextJarEntry()) != null) {
+                    if (!je2.isDirectory())
+                        break;
+                }
+
+                assertEquals(je1.getName(), je2.getName());
+                assertEquals(je1.getSize(), je2.getSize());
+
+                try {
+                    byte[] buf1 = streamToByteArray(jis1);
+                    byte[] buf2 = streamToByteArray(jis2);
+
+                    assertArrayEquals("Contents not equal: " + je1.getName(), buf1, buf2);
+                } finally {
+                    jis1.closeEntry();
+                    jis2.closeEntry();
+                }
+            }
+        }
+    }
+
+    private static byte [] streamToByteArray(InputStream is) throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        BundleUtil.pumpStream(is, baos);
+        return baos.toByteArray();
+    }
+
+    private static File getMavenArtifactFile(File repoRoot, String gid, String aid, String ver) {
+        return new File(repoRoot, gid.replace('.', '/') + '/' + aid + '/' + ver + '/' + aid + '-' + ver + ".jar");
+    }
+
+    private static File getMavenRepoRoot() throws IOException {
+        URL res = BundleUtilTest.class.getClassLoader().getResource(
+                Test.class.getName().replace('.', '/') + ".class");
+
+        String u = res.toExternalForm();
+        if (u.startsWith("jar:"))
+            u = u.substring(4);
+
+        int idx = u.indexOf("junit");
+        if (idx < 0)
+            throw new IllegalStateException("Cannot infer maven repo root: " + res);
+
+        return new File(new URL(u.substring(0, idx)).getFile());
+    }
+}

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.