This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-factory-subsystems-base.git
commit 4be1a7950840d0b9a29935df81d0bac933d91502 Author: Robert Munteanu <[email protected]> AuthorDate: Thu Nov 5 17:09:31 2015 +0000 SLING-5210 - Create an installer factory/transformer for slingstart-maven-plugin generated intermediary subsystem files Submitted-By: David Bosschaert git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1712821 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 112 +++++++++ .../factories/subsystems/base/impl/Activator.java | 77 ++++++ .../base/impl/SubsystemBaseTransformer.java | 240 +++++++++++++++++++ .../base/impl/SubsystemBaseTransformerTest.java | 258 +++++++++++++++++++++ src/test/resources/test1.subsystem-base | Bin 0 -> 160681 bytes 5 files changed, 687 insertions(+) diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..1b7a349 --- /dev/null +++ b/pom.xml @@ -0,0 +1,112 @@ +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.sling</groupId> + <artifactId>sling</artifactId> + <version>25</version> + <relativePath/> + </parent> + + <artifactId>org.apache.sling.installer.factory.subsystems-base</artifactId> + <version>1.0.0-SNAPSHOT</version> + <packaging>bundle</packaging> + + <name>Apache Sling Subsystems Base Installer</name> + <description> + Provides support for subsystems-base files to the Apache Sling OSGi installer + </description> + + <properties> + <sling.java.version>7</sling.java.version> + </properties> + + <scm> + <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/installer/factories/subsystems-base</connection> + <developerConnection> scm:svn:https://svn.apache.org/repos/asf/sling/trunk/installer/factories/subsystems-base</developerConnection> + <url>http://svn.apache.org/viewvc/sling/trunk/installer/factories/subsystems-base/</url> + </scm> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-Activator> + org.apache.sling.installer.factories.subsystems.base.impl.Activator + </Bundle-Activator> + <Private-Package> + org.apache.sling.installer.factories.subsystems.base.impl.* + </Private-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <version>5.0.0</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <version>5.0.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.installer.api</artifactId> + <version>1.0.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.settings</artifactId> + <version>1.3.6</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-all</artifactId> + <version>1.10.19</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + <scope>test</scope> + </dependency> + </dependencies> +</project> diff --git a/src/main/java/org/apache/sling/installer/factories/subsystems/base/impl/Activator.java b/src/main/java/org/apache/sling/installer/factories/subsystems/base/impl/Activator.java new file mode 100644 index 0000000..0708f71 --- /dev/null +++ b/src/main/java/org/apache/sling/installer/factories/subsystems/base/impl/Activator.java @@ -0,0 +1,77 @@ +/* + * 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.installer.factories.subsystems.base.impl; + +import java.util.Dictionary; +import java.util.Hashtable; + +import org.apache.sling.installer.api.tasks.ResourceTransformer; +import org.apache.sling.settings.SlingSettingsService; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; +import org.osgi.util.tracker.ServiceTracker; + +public class Activator implements BundleActivator { + private ServiceTracker<SlingSettingsService, SlingSettingsService> slingSettingsTracker; + + /** The service registration for the installer service. */ + private ServiceRegistration<?> serviceReg; + + public void start(BundleContext context) throws Exception { + slingSettingsTracker = new ServiceTracker<SlingSettingsService, SlingSettingsService>(context, + SlingSettingsService.class, null) { + @Override + public SlingSettingsService addingService(ServiceReference<SlingSettingsService> reference) { + SlingSettingsService slingSettings = super.addingService(reference); + registerInstaller(context, slingSettings); + return slingSettings; + } + + @Override + public void removedService(ServiceReference<SlingSettingsService> reference, SlingSettingsService service) { + unregisterInstaller(); + super.removedService(reference, service); + } + }; + slingSettingsTracker.open(); + } + + public void stop(BundleContext context) throws Exception { + slingSettingsTracker.close(); + unregisterInstaller(); + } + + private void registerInstaller(BundleContext context, SlingSettingsService slingSettings) { + final Dictionary<String, Object> props = new Hashtable<String, Object>(); + props.put(Constants.SERVICE_DESCRIPTION, "Apache Sling Installer Support for subsystem-base files"); + props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation"); + this.serviceReg = context.registerService(ResourceTransformer.class, + new SubsystemBaseTransformer(slingSettings), props); + } + + private void unregisterInstaller() { + if ( serviceReg != null ) { + serviceReg.unregister(); + serviceReg = null; + } + } +} diff --git a/src/main/java/org/apache/sling/installer/factories/subsystems/base/impl/SubsystemBaseTransformer.java b/src/main/java/org/apache/sling/installer/factories/subsystems/base/impl/SubsystemBaseTransformer.java new file mode 100644 index 0000000..c536004 --- /dev/null +++ b/src/main/java/org/apache/sling/installer/factories/subsystems/base/impl/SubsystemBaseTransformer.java @@ -0,0 +1,240 @@ +/* + * 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.installer.factories.subsystems.base.impl; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +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 java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.jar.JarInputStream; +import java.util.jar.Manifest; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + +import org.apache.sling.installer.api.InstallableResource; +import org.apache.sling.installer.api.tasks.RegisteredResource; +import org.apache.sling.installer.api.tasks.ResourceTransformer; +import org.apache.sling.installer.api.tasks.TransformationResult; +import org.apache.sling.settings.SlingSettingsService; +import org.osgi.framework.Constants; +import org.osgi.framework.Version; +import org.osgi.framework.namespace.IdentityNamespace; +import org.osgi.service.subsystem.SubsystemConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SubsystemBaseTransformer implements ResourceTransformer { + private static final String POTENTIAL_BUNDLES = "Potential_Bundles/"; + + private static final String TYPE_SUBSYSTEM_BASE = "subsystem-base"; + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + private final SlingSettingsService slingSettings; + + public SubsystemBaseTransformer(SlingSettingsService settings) { + slingSettings = settings; + } + + public TransformationResult[] transform(RegisteredResource resource) { + // TODO start level of the subsystem + if ( resource.getType().equals(InstallableResource.TYPE_FILE) ) { + if ( resource.getURL().endsWith("." + TYPE_SUBSYSTEM_BASE) ) { + logger.info("Found subsystem-base resource {}", resource); + + try { + SubsystemData ssd = createSubsystemFile(resource); + + TransformationResult tr = new TransformationResult(); + Attributes mfAttributes = ssd.manifest.getMainAttributes(); + tr.setId(mfAttributes.getValue(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME)); + tr.setVersion(new Version(mfAttributes.getValue(SubsystemConstants.SUBSYSTEM_VERSION))); + tr.setResourceType("esa"); + tr.setInputStream(new DeleteOnCloseFileInputStream(ssd.file)); + + Map<String, Object> attr = new HashMap<String, Object>(); + attr.put(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, mfAttributes.getValue(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME)); + attr.put(SubsystemConstants.SUBSYSTEM_VERSION, mfAttributes.getValue(SubsystemConstants.SUBSYSTEM_VERSION)); + tr.setAttributes(attr); + + return new TransformationResult[] {tr}; + } catch (IOException ioe) { + logger.error("Problem processing subsystem-base file " + resource, ioe); + } + } + } + return null; + } + + private SubsystemData createSubsystemFile(RegisteredResource resource) throws IOException { + SubsystemData data = new SubsystemData(); + StringBuilder subsystemContent = new StringBuilder(); + try (JarInputStream jis = new JarInputStream(resource.getInputStream())) { + Manifest runModesManifest = jis.getManifest(); + Set<String> runModeResources = processRunModesManifest(runModesManifest); + + File zf = File.createTempFile("sling-generated", ".esa"); + zf.deleteOnExit(); + data.file = zf; + try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zf))) { + ZipEntry zie = null; + while((zie = jis.getNextEntry()) != null) { + String zieName = zie.getName(); + if ("SUBSYSTEM-MANIFEST-BASE.MF".equals(zieName)) { + data.manifest = new Manifest(jis); + } else if (runModeResources.contains(zieName)) { + zieName = zieName.substring(POTENTIAL_BUNDLES.length()); + + handleSubsystemArtifact(zieName, jis, zos, subsystemContent); + } + } + + data.manifest.getMainAttributes().putValue(SubsystemConstants.SUBSYSTEM_CONTENT, subsystemContent.toString()); + ZipEntry zoe = new ZipEntry("OSGI-INF/SUBSYSTEM.MF"); + try { + zos.putNextEntry(zoe); + data.manifest.write(zos); + } finally { + zos.closeEntry(); + } + } + } + + return data; + } + + private Set<String> processRunModesManifest(Manifest runModesManifest) { + Set<String> res = new HashSet<>(); + + Attributes attrs = runModesManifest.getMainAttributes(); + + res.addAll(parseManifestHeader(attrs, "_all_")); + for (String rm : slingSettings.getRunModes()) { + res.addAll(parseManifestHeader(attrs, rm)); + } + + return res; + } + + private List<String> parseManifestHeader(Attributes attrs, String key) { + List<String> res = new ArrayList<>(); + + String val = attrs.getValue(key); + if (val == null) + return Collections.emptyList(); + + for (String r : val.split("[|]")) { + if (r.length() > 0) + res.add(r); + } + return res; + } + + private void handleSubsystemArtifact(String artifactName, ZipInputStream zis, ZipOutputStream zos, + StringBuilder subsystemContent) throws IOException { + int idx = artifactName.indexOf('/'); + int idx2 = artifactName.lastIndexOf('/'); + if (idx != idx2 || idx == 0) + throw new IOException("Invalid entry name, should have format .../<num>/artifact.jar: " + artifactName); + + int startOrder = Integer.parseInt(artifactName.substring(0, idx)); + idx++; + if (artifactName.length() > idx) { + File tempArtifact = File.createTempFile("sling-generated", ".tmp"); + tempArtifact.deleteOnExit(); + Path tempPath = tempArtifact.toPath(); + Files.copy(zis, tempPath, StandardCopyOption.REPLACE_EXISTING); + + try (JarFile jf = new JarFile(tempArtifact)) { + Attributes ma = jf.getManifest().getMainAttributes(); + String bsn = ma.getValue(Constants.BUNDLE_SYMBOLICNAME); + String version = ma.getValue(Constants.BUNDLE_VERSION); + if (version == null) + version = "0"; + String type = ma.getValue(Constants.FRAGMENT_HOST) != null ? + IdentityNamespace.TYPE_FRAGMENT : IdentityNamespace.TYPE_BUNDLE; + if (bsn != null) { + if (subsystemContent.length() > 0) + subsystemContent.append(','); + + subsystemContent.append(bsn); + subsystemContent.append(';'); + subsystemContent.append(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE); + subsystemContent.append('='); + subsystemContent.append(version); + subsystemContent.append(';'); + subsystemContent.append(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE); + subsystemContent.append('='); + subsystemContent.append(type); + subsystemContent.append(';'); + subsystemContent.append(SubsystemConstants.START_ORDER_DIRECTIVE); + subsystemContent.append(":="); + subsystemContent.append(startOrder); + } + + } catch (Exception ex) { + // apparently not a valid JarFile + } + ZipEntry zoe = new ZipEntry(artifactName.substring(idx)); + try { + zos.putNextEntry(zoe); + Files.copy(tempPath, zos); + } finally { + zos.closeEntry(); + tempArtifact.delete(); + } + } + } + + private static class SubsystemData { + File file; + Manifest manifest; + } + + static class DeleteOnCloseFileInputStream extends FileInputStream { + final File file; + + public DeleteOnCloseFileInputStream(File f) throws FileNotFoundException { + super(f); + file = f; + } + + @Override + public void close() throws IOException { + try { + super.close(); + } finally { + file.delete(); + } + } + } +} diff --git a/src/test/java/org/apache/sling/installer/factories/subsystems/base/impl/SubsystemBaseTransformerTest.java b/src/test/java/org/apache/sling/installer/factories/subsystems/base/impl/SubsystemBaseTransformerTest.java new file mode 100644 index 0000000..f99d3d3 --- /dev/null +++ b/src/test/java/org/apache/sling/installer/factories/subsystems/base/impl/SubsystemBaseTransformerTest.java @@ -0,0 +1,258 @@ +/* + * 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.installer.factories.subsystems.base.impl; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.util.Arrays; +import java.util.Dictionary; +import java.util.HashSet; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.jar.Manifest; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import org.apache.sling.installer.api.tasks.RegisteredResource; +import org.apache.sling.installer.api.tasks.TransformationResult; +import org.apache.sling.installer.factories.subsystems.base.impl.SubsystemBaseTransformer.DeleteOnCloseFileInputStream; +import org.apache.sling.settings.SlingSettingsService; +import org.junit.Test; +import org.mockito.Mockito; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class SubsystemBaseTransformerTest { + @Test + public void testTransformNoRunMode() throws Exception { + SlingSettingsService slingSettings = Mockito.mock(SlingSettingsService.class); + SubsystemBaseTransformer sbt = new SubsystemBaseTransformer(slingSettings); + + URL testArchive = getClass().getResource("/test1.subsystem-base"); + RegisteredResource resource = new TestRegisteredResource(testArchive); + TransformationResult[] tra = sbt.transform(resource); + assertEquals(1, tra.length); + TransformationResult tr = tra[0]; + assertEquals("esa", tr.getResourceType()); + assertEquals("test1", tr.getId()); + DeleteOnCloseFileInputStream dcis = (DeleteOnCloseFileInputStream) tr.getInputStream(); + assertTrue("The file backing the stream should exist", dcis.file.exists()); + + Set<String> foundBundles = new HashSet<>(); + try (ZipInputStream zis = new ZipInputStream(dcis); + JarFile jf = new JarFile(testArchive.getFile())) { + ZipEntry ze = null; + while((ze = zis.getNextEntry()) != null) { + foundBundles.add(ze.getName()); + switch(ze.getName()) { + case "OSGI-INF/SUBSYSTEM.MF": + Manifest mf = new Manifest(zis); + Attributes attrs = mf.getMainAttributes(); + assertEquals("test1", attrs.getValue("Subsystem-SymbolicName")); + assertEquals("osgi.subsystem.composite", attrs.getValue("Subsystem-Type")); + assertEquals("(c) 2015 yeah!", attrs.getValue("Subsystem-Copyright")); + assertEquals("Extra subsystem headers can go here including very long ones " + + "that would span multiple lines in a manifest", attrs.getValue("Subsystem-Description")); + assertEquals("org.apache.sling.commons.osgi;version=2.3.0;type=osgi.bundle;start-order:=0," + + "org.apache.sling.commons.json;version=2.0.12;type=osgi.bundle;start-order:=10," + + "org.apache.sling.commons.mime;version=2.1.8;type=osgi.bundle;start-order:=10", + attrs.getValue("Subsystem-Content")); + break; + case "org.apache.sling.commons.osgi-2.3.0.jar": + ZipEntry oze = jf.getEntry("Potential_Bundles/0/org.apache.sling.commons.osgi-2.3.0.jar"); + assertArtifactsEqual(oze.getName(), jf.getInputStream(oze), zis); + break; + case "org.apache.sling.commons.json-2.0.12.jar": + ZipEntry jze = jf.getEntry("Potential_Bundles/10/org.apache.sling.commons.json-2.0.12.jar"); + assertArtifactsEqual(jze.getName(), jf.getInputStream(jze), zis); + break; + case "org.apache.sling.commons.mime-2.1.8.jar": + ZipEntry mze = jf.getEntry("Potential_Bundles/10/org.apache.sling.commons.mime-2.1.8.jar"); + assertArtifactsEqual(mze.getName(), jf.getInputStream(mze), zis); + break; + } + } + } + assertEquals(new HashSet<>(Arrays.asList("OSGI-INF/SUBSYSTEM.MF", + "org.apache.sling.commons.osgi-2.3.0.jar", + "org.apache.sling.commons.json-2.0.12.jar", + "org.apache.sling.commons.mime-2.1.8.jar")), foundBundles); + + assertFalse("After closing the stream the temp file should have been deleted.", + dcis.file.exists()); + } + + @Test + public void testOtherRunMode() throws Exception { + SlingSettingsService slingSettings = Mockito.mock(SlingSettingsService.class); + Mockito.when(slingSettings.getRunModes()).thenReturn(new HashSet<String>(Arrays.asList("bar", "tar"))); + SubsystemBaseTransformer sbt = new SubsystemBaseTransformer(slingSettings); + + URL testArchive = getClass().getResource("/test1.subsystem-base"); + RegisteredResource resource = new TestRegisteredResource(testArchive); + TransformationResult[] tra = sbt.transform(resource); + assertEquals(1, tra.length); + TransformationResult tr = tra[0]; + assertEquals("esa", tr.getResourceType()); + assertEquals("test1", tr.getId()); + DeleteOnCloseFileInputStream dcis = (DeleteOnCloseFileInputStream) tr.getInputStream(); + assertTrue("The file backing the stream should exist", dcis.file.exists()); + + Set<String> foundBundles = new HashSet<>(); + try (ZipInputStream zis = new ZipInputStream(dcis); + JarFile jf = new JarFile(testArchive.getFile())) { + ZipEntry ze = null; + while((ze = zis.getNextEntry()) != null) { + foundBundles.add(ze.getName()); + switch(ze.getName()) { + case "OSGI-INF/SUBSYSTEM.MF": + Manifest mf = new Manifest(zis); + Attributes attrs = mf.getMainAttributes(); + assertEquals("test1", attrs.getValue("Subsystem-SymbolicName")); + assertEquals("osgi.subsystem.composite", attrs.getValue("Subsystem-Type")); + assertEquals("(c) 2015 yeah!", attrs.getValue("Subsystem-Copyright")); + assertEquals("Extra subsystem headers can go here including very long ones " + + "that would span multiple lines in a manifest", attrs.getValue("Subsystem-Description")); + assertEquals("org.apache.sling.commons.osgi;version=2.3.0;type=osgi.bundle;start-order:=0," + + "org.apache.sling.commons.json;version=2.0.12;type=osgi.bundle;start-order:=10," + + "org.apache.sling.commons.mime;version=2.1.8;type=osgi.bundle;start-order:=10," + + "org.apache.sling.commons.threads;version=3.2.0;type=osgi.bundle;start-order:=20," + + "org.apache.sling.commons.contentdetection;version=1.0.2;type=osgi.bundle;start-order:=100", + attrs.getValue("Subsystem-Content")); + break; + case "org.apache.sling.commons.osgi-2.3.0.jar": + ZipEntry oze = jf.getEntry("Potential_Bundles/0/org.apache.sling.commons.osgi-2.3.0.jar"); + assertArtifactsEqual(oze.getName(), jf.getInputStream(oze), zis); + break; + case "org.apache.sling.commons.json-2.0.12.jar": + ZipEntry jze = jf.getEntry("Potential_Bundles/10/org.apache.sling.commons.json-2.0.12.jar"); + assertArtifactsEqual(jze.getName(), jf.getInputStream(jze), zis); + break; + case "org.apache.sling.commons.mime-2.1.8.jar": + ZipEntry mze = jf.getEntry("Potential_Bundles/10/org.apache.sling.commons.mime-2.1.8.jar"); + assertArtifactsEqual(mze.getName(), jf.getInputStream(mze), zis); + break; + case "org.apache.sling.commons.threads-3.2.0.jar": + ZipEntry tze = jf.getEntry("Potential_Bundles/20/org.apache.sling.commons.threads-3.2.0.jar"); + assertArtifactsEqual(tze.getName(), jf.getInputStream(tze), zis); + break; + case "org.apache.sling.commons.contentdetection-1.0.2.jar": + ZipEntry cze = jf.getEntry("Potential_Bundles/100/org.apache.sling.commons.contentdetection-1.0.2.jar"); + assertArtifactsEqual(cze.getName(), jf.getInputStream(cze), zis); + break; + } + } + } + assertEquals(new HashSet<>(Arrays.asList("OSGI-INF/SUBSYSTEM.MF", + "org.apache.sling.commons.osgi-2.3.0.jar", + "org.apache.sling.commons.json-2.0.12.jar", + "org.apache.sling.commons.mime-2.1.8.jar", + "org.apache.sling.commons.threads-3.2.0.jar", + "org.apache.sling.commons.contentdetection-1.0.2.jar")), foundBundles); + + assertFalse("After closing the stream the temp file should have been deleted.", + dcis.file.exists()); + } + + private void assertArtifactsEqual(String name, InputStream is1, InputStream is2) throws IOException { + byte[] bytes1 = suckStreams(is1); + byte[] bytes2 = suckStreams(is2); + assertArrayEquals(name, bytes1, bytes2); + } + + public static void pumpStreams(InputStream is, OutputStream os) throws IOException { + byte[] bytes = new byte[16384]; + + 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); + } + } + + public static byte [] suckStreams(InputStream is) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + pumpStreams(is, baos); + return baos.toByteArray(); + } + + private static class TestRegisteredResource implements RegisteredResource { + private final URL resourceURL; + + TestRegisteredResource(URL url) { + resourceURL = url; + } + + @Override + public String getScheme() { + return resourceURL.getProtocol(); + } + + @Override + public String getURL() { + return resourceURL.toExternalForm(); + } + + @Override + public String getType() { + return "file"; + } + + @Override + public InputStream getInputStream() throws IOException { + return resourceURL.openStream(); + } + + @Override + public Dictionary<String, Object> getDictionary() { + return null; + } + + @Override + public String getDigest() { + return null; + } + + @Override + public int getPriority() { + return 0; + } + + @Override + public String getEntityId() { + return null; + } + } +} diff --git a/src/test/resources/test1.subsystem-base b/src/test/resources/test1.subsystem-base new file mode 100644 index 0000000..434ace7 Binary files /dev/null and b/src/test/resources/test1.subsystem-base differ -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
