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

cziegeler pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-launcher.git


The following commit(s) were added to refs/heads/master by this push:
     new 80ffa27  SLING-9413 : Provide the Ability for the Launcher to start 
with Feature Archive(s)
80ffa27 is described below

commit 80ffa27a832989fbdf42cde2181cbdcde2826601
Author: Carsten Ziegeler <[email protected]>
AuthorDate: Fri May 1 14:40:33 2020 +0200

    SLING-9413 : Provide the Ability for the Launcher to start with Feature 
Archive(s)
---
 pom.xml                                            | 28 +++++---
 .../sling/feature/launcher/impl/Bootstrap.java     |  5 +-
 .../feature/launcher/impl/FeatureProcessor.java    | 79 +++++++++++++++++-----
 .../sling/feature/launcher/impl/Installation.java  |  1 -
 .../feature/launcher/impl/LauncherConfig.java      | 10 +--
 .../apache/sling/feature/launcher/impl/Main.java   | 15 ++--
 .../launcher/impl/launchers/FrameworkLauncher.java |  1 +
 7 files changed, 98 insertions(+), 41 deletions(-)

diff --git a/pom.xml b/pom.xml
index 5a039e3..0f5f5f1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -56,7 +56,7 @@
                         
<outputDirectory>${project.build.directory}/classes</outputDirectory>
                         <overWriteReleases>false</overWriteReleases>
                         <overWriteSnapshots>true</overWriteSnapshots>
-                        
<includeArtifactIds>osgi.core,commons-text,org.apache.sling.feature,org.apache.sling.feature.io,org.apache.sling.commons.johnzon,org.apache.felix.converter,commons-cli,slf4j-api,slf4j-simple</includeArtifactIds>
+                        
<includeArtifactIds>osgi.core,commons-text,commons-lang3,org.apache.sling.feature,org.osgi.util.function,org.apache.felix.cm.json,org.apache.sling.commons.johnzon,org.apache.felix.converter,commons-cli,slf4j-api,slf4j-simple</includeArtifactIds>
                     </configuration>
                 </execution>
             </executions>
@@ -95,6 +95,12 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>3.10</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>osgi.core</artifactId>
             <version>7.0.0</version>
@@ -113,19 +119,25 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.feature</artifactId>
-            <version>1.1.8</version>
+            <version>1.2.1-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.feature.io</artifactId>
-            <version>1.3.0</version>
-            <scope>provided</scope>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.util.function</artifactId>
+            <version>1.0.0</version>
+            <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.felix</groupId>
             <artifactId>org.apache.felix.converter</artifactId>
-            <version>1.0.12</version>
+            <version>1.0.14</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.cm.json</artifactId>
+            <version>1.0.2</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
@@ -137,7 +149,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.commons.johnzon</artifactId>
-            <version>1.1.0</version>
+            <version>1.2.2</version>
             <scope>provided</scope>
         </dependency>
 
