Author: bdelacretaz
Date: Mon Dec 21 15:11:26 2015
New Revision: 1721185
URL: http://svn.apache.org/viewvc?rev=1721185&view=rev
Log:
SLING-5379 - support renaming of bundles in maven-slingstart-plugin.
Contributed by David Bosschaert, thanks!
Added:
sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/BundleUtil.java
sling/trunk/bundles/commons/osgi/src/test/java/org/apache/sling/commons/osgi/BundleUtilTest.java
Modified:
sling/trunk/bundles/commons/osgi/pom.xml
sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/package-info.java
sling/trunk/tooling/maven/slingstart-maven-plugin/pom.xml
sling/trunk/tooling/maven/slingstart-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/PreparePackageMojo.java
sling/trunk/tooling/maven/slingstart-maven-plugin/src/test/java/org/apache/sling/maven/slingstart/PreparePackageMojoTest.java
Modified: sling/trunk/bundles/commons/osgi/pom.xml
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/commons/osgi/pom.xml?rev=1721185&r1=1721184&r2=1721185&view=diff
==============================================================================
--- sling/trunk/bundles/commons/osgi/pom.xml (original)
+++ sling/trunk/bundles/commons/osgi/pom.xml Mon Dec 21 15:11:26 2015
@@ -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>
Added:
sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/BundleUtil.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/BundleUtil.java?rev=1721185&view=auto
==============================================================================
---
sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/BundleUtil.java
(added)
+++
sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/BundleUtil.java
Mon Dec 21 15:11:26 2015
@@ -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);
+ }
+ }
+}
Modified:
sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/package-info.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/package-info.java?rev=1721185&r1=1721184&r2=1721185&view=diff
==============================================================================
---
sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/package-info.java
(original)
+++
sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/package-info.java
Mon Dec 21 15:11:26 2015
@@ -16,5 +16,5 @@
* specific language governing permissions and limitations
* under the License.
*/
[email protected]("2.3")
[email protected]("2.4")
package org.apache.sling.commons.osgi;
Added:
sling/trunk/bundles/commons/osgi/src/test/java/org/apache/sling/commons/osgi/BundleUtilTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/commons/osgi/src/test/java/org/apache/sling/commons/osgi/BundleUtilTest.java?rev=1721185&view=auto
==============================================================================
---
sling/trunk/bundles/commons/osgi/src/test/java/org/apache/sling/commons/osgi/BundleUtilTest.java
(added)
+++
sling/trunk/bundles/commons/osgi/src/test/java/org/apache/sling/commons/osgi/BundleUtilTest.java
Mon Dec 21 15:11:26 2015
@@ -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());
+ }
+}
Modified: sling/trunk/tooling/maven/slingstart-maven-plugin/pom.xml
URL:
http://svn.apache.org/viewvc/sling/trunk/tooling/maven/slingstart-maven-plugin/pom.xml?rev=1721185&r1=1721184&r2=1721185&view=diff
==============================================================================
--- sling/trunk/tooling/maven/slingstart-maven-plugin/pom.xml (original)
+++ sling/trunk/tooling/maven/slingstart-maven-plugin/pom.xml Mon Dec 21
15:11:26 2015
@@ -86,7 +86,7 @@
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.provisioning.model</artifactId>
- <version>1.4.0</version>
+ <version>1.4.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
@@ -169,6 +169,11 @@
</exclusions>
</dependency>
<dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.commons.osgi</artifactId>
+ <version>2.3.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
@@ -207,12 +212,6 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.apache.sling</groupId>
- <artifactId>org.apache.sling.commons.osgi</artifactId>
- <version>2.3.0</version>
- <scope>test</scope>
- </dependency>
- <dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.commons.threads</artifactId>
<version>3.2.0</version>
Modified:
sling/trunk/tooling/maven/slingstart-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/PreparePackageMojo.java
URL:
http://svn.apache.org/viewvc/sling/trunk/tooling/maven/slingstart-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/PreparePackageMojo.java?rev=1721185&r1=1721184&r2=1721185&view=diff
==============================================================================
---
sling/trunk/tooling/maven/slingstart-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/PreparePackageMojo.java
(original)
+++
sling/trunk/tooling/maven/slingstart-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/PreparePackageMojo.java
Mon Dec 21 15:11:26 2015
@@ -48,6 +48,7 @@ import org.apache.maven.plugins.annotati
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.apache.sling.commons.osgi.BundleUtil;
import org.apache.sling.provisioning.model.ArtifactGroup;
import org.apache.sling.provisioning.model.Configuration;
import org.apache.sling.provisioning.model.Feature;
@@ -231,7 +232,18 @@ public class PreparePackageMojo extends
for(final org.apache.sling.provisioning.model.Artifact a : group) {
final Artifact artifact = ModelUtils.getArtifact(this.project,
this.mavenSession, this.artifactHandlerManager, this.resolver,
a.getGroupId(), a.getArtifactId(), a.getVersion(),
a.getType(), a.getClassifier());
- final File artifactFile = artifact.getFile();
+ File artifactFile = artifact.getFile();
+
+ String newBSN = a.getMetadata().get("bundle:rename-bsn");
+ if (newBSN != null) {
+ try {
+ getTmpDir().mkdirs();
+ artifactFile = BundleUtil.renameBSN(artifactFile,
newBSN, getTmpDir());
+ } catch (IOException e) {
+ throw new MojoExecutionException("Unable to rename
bundle BSN to " + newBSN + " for " + artifactFile, e);
+ }
+ }
+
contentsMap.put(getPathForArtifact(group.getStartLevel(),
artifactFile.getName(), runMode, isBoot), artifactFile);
}
}
@@ -264,7 +276,6 @@ public class PreparePackageMojo extends
}
}
-
private File createSubsystemBaseFile(Feature feature, AtomicInteger
startLevelHolder) throws MojoExecutionException {
File subsystemFile = new File(getTmpDir(), feature.getName() +
".subsystem-base");
if (subsystemFile.exists()) {
@@ -354,7 +365,7 @@ public class PreparePackageMojo extends
attrs.putValue("Manifest-Version", "1.0"); // Manifest does not work
without this value
attrs.putValue("About-This-Manifest", "This is not a real manifest, it
is used as information when this archive is transformed into a real subsystem
.esa file");
for (Map.Entry<String, StringBuilder> entry : runModes.entrySet()) {
- attrs.putValue(entry.getKey(), entry.getValue().toString());
+ attrs.putValue(entry.getKey().replace(':', '_'),
entry.getValue().toString());
}
return mf;
}
Modified:
sling/trunk/tooling/maven/slingstart-maven-plugin/src/test/java/org/apache/sling/maven/slingstart/PreparePackageMojoTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/tooling/maven/slingstart-maven-plugin/src/test/java/org/apache/sling/maven/slingstart/PreparePackageMojoTest.java?rev=1721185&r1=1721184&r2=1721185&view=diff
==============================================================================
---
sling/trunk/tooling/maven/slingstart-maven-plugin/src/test/java/org/apache/sling/maven/slingstart/PreparePackageMojoTest.java
(original)
+++
sling/trunk/tooling/maven/slingstart-maven-plugin/src/test/java/org/apache/sling/maven/slingstart/PreparePackageMojoTest.java
Mon Dec 21 15:11:26 2015
@@ -17,6 +17,7 @@
package org.apache.sling.maven.slingstart;
import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
@@ -27,7 +28,9 @@ import java.nio.file.Path;
import java.util.HashSet;
import java.util.Set;
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 java.util.zip.ZipEntry;
@@ -52,7 +55,87 @@ import static org.junit.Assert.assertEqu
public class PreparePackageMojoTest {
@Test
- public void testSubsystemBaseGeneration1() throws Exception {
+ public void testBSNRenaming() throws Exception {
+ // Provide the system with some artifacts that are known to be in the
local .m2 repo
+ // These are explicitly included in the test section of the pom.xml
+ PreparePackageMojo ppm = getMojoUnderTest(
+ "org.apache.sling/org.apache.sling.commons.classloader/1.3.2",
+
"org.apache.sling/org.apache.sling.commons.classloader/1.3.2/app",
+ "org.apache.sling/org.apache.sling.commons.json/2.0.12");
+ try {
+ String modelTxt = "[feature name=:launchpad]\n" +
+ "[artifacts]\n" +
+ "
org.apache.sling/org.apache.sling.commons.classloader/1.3.2\n" +
+ "" +
+ "[feature name=rename_test]\n" +
+ " org.apache.sling/org.apache.sling.commons.json/2.0.12
[bundle:rename-bsn=r-foo.bar.renamed.sling.commons.json]\n";
+
+ Model model = ModelReader.read(new StringReader(modelTxt), null);
+ ppm.execute(model);
+
+ File orgJar = getMavenArtifactFile(getMavenRepoRoot(),
"org.apache.sling", "org.apache.sling.commons.json", "2.0.12");
+ File generatedJar = new File(ppm.getTmpDir() +
"/r-foo.bar.renamed.sling.commons.json-2.0.12.jar");
+
+ compareJarContents(orgJar, generatedJar);
+
+ try (JarFile jfOrg = new JarFile(orgJar);
+ JarFile jfNew = new JarFile(generatedJar)) {
+ 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("r-foo.bar.renamed.sling.commons.json",
newVal);
+ } else {
+ assertEquals("Different keys: " + key, orgVal, newVal);
+ }
+ }
+ }
+ } finally {
+ FileUtils.deleteDirectory(new
File(ppm.project.getBuild().getDirectory()));
+ }
+ }
+
+ 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 = IOUtils.toByteArray(jis1);
+ byte[] buf2 = IOUtils.toByteArray(jis2);
+
+ assertArrayEquals("Contents not equal: " + je1.getName(),
buf1, buf2);
+ } finally {
+ jis1.closeEntry();
+ jis2.closeEntry();
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testSubsystemBaseGeneration() throws Exception {
// Provide the system with some artifacts that are known to be in the
local .m2 repo
// These are explicitly included in the test section of the pom.xml
PreparePackageMojo ppm = getMojoUnderTest(
@@ -84,7 +167,7 @@ public class PreparePackageMojoTest {
"
org.apache.sling/org.apache.sling.commons.json/2.0.12\n" +
" org.apache.sling/org.apache.sling.commons.mime/2.1.8\n"
+
"" +
- "[artifacts startLevel=20 runModes=foo,bar]\n" +
+ "[artifacts startLevel=20 runModes=foo,bar,:blah]\n" +
"
org.apache.sling/org.apache.sling.commons.threads/3.2.0\n" +
"" +
"[artifacts startLevel=100 runModes=bar]\n" +