You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2015/06/10 12:49:17 UTC

svn commit: r1684637 - in /sling/whiteboard/bdelacretaz/crankstart3/launcher: ./ src/main/java/org/apache/sling/crankstart/launcher/ src/test/resources/

Author: bdelacretaz
Date: Wed Jun 10 10:49:16 2015
New Revision: 1684637

URL: http://svn.apache.org/r1684637
Log:
SLING-4728 - work in progress - OSGi framework starts

Added:
    sling/whiteboard/bdelacretaz/crankstart3/launcher/src/main/java/org/apache/sling/crankstart/launcher/CrankstartModelHelper.java
    sling/whiteboard/bdelacretaz/crankstart3/launcher/src/main/java/org/apache/sling/crankstart/launcher/Launcher.java
      - copied, changed from r1684398, sling/whiteboard/bdelacretaz/crankstart3/launcher/src/main/java/org/apache/sling/crankstart/launcher/Main.java
    sling/whiteboard/bdelacretaz/crankstart3/launcher/src/test/resources/crankstart-model.txt
      - copied, changed from r1684404, sling/whiteboard/bdelacretaz/crankstart3/launcher/src/test/resources/launcher-test.crank.txt
Removed:
    sling/whiteboard/bdelacretaz/crankstart3/launcher/src/main/java/org/apache/sling/crankstart/launcher/Main.java
    sling/whiteboard/bdelacretaz/crankstart3/launcher/src/test/resources/launcher-test.crank.txt
Modified:
    sling/whiteboard/bdelacretaz/crankstart3/launcher/pom.xml
    sling/whiteboard/bdelacretaz/crankstart3/launcher/src/main/java/org/apache/sling/crankstart/launcher/CrankstartBootstrap.java

Modified: sling/whiteboard/bdelacretaz/crankstart3/launcher/pom.xml
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/crankstart3/launcher/pom.xml?rev=1684637&r1=1684636&r2=1684637&view=diff
==============================================================================
--- sling/whiteboard/bdelacretaz/crankstart3/launcher/pom.xml (original)
+++ sling/whiteboard/bdelacretaz/crankstart3/launcher/pom.xml Wed Jun 10 10:49:16 2015
@@ -40,7 +40,7 @@
                 <configuration>
                     <archive>
                         <manifest>
-                            <mainClass>org.apache.sling.crankstart.launcher.Main</mainClass>
+                            <mainClass>org.apache.sling.crankstart.launcher.Launcher</mainClass>
                             <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                         </manifest>
                     </archive>
@@ -56,7 +56,7 @@
                             <goal>unpack-dependencies</goal>
                         </goals>
                         <configuration>
-                            <includeGroupIds>org.slf4j,org.ops4j.pax.url</includeGroupIds>
+                            <includeGroupIds>org.slf4j,org.ops4j.pax.url,org.apache.sling</includeGroupIds>
                             <excludeTransitive>false</excludeTransitive>
                             <outputDirectory>${project.build.directory}/classes</outputDirectory>
                             <overWriteReleases>false</overWriteReleases>
@@ -81,7 +81,7 @@
                         <fileset>
                             <directory>${basedir}</directory>
                             <includes>
-                                <include>sling-crankstart</include>
+                                <include>CRANKSTART</include>
                             </includes>
                         </fileset>
                     </filesets>
@@ -101,34 +101,16 @@
     </build>   
 
     <dependencies>
-        <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.crankstart.api</artifactId>
-            <version>1.0.1-SNAPSHOT</version>
+       <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+            <version>4.2.0</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.crankstart.api.fragment</artifactId>
-            <version>1.0.3-SNAPSHOT</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.crankstart.core</artifactId>
-            <version>1.0.1-SNAPSHOT</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-	    <groupId>org.apache.sling</groupId>
-	    <artifactId>org.apache.sling.crankstart.test.services</artifactId>
-            <version>1.0.1-SNAPSHOT</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-	    <groupId>org.apache.sling</groupId>
-	    <artifactId>org.apache.sling.crankstart.sling.extensions</artifactId>
-            <version>1.0.1-SNAPSHOT</version>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.framework</artifactId>
+            <version>4.0.0</version>
             <scope>provided</scope>
         </dependency>
          <dependency>
