You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by dj...@apache.org on 2011/04/27 01:16:30 UTC
svn commit: r1096949 [1/2] - in /geronimo/server/trunk: ./
framework/buildsupport/car-maven-plugin/
framework/buildsupport/car-maven-plugin/src/main/filtered-resources/
framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/
fram...
Author: djencks
Date: Tue Apr 26 23:16:30 2011
New Revision: 1096949
URL: http://svn.apache.org/viewvc?rev=1096949&view=rev
Log:
start working on a karaf-like framework starter for car-maven-plugin
Added:
geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/
geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/
geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/etc/
geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/etc/startup.properties (with props)
geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/AbstractFrameworkMojo.java (with props)
geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/FrameworkHelper.java (with props)
geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/ThreadLocalProperties.java (with props)
geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/test/java/org/apache/geronimo/mavenplugins/car/FrameworkHelperTest.java (with props)
Modified:
geronimo/server/trunk/framework/buildsupport/car-maven-plugin/pom.xml
geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/resources/META-INF/plexus/components.xml
geronimo/server/trunk/framework/modules/geronimo-kernel/pom.xml
geronimo/server/trunk/framework/modules/geronimo-system/pom.xml
geronimo/server/trunk/framework/modules/geronimo-system/src/main/java/org/apache/geronimo/system/main/MainBridge.java
geronimo/server/trunk/framework/modules/geronimo-system/src/main/java/org/apache/geronimo/system/osgi/BootActivator.java
geronimo/server/trunk/pom.xml
Modified: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/framework/buildsupport/car-maven-plugin/pom.xml?rev=1096949&r1=1096948&r2=1096949&view=diff
==============================================================================
--- geronimo/server/trunk/framework/buildsupport/car-maven-plugin/pom.xml (original)
+++ geronimo/server/trunk/framework/buildsupport/car-maven-plugin/pom.xml Tue Apr 26 23:16:30 2011
@@ -160,11 +160,21 @@
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
- <version>2.2.1</version>
+ <version>3.0</version>
<scope>provided</scope>
</dependency>
<dependency>
+ <groupId>org.sonatype.aether</groupId>
+ <artifactId>aether-api</artifactId>
+ <version>1.8</version>
+ </dependency>
+ <dependency>
+ <groupId>org.sonatype.aether</groupId>
+ <artifactId>aether-util</artifactId>
+ <version>1.8</version>
+ </dependency>
+ <dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-archiver</artifactId>
<version>2.2</version>
@@ -281,6 +291,15 @@
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.framework</artifactId>
</dependency>
+ <!--<dependency>-->
+ <!--<groupId>org.apache.karaf</groupId>-->
+ <!--<artifactId>org.apache.karaf.main</artifactId>-->
+ <!--</dependency>-->
+ <dependency>
+ <groupId>org.apache.karaf.assemblies.features</groupId>
+ <artifactId>karaf-framework</artifactId>
+ <type>kar</type>
+ </dependency>
</dependencies>
</profile>
@@ -300,10 +319,103 @@
<groupId>org.eclipse</groupId>
<artifactId>osgi</artifactId>
</dependency>
+ <!--<dependency>-->
+ <!--<groupId>org.apache.karaf</groupId>-->
+ <!--<artifactId>org.apache.karaf.main</artifactId>-->
+ <!--</dependency>-->
+ <dependency>
+ <groupId>org.apache.karaf.assemblies.features</groupId>
+ <artifactId>karaf-framework</artifactId>
+ <type>kar</type>
+ </dependency>
</dependencies>
</profile>
</profiles>
+ <build>
+ <plugins>
+<!-- This causes a class cast exception
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.2</version>
+ <executions>
+ <execution>
+ <id>unpack</id>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>unpack</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.apache.karaf.assemblies.features</groupId>
+ <artifactId>karaf-framework</artifactId>
+ <type>kar</type>
+ <overWrite>false</overWrite>
+ <outputDirectory>${project.build.directory}/classes</outputDirectory>
+ <includes>resources/etc/**</includes>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+-->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.2</version>
+ <executions>
+ <execution>
+ <id>copy</id>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.apache.karaf.assemblies.features</groupId>
+ <artifactId>karaf-framework</artifactId>
+ <type>kar</type>
+ <!--<overWrite>false</overWrite>-->
+ <!--<outputDirectory>${project.build.directory}/classes</outputDirectory>-->
+ <!--<includes>resources/etc/**</includes>-->
+ </artifactItem>
+ </artifactItems>
+ <stripVersion>true</stripVersion>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>1.6</version>
+ <executions>
+ <execution>
+ <phase>process-resources</phase>
+ <configuration>
+ <target>
+ <unzip src="${project.build.directory}/dependency/karaf-framework.kar"
+ dest="${project.build.directory}/classes">
+ <patternset>
+ <include name="resources/etc/**"/>
+ <exclude name="resources/etc/startup.properties"/>
+ </patternset>
+ </unzip>
+
+ </target>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
</project>
Added: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/etc/startup.properties
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/etc/startup.properties?rev=1096949&view=auto
==============================================================================
--- geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/etc/startup.properties (added)
+++ geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/etc/startup.properties Tue Apr 26 23:16:30 2011
@@ -0,0 +1,97 @@
+################################################################################
+#
+# 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.
+#
+################################################################################
+
+# This file allows you to control the start level of each bundle.
+#
+
+#
+# Startup core services like logging
+#
+org.ops4j.pax.url\:pax-url-mvn\:${pax.url.version}=5
+org.ops4j.pax.url\:pax-url-wrap\:${pax.url.version}=5
+org.ops4j.pax.logging\:pax-logging-api\:${pax.logging.version}=8
+org.ops4j.pax.logging\:pax-logging-service\:${pax.logging.version}=8
+org.apache.felix\:org.apache.felix.configadmin\:${felix.configadmin.version}=10
+org.apache.felix\:org.apache.felix.fileinstall\:${felix.fileinstall.version}=11
+
+#
+# The rest of the services..
+#
+org.apache.servicemix.bundles\:org.apache.servicemix.bundles.asm\:${asm.bundle.version}=20
+org.apache.aries\:org.apache.aries.util\:${aries.util.version}=20
+org.apache.aries.proxy\:org.apache.aries.proxy\:${aries.proxy.version}=20
+org.apache.aries.blueprint\:org.apache.aries.blueprint\:${aries.blueprint.version}=20
+
+org.apache.karaf.shell\:org.apache.karaf.shell.console\:${karaf.version}=30
+org.apache.karaf.shell\:org.apache.karaf.shell.osgi\:${karaf.version}=30
+org.apache.karaf.shell\:org.apache.karaf.shell.log\:${karaf.version}=30
+org.apache.karaf.shell\:org.apache.karaf.shell.packages\:${karaf.version}=30
+org.apache.karaf.shell\:org.apache.karaf.shell.commands\:${karaf.version}=30
+org.apache.karaf.shell\:org.apache.karaf.shell.dev\:${karaf.version}=30
+org.apache.karaf.jaas\:org.apache.karaf.jaas.config\:${karaf.version}=30
+org.apache.karaf.jaas\:org.apache.karaf.jaas.modules\:${karaf.version}=30
+org.apache.karaf.jaas\:org.apache.karaf.jaas.command\:${karaf.version}=30
+org.apache.karaf.features\:org.apache.karaf.features.core\:${karaf.version}=30
+org.apache.karaf.features\:org.apache.karaf.features.command\:${karaf.version}=30
+#org.apache.karaf.features\:org.apache.karaf.features.management\:${karaf.version}=30
+
+org.apache.karaf.diagnostic\:org.apache.karaf.diagnostic.core\:${karaf.version}=30
+org.apache.karaf.diagnostic\:org.apache.karaf.diagnostic.common\:${karaf.version}=30
+org.apache.karaf.diagnostic\:org.apache.karaf.diagnostic.command\:${karaf.version}=30
+#org.apache.karaf.diagnostic\:org.apache.karaf.diagnostic.management\:${karaf.version}=30
+
+#org.apache.karaf\:org.apache.karaf.management\:${karaf.version}=30
+#org.apache.aries.jmx\:org.apache.aries.jmx\:0.3=30
+#org.apache.aries.jmx\:org.apache.aries.jmx.blueprint\:0.3=30
+
+#org.apache.karaf.admin\:org.apache.karaf.admin.core\:${karaf.version}=30
+#org.apache.karaf.admin\:org.apache.karaf.admin.command\:${karaf.version}=30
+#org.apache.karaf.admin\:org.apache.karaf.admin.management\:${karaf.version}=30
+
+#org.apache.mina\:mina-core\:2.0.1=30
+#org.apache.sshd\:sshd-core\:0.5.0=30
+#org.apache.karaf.shell\:org.apache.karaf.shell.ssh\:${karaf.version}=30
+
+#org.apache.karaf.deployer\:org.apache.karaf.deployer.spring\:${karaf.version}=30
+org.apache.karaf.deployer\:org.apache.karaf.deployer.blueprint\:${karaf.version}=30
+org.apache.karaf.deployer\:org.apache.karaf.deployer.features\:${karaf.version}=30
+org.apache.karaf.deployer\:org.apache.karaf.deployer.kar\:${karaf.version}=30
+org.apache.karaf.deployer\:org.apache.karaf.deployer.wrap\:${karaf.version}=30
+
+# geronimo additions
+org.apache.felix\:org.apache.felix.scr\:1.6.0=15
+org.apache.felix\:org.apache.felix.shell\:1.5.0-SNAPSHOT=15
+org.apache.geronimo.bundles\:jaxb-impl\:2.2.3_1-SNAPSHOT=15
+org.apache.geronimo.specs\:geronimo-stax-api_1.2_spec\:1.1-SNAPSHOT=15
+org.apache.geronimo.specs\:geronimo-jaxb_2.2_spec\:1.0.2-SNAPSHOT=15
+org.apache.geronimo.specs\:geronimo-activation_1.1_spec\:1.1=15
+org.apache.geronimo.bundles\:woodstox\:4.0.6_2-SNAPSHOT=15
+org.apache.geronimo.specs\:geronimo-osgi-registry\:1.1-SNAPSHOT=15
+
+org.apache.geronimo.framework\:geronimo-kernel\:${geronimo.version}=40
+org.apache.geronimo.framework\:geronimo-crypto\:${geronimo.version}=40
+org.apache.felix\:org.apache.felix.bundlerepository\:${felix.bundlerepository.version}=40
+org.apache.xbean\:xbean-reflect\:${xbeanVersion}=40
+
+org.apache.geronimo.framework\:geronimo-system\:${geronimo.version}=40
+org.apache.geronimo.framework\:geronimo-common\:${geronimo.version}=40
+org.apache.geronimo.framework\:geronimo-pax-logging\:${geronimo.version}=40
+org.apache.geronimo.framework\:geronimo-main\:${geronimo.version}=40
+org.apache.servicemix.bundles\:org.apache.servicemix.bundles.commons-jexl\:1.1_3=40
+org.apache.xbean\:xbean-bundleutils\:${xbeanVersion}=40
\ No newline at end of file
Propchange: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/etc/startup.properties
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/etc/startup.properties
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/filtered-resources/resources/etc/startup.properties
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/AbstractFrameworkMojo.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/AbstractFrameworkMojo.java?rev=1096949&view=auto
==============================================================================
--- geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/AbstractFrameworkMojo.java (added)
+++ geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/AbstractFrameworkMojo.java Tue Apr 26 23:16:30 2011
@@ -0,0 +1,155 @@
+/*
+ * 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.geronimo.mavenplugins.car;
+
+import java.io.File;
+import java.lang.Override;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.launch.Framework;
+import org.sonatype.aether.RepositorySystem;
+import org.sonatype.aether.RepositorySystemSession;
+import org.sonatype.aether.repository.RemoteRepository;
+import org.sonatype.aether.resolution.ArtifactRequest;
+import org.sonatype.aether.resolution.ArtifactResolutionException;
+import org.sonatype.aether.resolution.ArtifactResult;
+import org.sonatype.aether.util.artifact.DefaultArtifact;
+
+/**
+ * Base for karaf-aware mojos
+ *
+ * @goal karaf-framework
+ * @requiresDependencyResolution runtime
+ *
+ * @version $Rev$ $Date$
+ */
+public class AbstractFrameworkMojo extends AbstractMojo {
+ /**
+ * The entry point to Aether, i.e. the component doing all the work.
+ *
+ * @component
+ */
+ private RepositorySystem repoSystem;
+
+ /**
+ * The current repository/network configuration of Maven.
+ *
+ * @parameter default-value="${repositorySystemSession}"
+ * @readonly
+ */
+ private RepositorySystemSession repoSession;
+
+ /**
+ * The project's remote repositories to use for the resolution of plugins and their dependencies.
+ *
+ * @parameter default-value="${project.remoteProjectRepositories}"
+ * @readonly
+ */
+ private List<RemoteRepository> remoteRepos;
+
+ /**
+ * where we set up karaf
+ *
+ * @parameter default-value="${project.build.directory}/karaf"
+ */
+ private String karafHome;
+
+ private Framework framework;
+
+
+ @java.lang.Override
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ initializeFramework();
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+
+ }
+ ServiceReference sr = framework.getBundleContext().getServiceReference(FeaturesService.class.getName());
+ Object o = framework.getBundleContext().getService(sr);
+ if (o == null) {
+ throw new RuntimeException("no feature service found");
+ }
+ try {
+ framework.stop();
+ } catch (BundleException e) {
+ throw new MojoExecutionException("Can't stop framework: ", e );
+ }
+ }
+
+ void initializeFramework() throws MojoFailureException {
+ FrameworkHelper helper = new FrameworkHelper(karafHome, new AetherResolver(), Collections.<Artifact>emptyList());
+ try {
+ framework = helper.start();
+ } catch (Exception e) {
+ throw new MojoFailureException("Could not start karaf framework", e);
+ }
+ }
+
+ protected void listBundles() {
+ StringBuilder b = new StringBuilder("Bundles:");
+ for (Bundle bundle: framework.getBundleContext().getBundles()) {
+ b.append("\n Id:").append(bundle.getBundleId()).append(" status:").append(bundle.getState()).append(" ").append(bundle.getLocation());
+ }
+ getLog().info(b.toString());
+ }
+
+ class AetherResolver implements FrameworkHelper.Resolver {
+
+ @Override
+ public File resolve(String id) {
+ if (id.startsWith("mvn:")) {
+ id = id.substring("mvn:".length()).replaceAll("/", ":");
+ }
+ ArtifactRequest request = new ArtifactRequest();
+ request.setArtifact(
+ new DefaultArtifact(id));
+ request.setRepositories(remoteRepos);
+
+ getLog().debug("Resolving artifact " + id +
+ " from " + remoteRepos);
+
+ ArtifactResult result;
+ try {
+ result = repoSystem.resolveArtifact(repoSession, request);
+ } catch (ArtifactResolutionException e) {
+ getLog().warn("could not resolve " + id, e);
+ return null;
+ }
+
+ getLog().debug("Resolved artifact " + id + " to " +
+ result.getArtifact().getFile() + " from "
+ + result.getRepository());
+ return result.getArtifact().getFile();
+ }
+ }
+
+
+}
Propchange: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/AbstractFrameworkMojo.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/AbstractFrameworkMojo.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/AbstractFrameworkMojo.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/FrameworkHelper.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/FrameworkHelper.java?rev=1096949&view=auto
==============================================================================
--- geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/FrameworkHelper.java (added)
+++ geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/FrameworkHelper.java Tue Apr 26 23:16:30 2011
@@ -0,0 +1,1488 @@
+/*
+ * 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.geronimo.mavenplugins.car;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URL;
+import java.security.AccessControlException;
+import java.security.Provider;
+import java.security.Security;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Random;
+import java.util.ServiceLoader;
+import java.util.StringTokenizer;
+import java.util.TreeMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.karaf.main.BootstrapLogManager;
+import org.apache.karaf.main.Lock;
+import org.apache.karaf.main.ShutdownCallback;
+import org.apache.karaf.main.SimpleFileLock;
+import org.apache.karaf.main.StringMap;
+import org.apache.karaf.main.Utils;
+import org.apache.maven.artifact.Artifact;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.launch.FrameworkFactory;
+import org.osgi.service.startlevel.StartLevel;
+
+/**
+ * Mostly based on karaf Main class
+ *
+ * @version $Rev:$ $Date:$
+ */
+public class FrameworkHelper {
+
+ private String karafHomeString;
+ //path in karaf-framework kar containing etc dir.
+ //These have been copied into this plugin
+ private String etcLocation = "resources/etc/";
+
+ private Resolver resolver;
+
+ private List<Artifact> bundles;
+
+ public FrameworkHelper(String karafHome, Resolver resolver, List<Artifact> bundles) {
+ this.karafHomeString = karafHome;
+ File f = new File(karafHome);
+ if (f.exists() && !f.isDirectory()) {
+ throw new IllegalArgumentException("Karaf home exists but is not a directory: " + karafHome);
+ }
+ f.mkdirs();
+ this.resolver = resolver;
+ this.bundles = bundles;
+ }
+
+ public Framework start() throws Exception {
+ ThreadLocalProperties.install();
+ System.setProperty(PROP_KARAF_HOME, karafHomeString);
+ System.setProperty(PROP_KARAF_BASE, karafHomeString);
+ launch();
+ deployBundles(bundles);
+ return getFramework();
+ }
+
+ public void stop() throws Exception {
+ try {
+ destroy();
+ } finally {
+ ThreadLocalProperties.uninstall();
+ }
+ }
+
+ public void deployBundles(List<Artifact> bundles) throws BundleException {
+ BundleContext bundleContext = getFramework().getBundleContext();
+ List<Bundle> bundleIds = new ArrayList<Bundle>();
+ for (Artifact artifact: bundles) {
+ String location = artifact.getFile().getAbsolutePath();
+ bundleIds.add(bundleContext.installBundle(location));
+ }
+ for (Bundle bundle: bundleIds) {
+ bundle.start();
+ }
+ }
+
+ //modified copy of karaf Main class
+
+ /**
+ * The default name used for the system properties file.
+ */
+ public static final String SYSTEM_PROPERTIES_FILE_NAME = "system.properties";
+ /**
+ * The default name used for the configuration properties file.
+ */
+ public static final String CONFIG_PROPERTIES_FILE_NAME = "config.properties";
+ /**
+ * The default name used for the startup properties file.
+ */
+ public static final String STARTUP_PROPERTIES_FILE_NAME = "startup.properties";
+ /**
+ * The property name prefix for the launcher's auto-install property.
+ */
+ public static final String PROPERTY_AUTO_INSTALL = "karaf.auto.install";
+ /**
+ * The property for auto-discovering the bundles
+ */
+ public static final String PROPERTY_AUTO_START = "karaf.auto.start";
+ /**
+ * The system property for specifying the Karaf home directory. The home directory
+ * hold the binary install of Karaf.
+ */
+ public static final String PROP_KARAF_HOME = "karaf.home";
+ /**
+ * The environment variable for specifying the Karaf home directory. The home directory
+ * hold the binary install of Karaf.
+ */
+ public static final String ENV_KARAF_HOME = "KARAF_HOME";
+ /**
+ * The system property for specifying the Karaf base directory. The base directory
+ * holds the configuration and data for a Karaf instance.
+ */
+ public static final String PROP_KARAF_BASE = "karaf.base";
+ /**
+ * The environment variable for specifying the Karaf base directory. The base directory
+ * holds the configuration and data for a Karaf instance.
+ */
+ public static final String ENV_KARAF_BASE = "KARAF_BASE";
+ /**
+ * The system property for specifying the Karaf data directory. The data directory
+ * holds the bundles data and cache for a Karaf instance.
+ */
+ public static final String PROP_KARAF_DATA = "karaf.data";
+ /**
+ * The environment variable for specifying the Karaf data directory. The data directory
+ * holds the bundles data and cache for a Karaf instance.
+ */
+ public static final String ENV_KARAF_DATA = "KARAF_DATA";
+ /**
+ * The system property for specifying the Karaf data directory. The data directory
+ * holds the bundles data and cache for a Karaf instance.
+ */
+ public static final String PROP_KARAF_INSTANCES = "karaf.instances";
+ /**
+ * The system property for specifying the Karaf data directory. The data directory
+ * holds the bundles data and cache for a Karaf instance.
+ */
+ public static final String ENV_KARAF_INSTANCES = "KARAF_INSTANCES";
+
+ /**
+ * Config property which identifies directories which contain bundles to be loaded by SMX
+ */
+ public static final String BUNDLE_LOCATIONS = "bundle.locations";
+
+ /**
+ * Config property that indicates we want to convert bundles locations to maven style urls
+ */
+ public static final String PROPERTY_CONVERT_TO_MAVEN_URL = "karaf.maven.convert";
+
+ /**
+ * If a lock should be used before starting the runtime
+ */
+ public static final String PROPERTY_USE_LOCK = "karaf.lock";
+
+ /**
+ * The lock implementation
+ */
+ public static final String PROPERTY_LOCK_CLASS = "karaf.lock.class";
+
+ public static final String PROPERTY_LOCK_DELAY = "karaf.lock.delay";
+
+ public static final String PROPERTY_LOCK_LEVEL = "karaf.lock.level";
+
+ public static final String DEFAULT_REPO = "karaf.default.repository";
+
+ public static final String KARAF_FRAMEWORK = "karaf.framework";
+
+ public static final String KARAF_FRAMEWORK_FACTORY = "karaf.framework.factory";
+
+ public static final String KARAF_SHUTDOWN_TIMEOUT = "karaf.shutdown.timeout";
+
+ public static final String KARAF_SHUTDOWN_PORT = "karaf.shutdown.port";
+
+ public static final String KARAF_SHUTDOWN_HOST = "karaf.shutdown.host";
+
+ public static final String KARAF_SHUTDOWN_PORT_FILE = "karaf.shutdown.port.file";
+
+ public static final String KARAF_SHUTDOWN_COMMAND = "karaf.shutdown.command";
+
+ public static final String KARAF_SHUTDOWN_PID_FILE = "karaf.shutdown.pid.file";
+
+ public static final String DEFAULT_SHUTDOWN_COMMAND = "SHUTDOWN";
+
+ public static final String PROPERTY_LOCK_CLASS_DEFAULT = SimpleFileLock.class.getName();
+
+ public static final String INCLUDES_PROPERTY = "${includes}";
+
+ Logger LOG = Logger.getLogger(this.getClass().getName());
+
+ private File karafHome;
+ private File karafBase;
+ private File karafData;
+ private File karafInstances;
+ private Properties configProps = null;
+ private Framework framework = null;
+ private int exitCode;
+ private Lock lock;
+ private int defaultStartLevel = 100;
+ private int lockStartLevel = 1;
+ private int lockDelay = 1000;
+ private int shutdownTimeout = 5 * 60 * 1000;
+ private boolean exiting = false;
+ private ShutdownCallback shutdownCallback;
+
+ public void setShutdownCallback(ShutdownCallback shutdownCallback) {
+ this.shutdownCallback = shutdownCallback;
+ }
+
+ public void launch() throws Exception {
+ karafHome = Utils.getKarafHome();
+ karafBase = Utils.getKarafDirectory(PROP_KARAF_BASE, ENV_KARAF_BASE, karafHome, false, true);
+ karafData = Utils.getKarafDirectory(PROP_KARAF_DATA, ENV_KARAF_DATA, new File(karafBase, "data"), true, true);
+ karafInstances = Utils.getKarafDirectory(PROP_KARAF_INSTANCES, ENV_KARAF_INSTANCES, new File(karafHome, "instances"), false, false);
+
+ //System.out.println("Karaf Home: "+main.karafHome.getPath());
+ //System.out.println("Karaf Base: "+main.karafBase.getPath());
+ //System.out.println("Karaf Data: "+main.karafData.getPath());
+
+ System.setProperty(PROP_KARAF_HOME, karafHome.getPath());
+ System.setProperty(PROP_KARAF_BASE, karafBase.getPath());
+ System.setProperty(PROP_KARAF_DATA, karafData.getPath());
+ System.setProperty(PROP_KARAF_INSTANCES, karafInstances.getPath());
+
+ // Load system properties.
+ loadSystemProperties(karafBase);
+
+ updateInstancePid();
+
+ // Read configuration properties.
+ configProps = loadConfigProperties();
+ BootstrapLogManager.setProperties(configProps);
+ LOG.addHandler(BootstrapLogManager.getDefaultHandler());
+
+ // Copy framework properties from the system properties.
+ copySystemProperties(configProps);
+
+ ClassLoader classLoader = createClassLoader(configProps);
+
+ processSecurityProperties(configProps);
+
+ if (configProps.getProperty(Constants.FRAMEWORK_STORAGE) == null) {
+ File storage = new File(karafData.getPath(), "cache");
+ try {
+ storage.mkdirs();
+ } catch (SecurityException se) {
+ throw new Exception(se.getMessage());
+ }
+ configProps.setProperty(Constants.FRAMEWORK_STORAGE, storage.getAbsolutePath());
+ }
+
+ defaultStartLevel = Integer.parseInt(configProps.getProperty(Constants.FRAMEWORK_BEGINNING_STARTLEVEL));
+ lockStartLevel = Integer.parseInt(configProps.getProperty(PROPERTY_LOCK_LEVEL, Integer.toString(lockStartLevel)));
+ lockDelay = Integer.parseInt(configProps.getProperty(PROPERTY_LOCK_DELAY, Integer.toString(lockDelay)));
+ configProps.setProperty(Constants.FRAMEWORK_BEGINNING_STARTLEVEL, Integer.toString(lockStartLevel));
+ shutdownTimeout = Integer.parseInt(configProps.getProperty(KARAF_SHUTDOWN_TIMEOUT, Integer.toString(shutdownTimeout)));
+ // Start up the OSGI framework
+
+ String factoryClass = configProps.getProperty(KARAF_FRAMEWORK_FACTORY);
+ FrameworkFactory factory;
+ if (factoryClass == null) {
+ ServiceLoader<FrameworkFactory> loader = ServiceLoader.load(FrameworkFactory.class);
+ factory = loader.iterator().next();
+ } else {
+ factory = (FrameworkFactory) classLoader.loadClass(factoryClass).newInstance();
+ }
+ framework = factory.newFramework(new StringMap(configProps, false));
+ framework.start();
+ processAutoProperties(framework.getBundleContext());
+ // Start lock monitor
+ new Thread() {
+ public void run() {
+ lock(configProps);
+ }
+ }.start();
+ }
+
+ public void awaitShutdown() throws Exception {
+ while (true) {
+ FrameworkEvent event = framework.waitForStop(0);
+ if (event.getType() != FrameworkEvent.STOPPED_UPDATE) {
+ return;
+ }
+ }
+ }
+
+ public boolean destroy() throws Exception {
+ if (framework == null) {
+ return true;
+ }
+ try {
+ int step = 5000;
+
+ // Notify the callback asap
+ if (shutdownCallback != null) {
+ shutdownCallback.waitingForShutdown(step);
+ }
+
+ // Stop the framework in case it's still active
+ exiting = true;
+ if (framework.getState() == Bundle.ACTIVE) {
+ new Thread() {
+ public void run() {
+ try {
+ framework.stop();
+ } catch (BundleException e) {
+ System.err.println("Error stopping karaf: " + e.getMessage());
+ }
+ }
+ }.start();
+ }
+
+ int timeout = shutdownTimeout;
+ if (shutdownTimeout <= 0) {
+ timeout = Integer.MAX_VALUE;
+ }
+ while (timeout > 0) {
+ timeout -= step;
+ if (shutdownCallback != null) {
+ shutdownCallback.waitingForShutdown(step * 2);
+ }
+ FrameworkEvent event = framework.waitForStop(step);
+ if (event.getType() != FrameworkEvent.WAIT_TIMEDOUT) {
+ return true;
+ }
+ }
+ return false;
+ } finally {
+ unlock();
+ }
+ }
+
+ /**
+ * <p>
+ * This method performs the main task of constructing an framework instance
+ * and starting its execution. The following functions are performed
+ * when invoked:
+ * </p>
+ * <ol>
+ * <li><i><b>Read the system properties file.<b></i> This is a file
+ * containing properties to be pushed into <tt>System.setProperty()</tt>
+ * before starting the framework. This mechanism is mainly shorthand
+ * for people starting the framework from the command line to avoid having
+ * to specify a bunch of <tt>-D</tt> system property definitions.
+ * The only properties defined in this file that will impact the framework's
+ * behavior are the those concerning setting HTTP proxies, such as
+ * <tt>http.proxyHost</tt>, <tt>http.proxyPort</tt>, and
+ * <tt>http.proxyAuth</tt>.
+ * </li>
+ * <li><i><b>Perform system property variable substitution on system
+ * properties.</b></i> Any system properties in the system property
+ * file whose value adheres to <tt>${<system-prop-name>}</tt>
+ * syntax will have their value substituted with the appropriate
+ * system property value.
+ * </li>
+ * <li><i><b>Read the framework's configuration property file.</b></i> This is
+ * a file containing properties used to configure the framework
+ * instance and to pass configuration information into
+ * bundles installed into the framework instance. The configuration
+ * property file is called <tt>config.properties</tt> by default
+ * and is located in the <tt>conf/</tt> directory of the Felix
+ * installation directory, which is the parent directory of the
+ * directory containing the <tt>felix.jar</tt> file. It is possible
+ * to use a different location for the property file by specifying
+ * the desired URL using the <tt>felix.config.properties</tt>
+ * system property; this should be set using the <tt>-D</tt> syntax
+ * when executing the JVM. Refer to the
+ * <a href="Felix.html#Felix(java.util.Map, java.util.List)">
+ * <tt>Felix</tt></a> constructor documentation for more
+ * information on the framework configuration options.
+ * </li>
+ * <li><i><b>Perform system property variable substitution on configuration
+ * properties.</b></i> Any configuration properties whose value adheres to
+ * <tt>${<system-prop-name>}</tt> syntax will have their value
+ * substituted with the appropriate system property value.
+ * </li>
+ * <li><i><b>Ensure the default bundle cache has sufficient information to
+ * initialize.</b></i> The default implementation of the bundle cache
+ * requires either a profile name or a profile directory in order to
+ * start. The configuration properties are checked for at least one
+ * of the <tt>felix.cache.profile</tt> or <tt>felix.cache.profiledir</tt>
+ * properties. If neither is found, the user is asked to supply a profile
+ * name that is added to the configuration property set. See the
+ * <a href="cache/DefaultBundleCache.html"><tt>DefaultBundleCache</tt></a>
+ * documentation for more details its configuration options.
+ * </li>
+ * <li><i><b>Creates and starts a framework instance.</b></i> A
+ * case insensitive
+ * <a href="util/StringMap.html"><tt>StringMap</tt></a>
+ * is created for the configuration property file and is passed
+ * into the framework.
+ * </li>
+ * </ol>
+ * <p>
+ * It should be noted that simply starting an instance of the framework is not enough
+ * to create an interactive session with it. It is necessary to install
+ * and start bundles that provide an interactive impl; this is generally
+ * done by specifying an "auto-start" property in the framework configuration
+ * property file. If no interactive impl bundles are installed or if
+ * the configuration property file cannot be found, the framework will appear to
+ * be hung or deadlocked. This is not the case, it is executing correctly,
+ * there is just no way to interact with it. Refer to the
+ * <a href="Felix.html#Felix(java.util.Map, java.util.List)">
+ * <tt>Felix</tt></a> constructor documentation for more information on
+ * framework configuration options.
+ * </p>
+// * @param args An array of arguments, all of which are ignored.
+// * @throws Exception If an error occurs.
+ **/
+// public static void main(String[] args) throws Exception {
+// while (true) {
+// boolean restart = false;
+// System.setProperty("karaf.restart", "false");
+// if (Boolean.getBoolean("karaf.restart.clean")) {
+// File karafHome = Utils.getKarafHome();
+// File karafBase = Utils.getKarafDirectory(PROP_KARAF_BASE, ENV_KARAF_BASE, karafHome, false, true);
+// File karafData = Utils.getKarafDirectory(PROP_KARAF_DATA, ENV_KARAF_DATA, new File(karafBase, "data"), true, true);
+// Utils.deleteDirectory(karafData);
+// }
+// final Main main = new Main(args);
+// try {
+// main.launch();
+// } catch (Throwable ex) {
+// main.setExitCode(-1);
+// System.err.println("Could not create framework: " + ex);
+// ex.printStackTrace();
+// }
+// try {
+// main.awaitShutdown();
+// boolean stopped = main.destroy();
+// restart = Boolean.getBoolean("karaf.restart");
+// if (!stopped) {
+// if (restart) {
+// System.err.println("Timeout waiting for framework to stop. Restarting now.");
+// } else {
+// System.err.println("Timeout waiting for framework to stop. Exiting VM.");
+// main.setExitCode(-3);
+// }
+// }
+// } catch (Throwable ex) {
+// main.setExitCode(-2);
+// System.err.println("Error occured shutting down framework: " + ex);
+// ex.printStackTrace();
+// } finally {
+// if (!restart) {
+// System.exit(main.getExitCode());
+// }
+// }
+// }
+// }
+
+ private static void processSecurityProperties(Properties m_configProps) {
+ String prop = m_configProps.getProperty("org.apache.karaf.security.providers");
+ if (prop != null) {
+ String[] providers = prop.split(",");
+ for (String provider : providers) {
+ addProvider(provider);
+ }
+ }
+ }
+
+ private static void addProvider(String provider) {
+ try {
+ Security.addProvider((Provider) Class.forName(provider).newInstance());
+ } catch (Throwable t) {
+ System.err.println("Unable to register security provider: " + t);
+ }
+ }
+
+ private void updateInstancePid() {
+ try {
+ String instanceName = System.getProperty("karaf.name");
+ String pid = ManagementFactory.getRuntimeMXBean().getName();
+ if (pid.indexOf('@') > 0) {
+ pid = pid.substring(0, pid.indexOf('@'));
+ }
+
+ boolean isRoot = karafHome.equals(karafBase);
+
+ if (instanceName != null) {
+ String storage = System.getProperty("karaf.instances");
+ if (storage == null) {
+ throw new Exception("System property 'karaf.instances' is not set. \n" +
+ "This property needs to be set to the full path of the instance.properties file.");
+ }
+ File storageFile = new File(storage);
+ File propertiesFile = new File(storageFile, "instance.properties");
+ Properties props = new Properties();
+ if (propertiesFile.exists()) {
+ FileInputStream fis = new FileInputStream(propertiesFile);
+ props.load(fis);
+ int count = Integer.parseInt(props.getProperty("count"));
+ for (int i = 0; i < count; i++) {
+ String name = props.getProperty("item." + i + ".name");
+ if (name.equals(instanceName)) {
+ props.setProperty("item." + i + ".pid", pid);
+ FileOutputStream fos = new FileOutputStream(propertiesFile);
+ props.store(fos, null);
+ fis.close();
+ fos.close();
+ return;
+ }
+ }
+ fis.close();
+ if (!isRoot) {
+ throw new Exception("Instance " + instanceName + " not found");
+ }
+ } else if (isRoot) {
+ if (!propertiesFile.getParentFile().exists()) {
+ try {
+ propertiesFile.getParentFile().mkdirs();
+ } catch (SecurityException se) {
+ throw new Exception(se.getMessage());
+ }
+ }
+ props.setProperty("count", "1");
+ props.setProperty("item.0.name", instanceName);
+ props.setProperty("item.0.loc", karafHome.getAbsolutePath());
+ props.setProperty("item.0.pid", pid);
+ props.setProperty("item.0.root", "true");
+ FileOutputStream fos = new FileOutputStream(propertiesFile);
+ props.store(fos, null);
+ fos.close();
+ }
+ }
+ } catch (Exception e) {
+ System.err.println("Unable to update instance pid: " + e.getMessage());
+ }
+ }
+
+ /**
+ * <p/>
+ * Processes the auto-install and auto-start properties from the
+ * specified configuration properties.
+ *
+ * @param context the system bundle context
+ */
+ private void processAutoProperties(BundleContext context) {
+ // Check if we want to convert URLs to maven style
+ boolean convertToMavenUrls = Boolean.parseBoolean(configProps.getProperty(PROPERTY_CONVERT_TO_MAVEN_URL, "true"));
+
+ // Retrieve the Start Level service, since it will be needed
+ // to set the start level of the installed bundles.
+ StartLevel sl = (StartLevel) context.getService(
+ context.getServiceReference(org.osgi.service.startlevel.StartLevel.class.getName()));
+
+ // Set the default bundle start level
+ int ibsl = 60;
+ try {
+ String str = configProps.getProperty("karaf.startlevel.bundle");
+ if (str != null) {
+ ibsl = Integer.parseInt(str);
+ }
+ } catch (Throwable t) {
+ }
+ sl.setInitialBundleStartLevel(ibsl);
+
+ // The auto-install property specifies a space-delimited list of
+ // bundle URLs to be automatically installed into each new profile;
+ // the start level to which the bundles are assigned is specified by
+ // appending a ".n" to the auto-install property name, where "n" is
+ // the desired start level for the list of bundles.
+ autoInstall(PROPERTY_AUTO_INSTALL, context, sl, convertToMavenUrls, false);
+
+ // The auto-start property specifies a space-delimited list of
+ // bundle URLs to be automatically installed and started into each
+ // new profile; the start level to which the bundles are assigned
+ // is specified by appending a ".n" to the auto-start property name,
+ // where "n" is the desired start level for the list of bundles.
+ // The following code starts bundles in one pass, installing bundles
+ // for a given level, then starting them, then moving to the next level.
+ autoInstall(PROPERTY_AUTO_START, context, sl, convertToMavenUrls, true);
+ }
+
+ private List<Bundle> autoInstall(String propertyPrefix, BundleContext context, StartLevel sl, boolean convertToMavenUrls, boolean start) {
+ Map<Integer, String> autoStart = new TreeMap<Integer, String>();
+ List<Bundle> bundles = new ArrayList<Bundle>();
+ for (Object o : configProps.keySet()) {
+ String key = (String) o;
+ // Ignore all keys that are not the auto-start property.
+ if (!key.startsWith(propertyPrefix)) {
+ continue;
+ }
+ // If the auto-start property does not have a start level,
+ // then assume it is the default bundle start level, otherwise
+ // parse the specified start level.
+ int startLevel = sl.getInitialBundleStartLevel();
+ if (!key.equals(propertyPrefix)) {
+ try {
+ startLevel = Integer.parseInt(key.substring(key.lastIndexOf('.') + 1));
+ } catch (NumberFormatException ex) {
+ System.err.println("Invalid property: " + key);
+ }
+ }
+ autoStart.put(startLevel, configProps.getProperty(key));
+ }
+ for (Integer startLevel : autoStart.keySet()) {
+ StringTokenizer st = new StringTokenizer(autoStart.get(startLevel), "\" ", true);
+ if (st.countTokens() > 0) {
+ String location;
+ do {
+ location = nextLocation(st);
+ if (location != null) {
+ try {
+ String[] parts = convertToMavenUrlsIfNeeded(location, convertToMavenUrls);
+ Bundle b = context.installBundle(parts[0], new URL(parts[1]).openStream());
+ sl.setBundleStartLevel(b, startLevel);
+ bundles.add(b);
+ }
+ catch (Exception ex) {
+ System.err.println("Error installing bundle " + location + ": " + ex);
+ }
+ }
+ }
+ while (location != null);
+ }
+ }
+ // Now loop through and start the installed bundles.
+ if (start) {
+ for (Bundle b : bundles) {
+ try {
+ String fragmentHostHeader = (String) b.getHeaders().get(Constants.FRAGMENT_HOST);
+ if (fragmentHostHeader == null || fragmentHostHeader.trim().length() == 0) {
+ b.start();
+ }
+ }
+ catch (Exception ex) {
+ System.err.println("Error starting bundle " + b.getSymbolicName() + ": " + ex);
+ }
+ }
+ }
+ return bundles;
+ }
+
+ private static String[] convertToMavenUrlsIfNeeded(String location, boolean convertToMavenUrls) {
+ String[] parts = location.split("\\|");
+ if (convertToMavenUrls) {
+ String[] p = parts[1].split("/");
+ if (p.length >= 4 && p[p.length-1].startsWith(p[p.length-3] + "-" + p[p.length-2])) {
+ String artifactId = p[p.length-3];
+ String version = p[p.length-2];
+ String classifier;
+ String type;
+ String artifactIdVersion = artifactId + "-" + version;
+ StringBuffer sb = new StringBuffer();
+ if (p[p.length-1].charAt(artifactIdVersion.length()) == '-') {
+ classifier = p[p.length-1].substring(artifactIdVersion.length() + 1, p[p.length-1].lastIndexOf('.'));
+ } else {
+ classifier = null;
+ }
+ type = p[p.length-1].substring(p[p.length-1].lastIndexOf('.') + 1);
+ sb.append("mvn:");
+ for (int j = 0; j < p.length - 3; j++) {
+ if (j > 0) {
+ sb.append('.');
+ }
+ sb.append(p[j]);
+ }
+ sb.append('/').append(artifactId).append('/').append(version);
+ if (!"jar".equals(type) || classifier != null) {
+ sb.append('/');
+ if (!"jar".equals(type)) {
+ sb.append(type);
+ }
+ if (classifier != null) {
+ sb.append('/').append(classifier);
+ }
+ }
+ parts[1] = parts[0];
+ parts[0] = sb.toString();
+ } else {
+ parts[1] = parts[0];
+ }
+ } else {
+ parts[1] = parts[0];
+ }
+ return parts;
+ }
+
+ private static String nextLocation(StringTokenizer st) {
+ String retVal = null;
+
+ if (st.countTokens() > 0) {
+ String tokenList = "\" ";
+ StringBuffer tokBuf = new StringBuffer(10);
+ String tok;
+ boolean inQuote = false;
+ boolean tokStarted = false;
+ boolean exit = false;
+ while ((st.hasMoreTokens()) && (!exit)) {
+ tok = st.nextToken(tokenList);
+ if (tok.equals("\"")) {
+ inQuote = !inQuote;
+ if (inQuote) {
+ tokenList = "\"";
+ } else {
+ tokenList = "\" ";
+ }
+
+ } else if (tok.equals(" ")) {
+ if (tokStarted) {
+ retVal = tokBuf.toString();
+ tokStarted = false;
+ tokBuf = new StringBuffer(10);
+ exit = true;
+ }
+ } else {
+ tokStarted = true;
+ tokBuf.append(tok.trim());
+ }
+ }
+
+ // Handle case where end of token stream and
+ // still got data
+ if ((!exit) && (tokStarted)) {
+ retVal = tokBuf.toString();
+ }
+ }
+
+ return retVal;
+ }
+
+ /**
+ * <p>
+ * Loads the properties in the system property file associated with the
+ * framework installation into <tt>System.setProperty()</tt>. These properties
+ * are not directly used by the framework in anyway. By default, the system
+ * property file is located in the <tt>conf/</tt> directory of the Felix
+ * installation directory and is called "<tt>system.properties</tt>". The
+ * installation directory of Felix is assumed to be the parent directory of
+ * the <tt>felix.jar</tt> file as found on the system class path property.
+ * The precise file from which to load system properties can be set by
+ * initializing the "<tt>felix.system.properties</tt>" system property to an
+ * arbitrary URL.
+ * </p>
+ *
+ * @param karafBase the karaf base folder
+ */
+ protected static void loadSystemProperties(File karafBase) {
+ // The system properties file is either specified by a system
+ // property or it is in the same directory as the Felix JAR file.
+ // Try to load it from one of these places.
+
+ // See if the property URL was specified as a property.
+ URL propURL;
+ try {
+ File file = new File(new File(karafBase, "etc"), SYSTEM_PROPERTIES_FILE_NAME);
+ propURL = file.toURI().toURL();
+ }
+ catch (MalformedURLException ex) {
+ System.err.print("Main: " + ex);
+ return;
+ }
+
+ // Read the properties file.
+ Properties props = new Properties();
+ InputStream is = null;
+ try {
+ is = propURL.openConnection().getInputStream();
+ props.load(is);
+ is.close();
+ }
+ catch (FileNotFoundException ex) {
+ // Ignore file not found.
+ }
+ catch (Exception ex) {
+ System.err.println(
+ "Main: Error loading system properties from " + propURL);
+ System.err.println("Main: " + ex);
+ try {
+ if (is != null) is.close();
+ }
+ catch (IOException ex2) {
+ // Nothing we can do.
+ }
+ return;
+ }
+
+ // Perform variable substitution on specified properties.
+ for (Enumeration e = props.propertyNames(); e.hasMoreElements();) {
+ String name = (String) e.nextElement();
+ String value = System.getProperty(name, props.getProperty(name));
+ System.setProperty(name, substVars(value, name, null, null));
+ }
+ }
+
+ /**
+ * <p>
+ * Loads the configuration properties in the configuration property file
+ * associated with the framework installation; these properties
+ * are accessible to the framework and to bundles and are intended
+ * for configuration purposes. By default, the configuration property
+ * file is located in the <tt>conf/</tt> directory of the Felix
+ * installation directory and is called "<tt>config.properties</tt>".
+ * The installation directory of Felix is assumed to be the parent
+ * directory of the <tt>felix.jar</tt> file as found on the system class
+ * path property. The precise file from which to load configuration
+ * properties can be set by initializing the "<tt>felix.config.properties</tt>"
+ * system property to an arbitrary URL.
+ * </p>
+ *
+ * @return A <tt>Properties</tt> instance or <tt>null</tt> if there was an error.
+ * @throws Exception if something wrong occurs
+ */
+ private Properties loadConfigProperties() throws Exception {
+ // The config properties file is either specified by a system
+ // property or it is in the conf/ directory of the Felix
+ // installation directory. Try to load it from one of these
+ // places.
+
+ List<File> bundleDirs = new ArrayList<File>();
+
+ // See if the property URL was specified as a property.
+ URL configPropURL;
+ URL startupPropURL;
+
+// File file = new File(new File(karafBase, "etc"), CONFIG_PROPERTIES_FILE_NAME);
+ configPropURL = getClass().getClassLoader().getResource(etcLocation + CONFIG_PROPERTIES_FILE_NAME);
+
+// file = new File(new File(karafBase, "etc"), STARTUP_PROPERTIES_FILE_NAME);
+ startupPropURL = getClass().getClassLoader().getResource(etcLocation + STARTUP_PROPERTIES_FILE_NAME);
+
+ if (configPropURL == null) {
+ System.err.println("Could not locate config.properties file in classpath at " + etcLocation + CONFIG_PROPERTIES_FILE_NAME);
+ return null;
+ }
+ if (startupPropURL == null) {
+ System.err.println("Could not locate startup.properties file in classpath at " + etcLocation + CONFIG_PROPERTIES_FILE_NAME);
+ return null;
+ }
+
+ Properties configProps = loadPropertiesFile(configPropURL, false);
+ Properties startupProps = loadPropertiesFile(startupPropURL, true);
+
+ String defaultRepo = System.getProperty(DEFAULT_REPO, "system");
+
+ if (karafBase.equals(karafHome)) {
+ bundleDirs.add(new File(karafHome, defaultRepo));
+ } else {
+ bundleDirs.add(new File(karafBase, defaultRepo));
+ bundleDirs.add(new File(karafHome, defaultRepo));
+ }
+
+ String locations = configProps.getProperty(BUNDLE_LOCATIONS);
+
+ if (locations != null) {
+ StringTokenizer st = new StringTokenizer(locations, "\" ", true);
+ if (st.countTokens() > 0) {
+ String location;
+ do {
+ location = nextLocation(st);
+ if (location != null) {
+ File f;
+ if (karafBase.equals(karafHome)) {
+ f = new File(karafHome, location);
+ } else {
+ f = new File(karafBase, location);
+ }
+ if (f.exists() && f.isDirectory()) {
+ bundleDirs.add(f);
+ } else {
+ System.err.println("Bundle location " + location
+ + " does not exist or is not a directory.");
+ }
+ }
+ }
+
+ while (location != null);
+ }
+ }
+
+ // Perform variable substitution for system properties.
+ for (Enumeration e = configProps.propertyNames(); e.hasMoreElements();) {
+ String name = (String) e.nextElement();
+ configProps.setProperty(name,
+ substVars(configProps.getProperty(name), name, null, configProps));
+ }
+
+ // Mutate properties
+ processConfigurationProperties(configProps, startupProps, bundleDirs);
+
+ return configProps;
+ }
+
+ protected static Properties loadPropertiesFile(URL configPropURL, boolean failIfNotFound) throws Exception {
+ // Read the properties file.
+ Properties configProps = new Properties();
+ InputStream is = null;
+ try {
+ is = configPropURL.openConnection().getInputStream();
+ configProps.load(is);
+ is.close();
+ }
+ catch (FileNotFoundException ex) {
+ if (failIfNotFound) {
+ throw ex;
+ }
+ }
+ catch (Exception ex) {
+ System.err.println("Error loading config properties from " + configPropURL);
+ System.err.println("Main: " + ex);
+ return configProps;
+ } finally {
+ try {
+ if (is != null) {
+ is.close();
+ }
+ }
+ catch (IOException ex2) {
+ // Nothing we can do.
+ }
+ }
+ String includes = configProps.getProperty(INCLUDES_PROPERTY);
+ if (includes != null) {
+ StringTokenizer st = new StringTokenizer(includes, "\" ", true);
+ if (st.countTokens() > 0) {
+ String location;
+ do {
+ location = nextLocation(st);
+ if (location != null) {
+ URL url = new URL(configPropURL, location);
+ Properties props = loadPropertiesFile(url, true);
+ configProps.putAll(props);
+ }
+ }
+ while (location != null);
+ }
+ configProps.remove(INCLUDES_PROPERTY);
+ }
+ for (Enumeration e = configProps.propertyNames(); e.hasMoreElements();) {
+ Object key = e.nextElement();
+ if (key instanceof String) {
+ String v = configProps.getProperty((String) key);
+ configProps.put(key, v.trim());
+ }
+ }
+ return configProps;
+ }
+
+ protected static void copySystemProperties(Properties configProps) {
+ for (Enumeration e = System.getProperties().propertyNames();
+ e.hasMoreElements();) {
+ String key = (String) e.nextElement();
+ if (key.startsWith("felix.") ||
+ key.startsWith("karaf.") ||
+ key.startsWith("org.osgi.framework.")) {
+ configProps.setProperty(key, System.getProperty(key));
+ }
+ }
+ }
+
+ private ClassLoader createClassLoader(Properties configProps) throws Exception {
+ return getClass().getClassLoader();
+// String framework = configProps.getProperty(KARAF_FRAMEWORK);
+// if (framework == null) {
+// throw new IllegalArgumentException("Property " + KARAF_FRAMEWORK + " must be set in the etc/" + CONFIG_PROPERTIES_FILE_NAME + " configuration file");
+// }
+// String bundle = configProps.getProperty(KARAF_FRAMEWORK + "." + framework);
+// if (bundle == null) {
+// throw new IllegalArgumentException("Property " + KARAF_FRAMEWORK + "." + framework + " must be set in the etc/" + CONFIG_PROPERTIES_FILE_NAME + " configuration file");
+// }
+// File bundleFile = new File(karafBase, bundle);
+// if (!bundleFile.exists()) {
+// bundleFile = new File(karafHome, bundle);
+// }
+// if (!bundleFile.exists()) {
+// throw new FileNotFoundException(bundleFile.getAbsolutePath());
+// }
+//
+// List<URL> urls = new ArrayList<URL>();
+// urls.add( bundleFile.toURI().toURL() );
+// File[] libs = new File(karafHome, "lib").listFiles();
+// if (libs != null) {
+// for (File f : libs) {
+// if (f.isFile() && f.canRead() && f.getName().endsWith(".jar")) {
+// urls.add(f.toURI().toURL());
+// }
+// }
+// }
+//
+// return new URLClassLoader(urls.toArray(new URL[urls.size()]), Main.class.getClassLoader());
+ }
+
+ /**
+ * Process properties to customize default felix behavior
+ *
+ * @param configProps properties loaded from etc/config.properties
+ * @param startupProps properties loaded from etc/startup.properties
+ * @param bundleDirs location to load bundles from (usually system/)
+ */
+ private void processConfigurationProperties(Properties configProps, Properties startupProps, List<File> bundleDirs) {
+ if (bundleDirs == null) {
+ return;
+ }
+ if ("all".equals(configProps.getProperty(PROPERTY_AUTO_START, "").trim())) {
+ configProps.remove(PROPERTY_AUTO_START);
+ ArrayList<File> jars = new ArrayList<File>();
+
+ // We should start all the bundles in the system dir.
+ for (File bundleDir : bundleDirs) {
+ findJars(bundleDir, jars);
+ }
+
+ StringBuffer sb = new StringBuffer();
+
+ for (File jar : jars) {
+ try {
+ sb.append("\"").append(jar.toURI().toURL().toString()).append("\" ");
+ } catch (MalformedURLException e) {
+ System.err.print("Ignoring " + jar.toString() + " (" + e + ")");
+ }
+ }
+
+ configProps.setProperty(PROPERTY_AUTO_START, sb.toString());
+
+ } else if (STARTUP_PROPERTIES_FILE_NAME.equals(configProps.getProperty(PROPERTY_AUTO_START, "").trim())) {
+ configProps.remove(PROPERTY_AUTO_START);
+ // We should start the bundles in the startup.properties file.
+ HashMap<Integer, StringBuffer> levels = new HashMap<Integer, StringBuffer>();
+ for (Object o : startupProps.keySet()) {
+ String name = (String) o;
+ File file = resolver == null? findFile(bundleDirs, name): resolver.resolve(name);
+
+ if (file != null) {
+ Integer level;
+ try {
+ level = new Integer(startupProps.getProperty(name).trim());
+ } catch (NumberFormatException e1) {
+ System.err.print("Ignoring " + file.toString() + " (run level must be an integer)");
+ continue;
+ }
+ StringBuffer sb = levels.get(level);
+ if (sb == null) {
+ sb = new StringBuffer(256);
+ levels.put(level, sb);
+ }
+ try {
+ sb.append("\"").append(file.toURI().toURL().toString()).append("|").append(name).append("\" ");
+ } catch (MalformedURLException e) {
+ System.err.print("Ignoring " + file.toString() + " (" + e + ")");
+ }
+ } else {
+ System.err.println("Bundle listed in " + STARTUP_PROPERTIES_FILE_NAME + " configuration not found: " + name);
+ }
+ }
+
+ for (Map.Entry<Integer, StringBuffer> entry : levels.entrySet()) {
+ configProps.setProperty(PROPERTY_AUTO_START + "." + entry.getKey(), entry.getValue().toString());
+ }
+ }
+
+ }
+
+ private static File findFile(List<File> bundleDirs, String name) {
+ for (File bundleDir : bundleDirs) {
+ File file = findFile(bundleDir, name);
+ if (file != null) {
+ return file;
+ }
+ }
+ return null;
+ }
+
+ private static File findFile(File dir, String name) {
+ name = fromMaven(name);
+ File theFile = new File(dir, name);
+
+ if (theFile.exists() && !theFile.isDirectory()) {
+ return theFile;
+ }
+ return null;
+ }
+
+ /**
+ * Returns a path for an srtifact.
+ * Input: path (no ':') returns path
+ * Input: mvn:<groupId>/<artifactId>/<version>/<type>/<classifier> converts to default repo location path
+ * Input: <groupId>:<artifactId>:<version>:<type>:<classifier> converts to default repo location path
+ * type and classifier are optional.
+ *
+ *
+ * @param name input artifact info
+ * @return path as supplied or a default maven repo path
+ */
+ private static String fromMaven(String name) {
+ if (name.indexOf(':') == -1) {
+ return name;
+ }
+ int firstBit = 0;
+ if (name.startsWith("mvn:")) {
+ firstBit = 1;
+ }
+ String[] bits = name.split("[:/]");
+ StringBuilder b = new StringBuilder(bits[firstBit]);
+ for (int i = 0; i < b.length(); i++) {
+ if (b.charAt(i) == '.') {
+ b.setCharAt(i, '/');
+ }
+ }
+ b.append('/').append(bits[firstBit + 1]); //artifactId
+ b.append('/').append(bits[firstBit + 2]); //version
+ b.append('/').append(bits[firstBit + 1]).append('-').append(bits[firstBit + 2]);
+ if (bits.length == firstBit + 5 && !bits[firstBit + 4].isEmpty()) {
+ b.append('-').append(bits[firstBit + 4]); //classifier
+ }
+ if (bits.length >= firstBit + 4 && !bits[firstBit + 3].isEmpty()) {
+ b.append('.').append(bits[firstBit + 3]);
+ } else {
+ b.append(".jar");
+ }
+ return b.toString();
+ }
+
+ private static void findJars(File dir, ArrayList<File> jars) {
+ for (File file : dir.listFiles()) {
+ if (file.isDirectory()) {
+ findJars(file, jars);
+ } else {
+ if (file.toString().endsWith(".jar")) {
+ jars.add(file);
+ }
+ }
+ }
+ }
+
+ private static final String DELIM_START = "${";
+ private static final String DELIM_STOP = "}";
+
+ /**
+ * <p>
+ * This method performs property variable substitution on the
+ * specified value. If the specified value contains the syntax
+ * <tt>${<prop-name>}</tt>, where <tt><prop-name></tt>
+ * refers to either a configuration property or a system property,
+ * then the corresponding property value is substituted for the variable
+ * placeholder. Multiple variable placeholders may exist in the
+ * specified value as well as nested variable placeholders, which
+ * are substituted from inner most to outer most. Configuration
+ * properties override system properties.
+ * </p>
+ *
+ * @param val The string on which to perform property substitution.
+ * @param currentKey The key of the property being evaluated used to
+ * detect cycles.
+ * @param cycleMap Map of variable references used to detect nested cycles.
+ * @param configProps Set of configuration properties.
+ * @return The value of the specified string after system property substitution.
+ * @throws IllegalArgumentException If there was a syntax error in the
+ * property placeholder syntax or a recursive variable reference.
+ */
+ public static String substVars(String val, String currentKey,
+ Map<String, String> cycleMap, Properties configProps)
+ throws IllegalArgumentException {
+ // If there is currently no cycle map, then create
+ // one for detecting cycles for this invocation.
+ if (cycleMap == null) {
+ cycleMap = new HashMap<String, String>();
+ }
+
+ // Put the current key in the cycle map.
+ cycleMap.put(currentKey, currentKey);
+
+ // Assume we have a value that is something like:
+ // "leading ${foo.${bar}} middle ${baz} trailing"
+
+ // Find the first ending '}' variable delimiter, which
+ // will correspond to the first deepest nested variable
+ // placeholder.
+ int stopDelim = val.indexOf(DELIM_STOP);
+
+ // Find the matching starting "${" variable delimiter
+ // by looping until we find a start delimiter that is
+ // greater than the stop delimiter we have found.
+ int startDelim = val.indexOf(DELIM_START);
+ while (stopDelim >= 0) {
+ int idx = val.indexOf(DELIM_START, startDelim + DELIM_START.length());
+ if ((idx < 0) || (idx > stopDelim)) {
+ break;
+ } else if (idx < stopDelim) {
+ startDelim = idx;
+ }
+ }
+
+ // If we do not have a start or stop delimiter, then just
+ // return the existing value.
+ if ((startDelim < 0) && (stopDelim < 0)) {
+ return val;
+ }
+ // At this point, we found a stop delimiter without a start,
+ // so throw an exception.
+ else if (((startDelim < 0) || (startDelim > stopDelim))
+ && (stopDelim >= 0)) {
+ throw new IllegalArgumentException(
+ "stop delimiter with no start delimiter: "
+ + val);
+ }
+
+ // At this point, we have found a variable placeholder so
+ // we must perform a variable substitution on it.
+ // Using the start and stop delimiter indices, extract
+ // the first, deepest nested variable placeholder.
+ String variable =
+ val.substring(startDelim + DELIM_START.length(), stopDelim);
+
+ // Verify that this is not a recursive variable reference.
+ if (cycleMap.get(variable) != null) {
+ throw new IllegalArgumentException(
+ "recursive variable reference: " + variable);
+ }
+
+ // Get the value of the deepest nested variable placeholder.
+ // Try to configuration properties first.
+ String substValue = (configProps != null)
+ ? configProps.getProperty(variable, null)
+ : null;
+ if (substValue == null) {
+ // Ignore unknown property values.
+ substValue = System.getProperty(variable, "");
+ }
+
+ // Remove the found variable from the cycle map, since
+ // it may appear more than once in the value and we don't
+ // want such situations to appear as a recursive reference.
+ cycleMap.remove(variable);
+
+ // Append the leading characters, the substituted value of
+ // the variable, and the trailing characters to get the new
+ // value.
+ val = val.substring(0, startDelim)
+ + substValue
+ + val.substring(stopDelim + DELIM_STOP.length(), val.length());
+
+ // Now perform substitution again, since there could still
+ // be substitutions to make.
+ val = substVars(val, currentKey, cycleMap, configProps);
+
+ // Return the value.
+ return val;
+ }
+
+ public Framework getFramework() {
+ return framework;
+ }
+
+ public void lock(Properties props) {
+ try {
+ if (Boolean.parseBoolean(props.getProperty(PROPERTY_USE_LOCK, "true"))) {
+ doLock(props);
+ } else {
+ setStartLevel(defaultStartLevel);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void doLock(Properties props) throws Exception {
+ String clz = props.getProperty(PROPERTY_LOCK_CLASS, PROPERTY_LOCK_CLASS_DEFAULT);
+ lock = (Lock) Class.forName(clz).getConstructor(Properties.class).newInstance(props);
+ boolean lockLogged = false;
+ setStartLevel(lockStartLevel);
+ while (!exiting) {
+ if (lock.lock()) {
+ if (lockLogged) {
+ LOG.info("Lock acquired.");
+ }
+ setupShutdown(props);
+ setStartLevel(defaultStartLevel);
+ for (;;) {
+ if (!lock.isAlive()) {
+ break;
+ }
+ Thread.sleep(lockDelay);
+ }
+ if (framework.getState() == Bundle.ACTIVE && !exiting) {
+ LOG.info("Lost the lock, stopping this instance ...");
+ setStartLevel(lockStartLevel);
+ }
+ } else if (!lockLogged) {
+ LOG.info("Waiting for the lock ...");
+ lockLogged = true;
+ }
+ Thread.sleep(lockDelay);
+ }
+ }
+
+ public void unlock() throws Exception {
+ if (lock != null) {
+ lock.release();
+ }
+ }
+
+ protected void setStartLevel(int level) throws Exception {
+ BundleContext ctx = framework.getBundleContext();
+ ServiceReference[] refs = ctx.getServiceReferences(StartLevel.class.getName(), null);
+ StartLevel sl = (StartLevel) ctx.getService(refs[0]);
+ sl.setStartLevel(level);
+ }
+
+
+ private Random random = null;
+ private ServerSocket shutdownSocket;
+
+ protected void setupShutdown(Properties props) {
+ writePid(props);
+ try {
+ int port = Integer.parseInt(props.getProperty(KARAF_SHUTDOWN_PORT, "0"));
+ String host = props.getProperty(KARAF_SHUTDOWN_HOST, "localhost");
+ String portFile = props.getProperty(KARAF_SHUTDOWN_PORT_FILE);
+ final String shutdown = props.getProperty(KARAF_SHUTDOWN_COMMAND, DEFAULT_SHUTDOWN_COMMAND);
+ if (port >= 0) {
+ shutdownSocket = new ServerSocket(port, 1, InetAddress.getByName(host));
+ if (port == 0) {
+ port = shutdownSocket.getLocalPort();
+ }
+ if (portFile != null) {
+ Writer w = new OutputStreamWriter(new FileOutputStream(portFile));
+ w.write(Integer.toString(port));
+ w.close();
+ }
+ Thread thread = new ShutdownSocketThread(shutdown);
+ thread.setDaemon(true);
+ thread.start();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void writePid(Properties props) {
+ try {
+ String pidFile = props.getProperty(KARAF_SHUTDOWN_PID_FILE);
+ if (pidFile != null) {
+ RuntimeMXBean rtb = ManagementFactory.getRuntimeMXBean();
+ String processName = rtb.getName();
+ Pattern pattern = Pattern.compile("^([0-9]+)@.+$", Pattern.CASE_INSENSITIVE);
+ Matcher matcher = pattern.matcher(processName);
+ if (matcher.matches()) {
+ int pid = Integer.parseInt(matcher.group(1));
+ Writer w = new OutputStreamWriter(new FileOutputStream(pidFile));
+ w.write(Integer.toString(pid));
+ w.close();
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private class ShutdownSocketThread extends Thread {
+
+ private final String shutdown;
+
+ public ShutdownSocketThread(String shutdown) {
+ this.shutdown = shutdown;
+ }
+
+ public void run() {
+ try {
+ while (true) {
+ // Wait for the next connection
+ Socket socket = null;
+ InputStream stream = null;
+ try {
+ socket = shutdownSocket.accept();
+ socket.setSoTimeout(10 * 1000); // Ten seconds
+ stream = socket.getInputStream();
+ } catch (AccessControlException ace) {
+ LOG.log(Level.WARNING, "Karaf shutdown socket: security exception: "
+ + ace.getMessage(), ace);
+ continue;
+ } catch (IOException e) {
+ LOG.log(Level.SEVERE, "Karaf shutdown socket: accept: ", e);
+ System.exit(1);
+ }
+
+ // Read a set of characters from the socket
+ StringBuilder command = new StringBuilder();
+ int expected = 1024; // Cut off to avoid DoS attack
+ while (expected < shutdown.length()) {
+ if (random == null) {
+ random = new Random();
+ }
+ expected += (random.nextInt() % 1024);
+ }
+ while (expected > 0) {
+ int ch;
+ try {
+ ch = stream.read();
+ } catch (IOException e) {
+ LOG.log(Level.WARNING, "Karaf shutdown socket: read: ", e);
+ ch = -1;
+ }
+ if (ch < 32) { // Control character or EOF terminates loop
+ break;
+ }
+ command.append((char) ch);
+ expected--;
+ }
+
+ // Close the socket now that we are done with it
+ try {
+ socket.close();
+ } catch (IOException e) {
+ // Ignore
+ }
+
+ // Match against our command string
+ boolean match = command.toString().equals(shutdown);
+ if (match) {
+ LOG.log(Level.INFO, "Karaf shutdown socket: received shutdown command. Stopping framework...");
+ framework.stop();
+ break;
+ } else {
+ LOG.log(Level.WARNING, "Karaf shutdown socket: Invalid command '" +
+ command.toString() + "' received");
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ shutdownSocket.close();
+ } catch (IOException e) {
+ // Ignore
+ }
+ }
+ }
+ }
+
+ public interface Resolver {
+ File resolve(String id);
+ }
+
+}
Propchange: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/FrameworkHelper.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/FrameworkHelper.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/server/trunk/framework/buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/FrameworkHelper.java
------------------------------------------------------------------------------
svn:mime-type = text/plain