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]>.

Reply via email to