You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by fm...@apache.org on 2007/12/18 11:25:29 UTC
svn commit: r605168 - in
/incubator/sling/trunk/launcher/app/src/main/java/org/apache/sling/launcher/app:
BootstrapInstaller.java Sling.java
Author: fmeschbe
Date: Tue Dec 18 02:25:25 2007
New Revision: 605168
URL: http://svn.apache.org/viewvc?rev=605168&view=rev
Log:
SLING-138 Implement bootstrap bundle installation not done by the
Felix framework anymore.
Added:
incubator/sling/trunk/launcher/app/src/main/java/org/apache/sling/launcher/app/BootstrapInstaller.java
Modified:
incubator/sling/trunk/launcher/app/src/main/java/org/apache/sling/launcher/app/Sling.java
Added: incubator/sling/trunk/launcher/app/src/main/java/org/apache/sling/launcher/app/BootstrapInstaller.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/launcher/app/src/main/java/org/apache/sling/launcher/app/BootstrapInstaller.java?rev=605168&view=auto
==============================================================================
--- incubator/sling/trunk/launcher/app/src/main/java/org/apache/sling/launcher/app/BootstrapInstaller.java (added)
+++ incubator/sling/trunk/launcher/app/src/main/java/org/apache/sling/launcher/app/BootstrapInstaller.java Tue Dec 18 02:25:25 2007
@@ -0,0 +1,200 @@
+/*
+ * 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.launcher.app;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.startlevel.StartLevel;
+
+/**
+ * The <code>BootstrapInstaller</code> class is installed into the OSGi
+ * framework as an activator to be called when the framework is starting up.
+ * Upon startup all bundles from the {@link #PATH_CORE_BUNDLES} and the
+ * {@link #PATH_BUNDLES} location are checked whether they are already installed
+ * or not. If they are not installed, they are installed, their start level set
+ * to 1 and started. Any bundle already installed is not installed again and
+ * will also not be started here.
+ */
+class BootstrapInstaller implements BundleActivator {
+
+ /**
+ * The Bundle location scheme (protocol) used for bundles installed by this
+ * activator (value is "slinginstall:"). The path part of the Bundle
+ * location of Bundles installed by this class is the name (without the
+ * path) of the resource from which the Bundle was installed.
+ */
+ public static final String SCHEME = "slinginstall:";
+
+ /**
+ * The location the core Bundles (value is "resources/corebundles"). These
+ * bundles are installed first.
+ */
+ public static final String PATH_CORE_BUNDLES = "resources/corebundles";
+
+ /**
+ * The location the additional Bundles (value is "resources/bundles"). These
+ * Bundles are installed after the {@link #PATH_CORE_BUNDLES core Bundles}.
+ */
+ public static final String PATH_BUNDLES = "resources/bundles";
+
+ /**
+ * The {@link Logger} use for logging messages during installation and
+ * startup.
+ */
+ private final Logger logger;
+
+ /**
+ * The {@link ResourceProvider} used to access the Bundle jar files to
+ * install.
+ */
+ private final ResourceProvider resourceProvider;
+
+ BootstrapInstaller(Logger logger, ResourceProvider resourceProvider) {
+ this.logger = logger;
+ this.resourceProvider = resourceProvider;
+ }
+
+ /**
+ * Installs any Bundles missing in the current framework instance. The
+ * Bundles are verified by the Bundle location string. All missing Bundles
+ * are first installed and then started in the order of installation.
+ */
+ public void start(BundleContext context) throws Exception {
+
+ // list all existing bundles
+ Bundle[] bundles = context.getBundles();
+ Map<String, Bundle> byLocation = new HashMap<String, Bundle>();
+ for (int i = 0; i < bundles.length; i++) {
+ byLocation.put(bundles[i].getLocation(), bundles[i]);
+ }
+
+ // install bundles
+ List<Bundle> installed = new LinkedList<Bundle>();
+ installBundles(context, byLocation, PATH_CORE_BUNDLES, installed);
+ installBundles(context, byLocation, PATH_BUNDLES, installed);
+
+ // set start levels on the bundles and start them
+ startBundles(context, installed);
+ }
+
+ /** Nothing to be done on stop */
+ public void stop(BundleContext context) {
+ }
+
+ /**
+ * Install the Bundles from JAR files found in the given <code>parent</code>
+ * path.
+ *
+ * @param context The <code>BundleContext</code> used to install the new
+ * Bundles.
+ * @param currentBundles The currently installed Bundles indexed by their
+ * Bundle location.
+ * @param parent The path to the location in which to look for JAR files to
+ * install. Only resources whose name ends with <em>.jar</em>
+ * are considered for installation.
+ * @param installed The list of Bundles installed by this method. Each
+ * Bundle successfully installed is added to this list.
+ */
+ private void installBundles(BundleContext context,
+ Map<String, Bundle> currentBundles, String parent,
+ List<Bundle> installed) {
+
+ Iterator<String> res = resourceProvider.getChildren(parent);
+ while (res.hasNext()) {
+
+ String path = res.next();
+
+ if (path.endsWith(".jar")) {
+
+ // check for an already installed Bundle with the given location
+ String location = SCHEME
+ + path.substring(path.lastIndexOf('/') + 1);
+ if (currentBundles.containsKey(location)) {
+ continue;
+ }
+
+ // try to access the JAR file, ignore if not possible
+ InputStream ins = resourceProvider.getResourceAsStream(path);
+ if (ins == null) {
+ continue;
+ }
+
+ // install the JAR file as a bundle
+ Bundle newBundle;
+ try {
+ newBundle = context.installBundle(location, ins);
+ logger.log("Bundle " + newBundle.getSymbolicName()
+ + " installed from " + location);
+ } catch (BundleException be) {
+ logger.log("Bundle installation from " + location
+ + " failed", be);
+ continue;
+ }
+
+ // finally add the bundle to the list for later start
+ installed.add(newBundle);
+ }
+ }
+ }
+
+ /**
+ * Starts the Bundles in the <code>bundles</code> list. If the framework
+ * provides an active <code>StartLevel</code> service, the start levels of
+ * the Bundles is first set to <em>1</em>.
+ */
+ private void startBundles(BundleContext context, List<Bundle> bundles) {
+
+ // the start level service to set the initial start level
+ ServiceReference ref = context.getServiceReference(StartLevel.class.getName());
+ StartLevel startLevel = (ref != null)
+ ? (StartLevel) context.getService(ref)
+ : null;
+
+ // start all bundles
+ for (Bundle bundle : bundles) {
+
+ if (startLevel != null) {
+ startLevel.setBundleStartLevel(bundle, 1);
+ }
+
+ try {
+ bundle.start();
+ } catch (BundleException be) {
+ logger.log("Bundle " + bundle.getSymbolicName()
+ + " could not be started", be);
+ }
+ }
+
+ // release the start level service
+ if (ref != null) {
+ context.ungetService(ref);
+ }
+ }
+
+}
Modified: incubator/sling/trunk/launcher/app/src/main/java/org/apache/sling/launcher/app/Sling.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/launcher/app/src/main/java/org/apache/sling/launcher/app/Sling.java?rev=605168&r1=605167&r2=605168&view=diff
==============================================================================
--- incubator/sling/trunk/launcher/app/src/main/java/org/apache/sling/launcher/app/Sling.java (original)
+++ incubator/sling/trunk/launcher/app/src/main/java/org/apache/sling/launcher/app/Sling.java Tue Dec 18 02:25:25 2007
@@ -16,13 +16,14 @@
*/
package org.apache.sling.launcher.app;
+import static org.apache.felix.framework.util.FelixConstants.EMBEDDED_EXECUTION_PROP;
+
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
@@ -181,12 +182,6 @@
public static final String CONFIG_PROPERTIES = "sling.properties";
/**
- * The property name prefix for the launcher's auto-start property.
- * FIXME - This is just a temporary solution to get this module compilable.
- **/
- public static final String AUTO_START_PROP = "felix.auto.start";
-
- /**
* The simple logger to log messages during startup and shutdown to
*/
protected final Logger logger;
@@ -227,7 +222,6 @@
// check for auto-start bundles
this.setInstallBundles(props);
- this.setAutoStartBundles(props);
// ensure execution environment
this.setExecutionEnvironment(props);
@@ -236,11 +230,12 @@
props.put(SLING_ID, getInstanceId(props));
// make sure Felix does not exit the VM when terminating ...
- props.put("felix.embedded.execution", "true");
+ props.put(EMBEDDED_EXECUTION_PROP, "true");
// the custom activator list just contains this servlet
List<BundleActivator> activators = new ArrayList<BundleActivator>();
activators.add(this);
+ activators.add(new BootstrapInstaller(logger, resourceProvider));
// create the framework and start it
Felix tmpFelix = new Felix(props, activators);
@@ -566,36 +561,6 @@
props.put(prefix + "bundles", buf.toString());
}
- private void setAutoStartBundles(Map<String, String> props) {
-
- String propName = AUTO_START_PROP + ".1";
- StringBuffer buf = new StringBuffer();
-
- // take over the current value
- String autostart = props.get(propName);
- if (autostart != null) {
- buf.append(autostart);
- }
-
- this.listBundles(buf, "resources/corebundles");
- this.listBundles(buf, "resources/bundles");
-
- props.put(propName, buf.toString());
- }
-
- private void listBundles(StringBuffer list, String path) {
- Iterator<String> res = this.resourceProvider.getChildren(path);
- while (res.hasNext()) {
- String name = res.next();
- if (name.endsWith(".jar")) {
- URL url = this.resourceProvider.getResource(name);
- if (url != null) {
- list.append(" ").append(this.toString(url));
- }
- }
- }
- }
-
/**
* Ensures sensible Execution Environment setting. If the
* <code>org.osgi.framework.executionenvironment</code> property is set in
@@ -699,41 +664,6 @@
}
return slingId;
- }
-
- /**
- * Convert the URL into a string. If the URL string contains blank spaces,
- * which may happen if the <code>File.toURL()</code> method is used on
- * files whose path contains blank spaces, this method replaces the blank
- * spaces with their URL encoding <code>%20</code>. No other encoding
- * takes place.
- * <p>
- * Note: This is a quick solution to a problem with the CQSE servlet
- * container which uses the File.toURL() method to return an URL for a web
- * application contained resource.
- *
- * @param url The <code>URL</code> to convert into a string
- * @return The URL string with any blanks replaced by "%20"
- */
- private String toString(URL url) {
- String urlS = url.toExternalForm();
-
- // return unmodified, if there is no blank
- if (urlS.indexOf(' ') < 0) {
- return urlS;
- }
-
- // otherwise replace all blanks with "%20"
- StringBuffer buf = new StringBuffer();
- for (int i = 0; i < urlS.length(); i++) {
- char c = urlS.charAt(i);
- if (c == ' ') {
- buf.append("%20");
- } else {
- buf.append(c);
- }
- }
- return buf.toString();
}
// ---------- Extension support --------------------------------------------