@@ -144,6 +126,12 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.provisioning.model</artifactId>
+            <version>1.1.0</version>
+            <scope>provided</scope>
+        </dependency>
+         <dependency>
             <groupId>org.ops4j.pax.url</groupId>
             <artifactId>pax-url-aether</artifactId>
             <version>${pax.url.version}</version>

Modified: sling/whiteboard/bdelacretaz/crankstart3/launcher/src/main/java/org/apache/sling/crankstart/launcher/CrankstartBootstrap.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/crankstart3/launcher/src/main/java/org/apache/sling/crankstart/launcher/CrankstartBootstrap.java?rev=1684637&r1=1684636&r2=1684637&view=diff
==============================================================================
--- sling/whiteboard/bdelacretaz/crankstart3/launcher/src/main/java/org/apache/sling/crankstart/launcher/CrankstartBootstrap.java (original)
+++ sling/whiteboard/bdelacretaz/crankstart3/launcher/src/main/java/org/apache/sling/crankstart/launcher/CrankstartBootstrap.java Wed Jun 10 10:49:16 2015
@@ -29,8 +29,6 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.Callable;
 
-import org.apache.sling.crankstart.api.CrankstartConstants;
-
 /** Execute a crankstart file */
 public class CrankstartBootstrap {
     public static final String CLASSPATH_PREFIX = "classpath ";
@@ -68,7 +66,7 @@ public class CrankstartBootstrap {
 
     
     public void start() throws Exception {
-        System.setProperty(CrankstartConstants.CRANKSTART_INPUT_FILENAME, crankFile);
+        //System.setProperty(CrankstartConstants.CRANKSTART_INPUT_FILENAME, crankFile);
         System.setProperty( "java.protocol.handler.pkgs", "org.ops4j.pax.url" );
         final URL [] launcherClasspath = getClasspath(crankFile);
         

Added: sling/whiteboard/bdelacretaz/crankstart3/launcher/src/main/java/org/apache/sling/crankstart/launcher/CrankstartModelHelper.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/crankstart3/launcher/src/main/java/org/apache/sling/crankstart/launcher/CrankstartModelHelper.java?rev=1684637&view=auto
==============================================================================
--- sling/whiteboard/bdelacretaz/crankstart3/launcher/src/main/java/org/apache/sling/crankstart/launcher/CrankstartModelHelper.java (added)
+++ sling/whiteboard/bdelacretaz/crankstart3/launcher/src/main/java/org/apache/sling/crankstart/launcher/CrankstartModelHelper.java Wed Jun 10 10:49:16 2015
@@ -0,0 +1,63 @@
+/*
+ * 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.crankstart.launcher;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+import org.apache.sling.provisioning.model.Model;
+import org.apache.sling.provisioning.model.ModelUtility;
+import org.apache.sling.provisioning.model.io.ModelReader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Read and merge 1..N Sling provisioning models based on file and folder names */ 
+public class CrankstartModelHelper {
+    public static final String MODEL_FILE_EXT = ".txt";
+    private final Model model = new Model();
+    private final Logger log = LoggerFactory.getLogger(getClass());
+    
+    public void read(String ... filesOrFolderNames) throws IOException {
+        for(String name : filesOrFolderNames) {
+            final File f = new File(name);
+            if(f.isDirectory()) {
+                final String [] list = f.list();
+                for(String s : list) {
+                    merge(new File(f, s));
+                }
+            } else {
+                merge(f);
+            }
+        }
+    }
+    
+    public Model getModel() {
+        return model;
+    }
+    
+    private void merge(File f) throws IOException {
+        if(!f.getName().endsWith(MODEL_FILE_EXT)) {
+            log.warn("Model filename does not end with {}, ignored: {}", MODEL_FILE_EXT, f.getAbsolutePath());
+            return;
+        }
+        log.info("Merging model file {}", f.getAbsolutePath());
+        final BufferedReader reader = new BufferedReader(new FileReader(f));
+        ModelUtility.merge(model,  ModelReader.read(reader, f.getAbsolutePath()));
+    }
+}
\ No newline at end of file

Copied: sling/whiteboard/bdelacretaz/crankstart3/launcher/src/main/java/org/apache/sling/crankstart/launcher/Launcher.java (from r1684398, sling/whiteboard/bdelacretaz/crankstart3/launcher/src/main/java/org/apache/sling/crankstart/launcher/Main.java)
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/crankstart3/launcher/src/main/java/org/apache/sling/crankstart/launcher/Launcher.java?p2=sling/whiteboard/bdelacretaz/crankstart3/launcher/src/main/java/org/apache/sling/crankstart/launcher/Launcher.java&p1=sling/whiteboard/bdelacretaz/crankstart3/launcher/src/main/java/org/apache/sling/crankstart/launcher/Main.java&r1=1684398&r2=1684637&rev=1684637&view=diff
==============================================================================
--- sling/whiteboard/bdelacretaz/crankstart3/launcher/src/main/java/org/apache/sling/crankstart/launcher/Main.java (original)
+++ sling/whiteboard/bdelacretaz/crankstart3/launcher/src/main/java/org/apache/sling/crankstart/launcher/Launcher.java Wed Jun 10 10:49:16 2015
@@ -16,21 +16,132 @@
  */
 package org.apache.sling.crankstart.launcher;
 
-import org.apache.sling.crankstart.api.CrankstartConstants;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
-/** Execute a crankstart file */
-public class Main {
-    public static final String CLASSPATH_PREFIX = "classpath ";
+import org.apache.sling.provisioning.model.Artifact;
+import org.apache.sling.provisioning.model.ArtifactGroup;
+import org.apache.sling.provisioning.model.Feature;
+import org.apache.sling.provisioning.model.Model;
+import org.apache.sling.provisioning.model.ModelUtility;
+import org.apache.sling.provisioning.model.RunMode;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.launch.FrameworkFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Launch an OSGi app instance using the Sling provisioning model */
+public class Launcher {
+    private Model model;
+    private final Logger log = LoggerFactory.getLogger(getClass());
     
-    public static void main(String [] args) throws Exception {
-        String crankFile = "default.crank.txt";
-        if(args.length < 1) {
-            System.err.println("Using default crank file " + crankFile);
-            System.err.println("To use a different one, provide its name as a jar file argument");
+    public Launcher(String [] args) throws IOException {
+        final CrankstartModelHelper mr = new CrankstartModelHelper();
+        mr.read(args);
+        model = ModelUtility.getEffectiveModel(mr.getModel(), null);
+    }
+    
+    public void launch() throws Exception {
+        // Enable pax URL for mvn: protocol
+        System.setProperty( "java.protocol.handler.pkgs", "org.ops4j.pax.url" );
+
+        // Setup initial classpath to launch the OSGi framework
+        for(URL u : getClasspathURLs(model, ":crankstart")) {
+            addToClasspath(u);
+        }
+        
+        final Map<String, String> frameworkConfig = new HashMap<String, String>();
+        
+        // Start the OSGi framework
+        final FrameworkFactory factory = (FrameworkFactory)getClass().getClassLoader().loadClass("org.apache.felix.framework.FrameworkFactory").newInstance();
+        final Framework f = factory.newFramework(frameworkConfig);
+        f.start();
+        setShutdownHook(f);
+        log.info("OSGi framework started, waiting for it to stop");
+        f.waitForStop(0);
+    }
+    
+    /** Slightly hacky way to add URLs to the system classloader,
+     *  based on http://stackoverflow.com/questions/60764/how-should-i-load-jars-dynamically-at-runtime
+     */  
+    private void addToClasspath(URL u) throws IOException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+        final URLClassLoader sysLoader = (URLClassLoader)ClassLoader.getSystemClassLoader();
+        final Method m = URLClassLoader.class.getDeclaredMethod("addURL",new Class[]{URL.class});
+        m.setAccessible(true);
+        m.invoke(sysLoader,new Object[]{ u });
+        log.info("Added to classpath: {}", u);
+    }
+    
+    /** Convert a Model feature to a set of URLs meant to setup
+     *  an URLClassLoader.
+     */
+    List<URL> getClasspathURLs(Model m, String featureName) throws MalformedURLException {
+        final List<URL> result = new ArrayList<URL>();
+        
+        // Add all URLs from the special feature to our classpath
+        final Feature f = m.getFeature(featureName);
+        if(f == null) {
+            log.warn("No {} feature found in provisioning model, nothing to add to our classpath", featureName);
         } else {
-            crankFile = args[0];
+            for(RunMode rm : f.getRunModes()) {
+                for(ArtifactGroup g : rm.getArtifactGroups()) {
+                    for(Artifact a : g) {
+                        final String url = mvnUrl(a);
+                        try {
+                            result.add(new URL(url));
+                        } catch(MalformedURLException e) {
+                            final MalformedURLException up = new MalformedURLException("Invalid URL [" + url + "]");
+                            up.initCause(e);
+                            throw up;
+                        }
+                    }
+                }
+            }
+        }
+        return result;
+    }
+    
+    public static String mvnUrl(Artifact a) {
+        return "mvn:" + a.getGroupId() + "/" + a.getArtifactId() + "/" + a.getVersion();
+    }
+    
+    private void setShutdownHook(final Framework osgiFramework) {
+        // Shutdown the framework when the JVM exits
+        Runtime.getRuntime().addShutdownHook(new Thread() {
+            @Override
+            public void run() {
+                if(osgiFramework != null && osgiFramework.getState() == Bundle.ACTIVE) {
+                    try {
+                        log.info("Stopping the OSGi framework");
+                        osgiFramework.stop();
+                        log.info("Waiting for the OSGi framework to exit");
+                        osgiFramework.waitForStop(0);
+                        log.info("OSGi framework stopped");
+                    } catch(Exception e) {
+                        log.error("Exception while stopping OSGi framework", e);
+                    }
+                }
+            }
+        });
+    }
+    
+     public static void main(String [] args) throws Exception {
+        if(args.length < 1) {
+            System.err.println("Usage: Main provisioning-model [provisioning-model ...]"); 
+            System.err.println("Where provisioning-model is either a Sling provisioning model file");
+            System.err.println("or a folder that contains oseveral of those.");
+            System.exit(0);
         }
-        System.setProperty(CrankstartConstants.CRANKSTART_JAR_PATH, Main.class.getProtectionDomain().getCodeSource().getLocation().getPath());
-        new CrankstartBootstrap(crankFile).start();
+        
+        new Launcher(args).launch();
     }
 }
\ No newline at end of file

Copied: sling/whiteboard/bdelacretaz/crankstart3/launcher/src/test/resources/crankstart-model.txt (from r1684404, sling/whiteboard/bdelacretaz/crankstart3/launcher/src/test/resources/launcher-test.crank.txt)
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/crankstart3/launcher/src/test/resources/crankstart-model.txt?p2=sling/whiteboard/bdelacretaz/crankstart3/launcher/src/test/resources/crankstart-model.txt&p1=sling/whiteboard/bdelacretaz/crankstart3/launcher/src/test/resources/launcher-test.crank.txt&r1=1684404&r2=1684637&rev=1684637&view=diff
==============================================================================
--- sling/whiteboard/bdelacretaz/crankstart3/launcher/src/test/resources/launcher-test.crank.txt (original)
+++ sling/whiteboard/bdelacretaz/crankstart3/launcher/src/test/resources/crankstart-model.txt Wed Jun 10 10:49:16 2015
@@ -1,67 +1,56 @@
+[feature name=:crankstart]
+
 # Test the crankstart launcher by setting up an HTTP
 # server with a few servlets that require specific OSGi configurations
 
 # Default values for our variables
-defaults single.path /single
+# defaults single.path /single
 
-# Bootstrap classpath (variables are not supported here)
-classpath mvn:org.apache.felix/org.apache.felix.framework/4.4.0
-classpath mvn:org.slf4j/slf4j-api/1.6.2
-classpath mvn:org.slf4j/slf4j-simple/1.6.2
-classpath mvn:org.apache.sling/org.apache.sling.crankstart.core/1.0.1-SNAPSHOT
-classpath mvn:org.apache.sling/org.apache.sling.crankstart.api/1.0.1-SNAPSHOT
-classpath mvn:org.apache.sling/org.apache.sling.provisioning.model/1.1.0
+[variables]
+  felix.framework.version=4.4.0
+  slf4j.version = 1.6.2
+  http.port = 8080
+  osgi.storage.path = CRANKSTART
+  
+[settings]
+  org.osgi.service.http.port = ${http.port}
+  org.osgi.framework.storage = ${osgi.storage.path}
+  
+[artifacts]
+  org.apache.felix/org.apache.felix.framework/${felix.framework.version}
+  org.slf4j/slf4j-api/${slf4j.version}
+  org.slf4j/slf4j-simple/${slf4j.version}
 
 # OSGi properties
-osgi.property org.osgi.service.http.port ${http.port}
-osgi.property org.osgi.framework.storage ${osgi.storage.path}
-
-# Start the framework. Crankstart file processing will stop here
-# if this is not the first startup.
-start.framework
+#osgi.property org.osgi.service.http.port ${http.port}
+#osgi.property org.osgi.framework.storage ${osgi.storage.path}
 
 # The crankstart.api.fragment bundle makes the crankstart.api package available
 # to bundles, required for bundles to provide crankstart extension commands like
 # the test.system.property command below
-bundle mvn:org.apache.sling/org.apache.sling.crankstart.api.fragment/1.0.2
-bundle mvn:org.apache.sling/org.apache.sling.crankstart3.test.services/1.0.3-SNAPSHOT
-
-# Add provisioning model artifacts
-# TODO move all bundles there
-provisioning.model src/test/resources/provisioning-model
- 
-# Now start our bundles
-start.all.bundles
+#bundle mvn:org.apache.sling/org.apache.sling.crankstart.api.fragment/1.0.2
+#bundle mvn:org.apache.sling/org.apache.sling.crankstart3.test.services/1.0.3-SNAPSHOT
 
 # OSGi configs that activate our test servlets
-config org.apache.sling.crankstart.testservices.SingleConfigServlet
-  path=${single.path}
-  message=doesn't matter
-
-config.factory org.apache.sling.crankstart.testservices.ConfigFactoryServlet
-  CRANKSTART_CONFIG_ID=some.unique.ID
-  path=/foo
-  message=Not used
+#config org.apache.sling.crankstart.testservices.SingleConfigServlet
+#  path=${single.path}
+#  message=doesn't matter
+
+#config.factory org.apache.sling.crankstart.testservices.ConfigFactoryServlet
+#  CRANKSTART_CONFIG_ID=some.unique.ID
+#  path=/foo
+#  message=Not used
   
-config.factory org.apache.sling.crankstart.testservices.ConfigFactoryServlet
-  path=/bar/test
-  message=Not used
+#config.factory org.apache.sling.crankstart.testservices.ConfigFactoryServlet
+#  path=/bar/test
+#  message=Not used
   
 # Test Felix format configs
-config felix.format.test FORMAT:felix.config
-  mongouri="mongodb://localhost:27017"
-  service.ranking.launcher.test=I"54321"
-  array=["foo","bar.from.launcher.test"]
-  
-config empty.config.should.work FORMAT:felix.config
+#config felix.format.test FORMAT:felix.config
+#  mongouri="mongodb://localhost:27017"
+#  service.ranking.launcher.test=I"54321"
+#  array=["foo","bar.from.launcher.test"]
   
-# Prepare additional resources for the Sling installer
-sling.installer.resource mvn:org.apache.sling/org.apache.sling.junit.core/1.0.8
-sling.installer.resource mvn:org.apache.sling/org.apache.sling.commons.mime/2.1.4
-sling.installer.resource mvn:org.apache.sling/org.apache.sling.settings/1.3.0
-
-# And register the installer resources
-sling.installer.register crankstart
+#config empty.config.should.work FORMAT:felix.config
 
-# Informative log  
-log felix http service should come up at http://localhost:${http.port}
+[configurations]
\ No newline at end of file