Index: src/main/java/org/apache/karaf/main/ConfigProperties.java =================================================================== --- src/main/java/org/apache/karaf/main/ConfigProperties.java (revision 1341013) +++ src/main/java/org/apache/karaf/main/ConfigProperties.java (working copy) @@ -95,6 +95,10 @@ private static final String KARAF_SHUTDOWN_COMMAND = "karaf.shutdown.command"; private static final String KARAF_SHUTDOWN_PID_FILE = "karaf.shutdown.pid.file"; + + static final String KARAF_STARTUP_FEATURE_URI = "karaf.startup.feature.uri"; + + private static final String KARAF_STARTUP_FEATURE_NAME = "karaf.startup.feature.name"; private static final String DEFAULT_SHUTDOWN_COMMAND = "SHUTDOWN"; @@ -133,6 +137,8 @@ String includes; String optionals; File etcFolder; + URI startupFeatureUri; + String startupFeatureName; public ConfigProperties() throws Exception { this.karafHome = Utils.getKarafHome(ConfigProperties.class, PROP_KARAF_HOME, ENV_KARAF_HOME); @@ -183,6 +189,10 @@ this.shutdownHost = props.getProperty(KARAF_SHUTDOWN_HOST, "localhost"); this.portFile = props.getProperty(KARAF_SHUTDOWN_PORT_FILE); this.shutdownCommand = props.getProperty(KARAF_SHUTDOWN_COMMAND, DEFAULT_SHUTDOWN_COMMAND); + if (props.getProperty(KARAF_STARTUP_FEATURE_URI) != null) { + this.startupFeatureUri = new URI(props.getProperty(KARAF_STARTUP_FEATURE_URI)); + } + this.startupFeatureName = props.getProperty(KARAF_STARTUP_FEATURE_NAME, "framework"); } private String getProperyOrFail(String propertyName) { Index: src/main/java/org/apache/karaf/main/FeatureReader.java =================================================================== --- src/main/java/org/apache/karaf/main/FeatureReader.java (revision 0) +++ src/main/java/org/apache/karaf/main/FeatureReader.java (working copy) @@ -0,0 +1,68 @@ +/* + * 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.karaf.main; + +import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +class FeatureReader { + List readBundles(URI featureUri, String featureName) throws Exception { + InputStream is = featureUri.toURL().openStream(); + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = dbf.newDocumentBuilder(); + Document doc = db.parse(is); + is.close(); + NodeList features = doc.getElementsByTagName("feature"); + for (int c=0; c(); + } + + private List getBundles(NodeList bundleNodes) throws URISyntaxException { + ArrayList bundles = new ArrayList(); + for (int c=0; c bundles = readBundlesFromStartupProperties(startupPropsFile); - installAndStartBundles(resolver, framework.getBundleContext(), bundles); - LOG.info("All initial bundles installed and set to start"); + if (startupPropsFile.exists()) { + LOG.info("Installing and starting bundles from " + startupPropsFile); + List bundles = readBundlesFromStartupProperties(startupPropsFile); + installAndStartBundles(resolver, framework.getBundleContext(), bundles); + } + + if (config.startupFeatureUri != null) { + LOG.info("Installing and starting bundles from startup feature uri " + config.startupFeatureUri + ", name " + config.startupFeatureName); + URI resolvedStartupFeatureUri = resolver.resolve(config.startupFeatureUri); + List bundles = new FeatureReader().readBundles(resolvedStartupFeatureUri, config.startupFeatureName); + installAndStartBundles(resolver, framework.getBundleContext(), bundles); + } + int numBundles = framework.getBundleContext().getBundles().length -1; + if (numBundles == 0) { + throw new RuntimeException("No bundles loaded. You either need a etc/startup.properties or set " + ConfigProperties.KARAF_STARTUP_FEATURE_URI + " in config.properties"); + } + LOG.info(numBundles + " initial bundles installed and set to start"); } ServerInfo serverInfo = new ServerInfoImpl(args, config); Index: src/test/java/org/apache/karaf/main/FeatureReaderTest.java =================================================================== --- src/test/java/org/apache/karaf/main/FeatureReaderTest.java (revision 0) +++ src/test/java/org/apache/karaf/main/FeatureReaderTest.java (working copy) @@ -0,0 +1,39 @@ +/* + * 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.karaf.main; + +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +public class FeatureReaderTest { + + @Test + public void testReadBundlesFromFeature() throws URISyntaxException, Exception { + URL res = this.getClass().getClassLoader().getResource("test-karaf-home/system/org/apache/karaf/features/framework/1.0.0/framework-1.0.0-features.xml"); + List bundles = new FeatureReader().readBundles(res.toURI(), "framework"); + Assert.assertEquals(1, bundles.size()); + Assert.assertEquals(10, bundles.get(0).startLevel.intValue()); + Assert.assertEquals(new URI("mvn:org.apache.aries.blueprint/org.apache.aries.blueprint.api/0.3.1"), bundles.get(0).uri); + } +} Index: src/test/resources/test-karaf-home/etc/config.properties =================================================================== --- src/test/resources/test-karaf-home/etc/config.properties (revision 1341013) +++ src/test/resources/test-karaf-home/etc/config.properties (working copy) @@ -39,3 +39,4 @@ karaf.startlevel.bundle=60 karaf.name=root karaf.default.repository=system +karaf.startup.feature.uri=mvn:org.apache.karaf.features/framework/1.0.0/xml/features Index: src/test/resources/test-karaf-home/etc/startup.properties =================================================================== --- src/test/resources/test-karaf-home/etc/startup.properties (revision 1341013) +++ src/test/resources/test-karaf-home/etc/startup.properties (working copy) @@ -23,6 +23,4 @@ # # Startup core services like logging # -mvn\:org.apache.aries.blueprint/org.apache.aries.blueprint.api/0.3.1=10 pax-url-mvn.jar=10 -#mvn\:org.apache.felix/org.apache.felix.configadmin/1.2.8=10