diff --git 
a/src/main/java/org/apache/sling/feature/launcher/impl/Bootstrap.java 
b/src/main/java/org/apache/sling/feature/launcher/impl/Bootstrap.java
index 47ee97c..e736d8d 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/Bootstrap.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/Bootstrap.java
@@ -19,7 +19,6 @@ package org.apache.sling.feature.launcher.impl;
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
-import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -126,7 +125,7 @@ public class Bootstrap {
             this.logger.info("Assembling provisioning model...");
 
             try {
-                boolean restart = this.config.getFeatureFiles().length == 0;
+                final boolean restart = 
this.config.getFeatureFiles().isEmpty();
 
                 Map<ArtifactId, Feature> loadedFeatures = new HashMap<>();
                 final Feature app = assemble(artifactManager, loadedFeatures);
@@ -188,7 +187,7 @@ public class Bootstrap {
     private Feature assemble(final ArtifactManager artifactManager,
             Map<ArtifactId, Feature> loadedFeatures) throws IOException
     {
-        if (this.config.getFeatureFiles().length == 0) {
+        if (this.config.getFeatureFiles().isEmpty() ) {
             File application = getApplicationFeatureFile(this.config);
             if (application.isFile()) {
                 
this.config.addFeatureFiles(application.toURI().toURL().toString());
diff --git 
a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java 
b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
index 764afab..ac1815b 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
@@ -16,8 +16,12 @@
  */
 package org.apache.sling.feature.launcher.impl;
 
+import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.io.OutputStream;
 import java.io.Reader;
 import java.net.URL;
 import java.util.ArrayList;
@@ -32,12 +36,15 @@ import org.apache.sling.feature.Artifact;
 import org.apache.sling.feature.ArtifactId;
 import org.apache.sling.feature.Configuration;
 import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.ExtensionState;
 import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.builder.ArtifactProvider;
 import org.apache.sling.feature.builder.BuilderContext;
 import org.apache.sling.feature.builder.FeatureBuilder;
 import org.apache.sling.feature.builder.MergeHandler;
 import org.apache.sling.feature.builder.PostProcessHandler;
 import org.apache.sling.feature.io.IOUtils;
+import org.apache.sling.feature.io.archive.ArchiveReader;
 import org.apache.sling.feature.io.artifacts.ArtifactHandler;
 import org.apache.sling.feature.io.artifacts.ArtifactManager;
 import org.apache.sling.feature.io.json.FeatureJSONReader;
@@ -71,16 +78,22 @@ public class FeatureProcessor {
                 return null;
             }
         });
-        builderContext.setArtifactProvider(id -> {
-            try {
-                final ArtifactHandler handler = 
artifactManager.getArtifactHandler(id.toMvnUrl());
-                return handler.getLocalURL();
-            } catch (final IOException e) {
-                // ignore
-                return null;
+        final ArtifactProvider provider = new ArtifactProvider() {
+
+            @Override
+            public URL provide(final ArtifactId id) {
+                try {
+                    final ArtifactHandler handler = 
artifactManager.getArtifactHandler(id.toMvnUrl());
+                    return handler.getLocalURL();
+                } catch (final IOException e) {
+                    // ignore
+                    return null;
+                }
             }
-        });
-        
builderContext.addArtifactsOverrides(config.getArtifactClashOverrides());
+        };
+        builderContext.setArtifactProvider(provider);
+
+        config.getArtifactClashOverrides().stream().forEach(id -> 
builderContext.addArtifactsOverride(id));
         builderContext.addConfigsOverrides(config.getConfigClashOverrides());
         builderContext.addVariablesOverrides(config.getVariables());
         
builderContext.addFrameworkPropertiesOverrides(config.getInstallation().getFrameworkProperties());
@@ -95,16 +108,46 @@ public class FeatureProcessor {
         }
 
         List<Feature> features = new ArrayList<>();
+        final byte[] buffer = new byte[1024*1024*256];
         for (final String featureFile : config.getFeatureFiles()) {
             for (final String initFile : 
IOUtils.getFeatureFiles(config.getHomeDirectory(), featureFile)) {
-                logger.debug("Reading feature file {}", initFile);
-                final ArtifactHandler featureArtifact = 
artifactManager.getArtifactHandler(initFile);
-                try (final Reader r = new 
InputStreamReader(featureArtifact.getLocalURL().openStream(), "UTF-8")) {
-                    final Feature f = FeatureJSONReader.read(r, 
featureArtifact.getUrl());
-                    loadedFeatures.put(f.getId(), f);
-                    features.add(f);
-                } catch (Exception ex) {
-                    throw new IOException("Error reading feature: " + 
initFile, ex);
+                if ( initFile.endsWith(IOUtils.EXTENSION_FEATURE_ARCHIVE) ) {
+                    logger.debug("Reading feature archive {}", initFile);
+                    final ArtifactHandler featureArtifact = 
artifactManager.getArtifactHandler(initFile);
+                    try (final InputStream is = 
featureArtifact.getLocalURL().openStream()) {
+                        for(final Feature feature : ArchiveReader.read(is, 
(id, stream) -> {
+
+                                if ( provider.provide(id) == null ) {
+                                    final File artifactFile = new 
File(config.getCacheDirectory(),
+                                            id.toMvnPath().replace('/', 
File.separatorChar));
+                                    if (!artifactFile.exists()) {
+                                        artifactFile.getParentFile().mkdirs();
+                                        try (final OutputStream os = new 
FileOutputStream(artifactFile)) {
+                                            int l = 0;
+                                            while ((l = stream.read(buffer)) > 
0) {
+                                                os.write(buffer, 0, l);
+                                            }
+                                        }
+                                    }
+                                }
+                            })) {
+
+                            features.add(feature);
+                            loadedFeatures.put(feature.getId(), feature);
+                        }
+                    } catch (final IOException ioe) {
+                        logger.info("Unable to read feature archive from " + 
initFile, ioe);
+                    }
+                } else {
+                    logger.debug("Reading feature file {}", initFile);
+                    final ArtifactHandler featureArtifact = 
artifactManager.getArtifactHandler(initFile);
+                    try (final Reader r = new 
InputStreamReader(featureArtifact.getLocalURL().openStream(), "UTF-8")) {
+                        final Feature f = FeatureJSONReader.read(r, 
featureArtifact.getUrl());
+                        loadedFeatures.put(f.getId(), f);
+                        features.add(f);
+                    } catch (Exception ex) {
+                        throw new IOException("Error reading feature: " + 
initFile, ex);
+                    }
                 }
             }
         }
@@ -170,7 +213,7 @@ public class FeatureProcessor {
                     continue extensions;
                 }
             }
-            if ( ext.isRequired() ) {
+            if ( ext.getState() == ExtensionState.REQUIRED ) {
                 throw new Exception("Unknown required extension " + 
ext.getName());
             }
         }
diff --git 
a/src/main/java/org/apache/sling/feature/launcher/impl/Installation.java 
b/src/main/java/org/apache/sling/feature/launcher/impl/Installation.java
index 9a32143..f1945b3 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/Installation.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/Installation.java
@@ -16,7 +16,6 @@
  */
 package org.apache.sling.feature.launcher.impl;
 
-import java.io.File;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Dictionary;
diff --git 
a/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java 
b/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java
index bacb449..5766046 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java
@@ -19,12 +19,14 @@ package org.apache.sling.feature.launcher.impl;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.sling.feature.ArtifactId;
 import org.apache.sling.feature.io.artifacts.ArtifactManagerConfig;
 import org.apache.sling.feature.io.artifacts.spi.ArtifactProviderContext;
 
@@ -39,7 +41,7 @@ public class LauncherConfig
 
     private static final String CACHE_DIR = "cache";
 
-    private final List<String> artifactClashOverrides = new ArrayList<>();
+    private final List<ArtifactId> artifactClashOverrides = new ArrayList<>();
 
     private final Map<String,String> configClashOverrides = new 
LinkedHashMap<>();
 
@@ -66,7 +68,7 @@ public class LauncherConfig
         this.setCacheDirectory(new File(getHomeDirectory(), CACHE_DIR));
     }
 
-    public List<String> getArtifactClashOverrides() {
+    public List<ArtifactId> getArtifactClashOverrides() {
         return this.artifactClashOverrides;
     }
 
@@ -90,8 +92,8 @@ public class LauncherConfig
      * Get the list of feature files.
      * @return The array of names.
      */
-    public String[] getFeatureFiles() {
-        return this.featureFiles.toArray(new String[0]);
+    public Collection<String> getFeatureFiles() {
+        return this.featureFiles;
     }
 
     /**
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/Main.java 
b/src/main/java/org/apache/sling/feature/launcher/impl/Main.java
index 0ecef1f..0267c4d 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/Main.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/Main.java
@@ -16,6 +16,12 @@
  */
 package org.apache.sling.feature.launcher.impl;
 
+import java.io.File;
+import java.util.AbstractMap;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
 import org.apache.commons.cli.BasicParser;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.CommandLineParser;
@@ -23,15 +29,10 @@ import org.apache.commons.cli.HelpFormatter;
 import org.apache.commons.cli.Option;
 import org.apache.commons.cli.Options;
 import org.apache.commons.cli.ParseException;
+import org.apache.sling.feature.ArtifactId;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.File;
-import java.util.AbstractMap;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
 /**
  * This is the launcher main class.
  * It parses command line parameters and prepares the launcher.
@@ -118,7 +119,7 @@ public class Main {
             }
             if ( cl.hasOption(artifactClashOverride.getOpt()) ) {
                 for(final String override : 
cl.getOptionValues(artifactClashOverride.getOpt())) {
-                    config.getArtifactClashOverrides().add(override);
+                    
config.getArtifactClashOverrides().add(ArtifactId.parse(override));
                 }
             }
             if ( cl.hasOption(configClashOverride.getOpt()) ) {
diff --git 
a/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java
 
b/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java
index 197f360..2aa9599 100644
--- 
a/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java
+++ 
b/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java
@@ -94,6 +94,7 @@ public class FrameworkLauncher implements Launcher {
         final Constructor<?> constructor = 
runnerClass.getDeclaredConstructor(Map.class, Map.class, List.class,
                 List.class);
         constructor.setAccessible(true);
+        @SuppressWarnings("unchecked")
         Callable<Integer> restart = (Callable<Integer>) 
constructor.newInstance(properties, context.getBundleMap(),
                 context.getConfigurations(), 
context.getInstallableArtifacts());
 

Reply via email to