FELIX-1547: OS shell level admin commands for Karaf
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@812616 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/karaf/assembly/src/main/descriptors/unix-bin.xml b/karaf/assembly/src/main/descriptors/unix-bin.xml
index 3ca944c..090f403 100644
--- a/karaf/assembly/src/main/descriptors/unix-bin.xml
+++ b/karaf/assembly/src/main/descriptors/unix-bin.xml
@@ -45,6 +45,15 @@
<lineEnding>unix</lineEnding>
</fileSet>
<fileSet>
+ <directory>target/classes/bin</directory>
+ <outputDirectory>/bin/</outputDirectory>
+ <lineEnding>unix</lineEnding>
+ <fileMode>0755</fileMode>
+ <includes>
+ <include>admin</include>
+ </includes>
+ </fileSet>
+ <fileSet>
<directory>target/classes/etc</directory>
<outputDirectory>/etc/</outputDirectory>
<lineEnding>unix</lineEnding>
diff --git a/karaf/assembly/src/main/descriptors/windows-bin.xml b/karaf/assembly/src/main/descriptors/windows-bin.xml
index 0ab16dd..0a09975 100644
--- a/karaf/assembly/src/main/descriptors/windows-bin.xml
+++ b/karaf/assembly/src/main/descriptors/windows-bin.xml
@@ -46,6 +46,14 @@
<lineEnding>dos</lineEnding>
</fileSet>
<fileSet>
+ <directory>target/classes/bin</directory>
+ <outputDirectory>/bin/</outputDirectory>
+ <lineEnding>dos</lineEnding>
+ <includes>
+ <include>admin.bat</include>
+ </includes>
+ </fileSet>
+ <fileSet>
<directory>target/classes/etc</directory>
<outputDirectory>/etc/</outputDirectory>
<lineEnding>dos</lineEnding>
diff --git a/karaf/assembly/src/main/distribution/unix-shell/bin/karaf b/karaf/assembly/src/main/distribution/unix-shell/bin/karaf
index 1a1d90b..d966b03 100755
--- a/karaf/assembly/src/main/distribution/unix-shell/bin/karaf
+++ b/karaf/assembly/src/main/distribution/unix-shell/bin/karaf
@@ -285,12 +285,12 @@
KARAF_BASE=`cygpath --path --windows "$KARAF_BASE"`
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
fi
- exec $JAVA $JAVA_OPTS -Dkaraf.home="$KARAF_HOME" -Dkaraf.base="$KARAF_BASE" -Djava.util.logging.config.file=$KARAF_BASE/etc/java.util.logging.properties $OPTS -classpath "$CLASSPATH" org.apache.felix.karaf.main.Bootstrap $*
+ exec $JAVA $JAVA_OPTS -Dkaraf.home="$KARAF_HOME" -Dkaraf.base="$KARAF_BASE" -Djava.util.logging.config.file=$KARAF_BASE/etc/java.util.logging.properties $OPTS -classpath "$CLASSPATH" org.apache.felix.karaf.main.Bootstrap "$@"
}
main() {
init
- run $@
+ run "$@"
}
-main $@
+main "$@"
diff --git a/karaf/assembly/src/main/filtered-resources/bin/admin b/karaf/assembly/src/main/filtered-resources/bin/admin
new file mode 100644
index 0000000..7b46968
--- /dev/null
+++ b/karaf/assembly/src/main/filtered-resources/bin/admin
@@ -0,0 +1,284 @@
+#!/bin/sh
+#
+# 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.
+#
+#
+
+DIRNAME=`dirname $0`
+PROGNAME=`basename $0`
+
+#
+# Check/Set up some easily accessible MIN/MAX params for JVM mem usage
+#
+
+if [ "x$JAVA_MIN_MEM" = "x" ]; then
+ JAVA_MIN_MEM=128M
+ export JAVA_MIN_MEM
+fi
+
+if [ "x$JAVA_MAX_MEM" = "x" ]; then
+ JAVA_MAX_MEM=512M
+ export JAVA_MAX_MEM
+fi
+
+warn() {
+ echo "${PROGNAME}: $*"
+}
+
+die() {
+ warn "$*"
+ exit 1
+}
+
+maybeSource() {
+ file="$1"
+ if [ -f "$file" ] ; then
+ . $file
+ fi
+}
+
+detectOS() {
+ # OS specific support (must be 'true' or 'false').
+ cygwin=false;
+ darwin=false;
+ aix=false;
+ os400=false;
+ case "`uname`" in
+ CYGWIN*)
+ cygwin=true
+ ;;
+ Darwin*)
+ darwin=true
+ ;;
+ AIX*)
+ aix=true
+ ;;
+ OS400*)
+ os400=true
+ ;;
+ esac
+ # For AIX, set an environment variable
+ if $aix; then
+ export LDR_CNTRL=MAXDATA=0xB0000000@DSA
+ export IBM_JAVA_HEAPDUMP_TEXT=true
+ echo $LDR_CNTRL
+ fi
+}
+
+unlimitFD() {
+ # Use the maximum available, or set MAX_FD != -1 to use that
+ if [ "x$MAX_FD" = "x" ]; then
+ MAX_FD="maximum"
+ fi
+
+ # Increase the maximum file descriptors if we can
+ if [ "$os400" = "false" ] && [ "$cygwin" = "false" ]; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ "$MAX_FD_LIMIT" != 'unlimited' ]; then
+ if [ $? -eq 0 ]; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ]; then
+ # use the system max
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+
+ ulimit -n $MAX_FD > /dev/null
+ # echo "ulimit -n" `ulimit -n`
+ if [ $? -ne 0 ]; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query system maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+ fi
+ fi
+}
+
+locateHome() {
+ if [ "x$KARAF_HOME" != "x" ]; then
+ warn "Ignoring predefined value for KARAF_HOME"
+ fi
+
+ # In POSIX shells, CDPATH may cause cd to write to stdout
+ (unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+ KARAF_HOME=`cd $DIRNAME/..; pwd`
+ if [ ! -d "$KARAF_HOME" ]; then
+ die "KARAF_HOME is not valid: $KARAF_HOME"
+ fi
+}
+
+locateBase() {
+ if [ "x$KARAF_BASE" != "x" ]; then
+ if [ ! -d "$KARAF_BASE" ]; then
+ die "KARAF_BASE is not valid: $KARAF_BASE"
+ fi
+ else
+ KARAF_BASE=$KARAF_HOME
+ fi
+}
+
+setupNativePath() {
+ # Support for loading native libraries
+ LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:$KARAF_BASE/lib:$KARAF_HOME/lib"
+
+ # For Cygwin, set PATH from LD_LIBRARY_PATH
+ if $cygwin; then
+ LD_LIBRARY_PATH=`cygpath --path --windows "$LD_LIBRARY_PATH"`
+ PATH="$PATH;$LD_LIBRARY_PATH"
+ export PATH
+ fi
+ export LD_LIBRARY_PATH
+}
+
+locateJava() {
+ # Setup the Java Virtual Machine
+ if $cygwin ; then
+ [ -n "$JAVA" ] && JAVA=`cygpath --unix "$JAVA"`
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ fi
+
+ if [ "x$JAVA" = "x" ]; then
+ if [ "x$JAVA_HOME" = "x" ] && [ "$darwin" = "true" ]; then
+ JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Home
+ fi
+ if [ "x$JAVA_HOME" != "x" ]; then
+ if [ ! -d "$JAVA_HOME" ]; then
+ die "JAVA_HOME is not valid: $JAVA_HOME"
+ fi
+ JAVA="$JAVA_HOME/bin/java"
+ else
+ warn "JAVA_HOME not set; results may vary"
+ JAVA="java"
+ fi
+ fi
+}
+
+detectJVM() {
+ #echo "`$JAVA -version`"
+ # This service should call `java -version`,
+ # read stdout, and look for hints
+ if $JAVA -version 2>&1 | grep "^IBM" ; then
+ JVM_VENDOR="IBM"
+ # on OS/400, java -version does not contain IBM explicitly
+ elif $os400; then
+ JVM_VENDOR="IBM"
+ else
+ JVM_VENDOR="SUN"
+ fi
+ # echo "JVM vendor is $JVM_VENDOR"
+}
+
+setupDebugOptions() {
+ if [ "x$JAVA_OPTS" = "x" ]; then
+ JAVA_OPTS="$DEFAULT_JAVA_OPTS"
+ fi
+ export JAVA_OPTS
+
+ # Set Debug options if enabled
+ if [ "x$KARAF_DEBUG" != "x" ]; then
+ # Use the defaults if JAVA_DEBUG_OPTS was not set
+ if [ "x$JAVA_DEBUG_OPTS" = "x" ]; then
+ JAVA_DEBUG_OPTS="$DEFAULT_JAVA_DEBUG_OPTS"
+ fi
+
+ JAVA_OPTS="$JAVA_DEBUG_OPTS $JAVA_OPTS"
+ warn "Enabling Java debug options: $JAVA_DEBUG_OPTS"
+ fi
+}
+
+setupDefaults() {
+ DEFAULT_JAVA_OPTS="-Dstorage.file=${KARAF_HOME}/etc/instances.properties -Xms$JAVA_MIN_MEM -Xmx$JAVA_MAX_MEM "
+
+ #Set the JVM_VENDOR specific JVM flags
+ if [ "$JVM_VENDOR" = "SUN" ]; then
+ DEFAULT_JAVA_OPTS="-server $DEFAULT_JAVA_OPTS -Dcom.sun.management.jmxremote"
+ elif [ "$JVM_VENDOR" = "IBM" ]; then
+ if $os400; then
+ DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS"
+ elif $aix; then
+ DEFAULT_JAVA_OPTS="-Xverify:none -Xlp $DEFAULT_JAVA_OPTS"
+ else
+ DEFAULT_JAVA_OPTS="-Xverify:none $DEFAULT_JAVA_OPTS"
+ fi
+ fi
+
+ # Add the jars in the lib dir
+ for file in $KARAF_HOME/lib/*.jar
+ do
+ if [ -z "$CLASSPATH" ]; then
+ CLASSPATH="$file"
+ else
+ CLASSPATH="$CLASSPATH:$file"
+ fi
+ done
+ DEFAULT_JAVA_DEBUG_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"
+
+ ##
+ ## TODO: Move to conf/profiler/yourkit.{sh|cmd}
+ ##
+ # Uncomment to enable YourKit profiling
+ #DEFAULT_JAVA_DEBUG_OPTS="-Xrunyjpagent"
+}
+
+init() {
+ # Determine if there is special OS handling we must perform
+ detectOS
+
+ # Unlimit the number of file descriptors if possible
+ unlimitFD
+
+ # Locate the Karaf home directory
+ locateHome
+
+ # Locate the Karaf base directory
+ locateBase
+
+ # Setup the native library path
+ setupNativePath
+
+ # Locate the Java VM to execute
+ locateJava
+
+ # Determine the JVM vendor
+ detectJVM
+
+ # Setup default options
+ setupDefaults
+
+ # Install debug options
+ setupDebugOptions
+
+}
+
+run() {
+
+ if $cygwin; then
+ KARAF_HOME=`cygpath --path --windows "$KARAF_HOME"`
+ KARAF_BASE=`cygpath --path --windows "$KARAF_BASE"`
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ fi
+
+ CLASSPATH=${KARAF_HOME}/system/org/apache/felix/karaf/gshell/org.apache.felix.karaf.gshell.admin/${project.version}/org.apache.felix.karaf.gshell.admin-${project.version}.jar:${KARAF_HOME}/system/org/apache/felix/karaf/gshell/org.apache.felix.karaf.gshell.console/${project.version}/org.apache.felix.karaf.gshell.console-${project.version}.jar:${KARAF_HOME}/system/org/apache/felix/gogo/org.apache.felix.gogo.runtime/${felix.gogo.version}/org.apache.felix.gogo.runtime-${felix.gogo.version}.jar:${KARAF_HOME}/system/org/apache/geronimo/blueprint-bundle/${geronimo.blueprint.version}/blueprint-bundle-${geronimo.blueprint.version}.jar:${KARAF_HOME}/system/org/ops4j/pax/logging/pax-logging-api/${pax.logging.version}/pax-logging-api-${pax.logging.version}.jar:${KARAF_HOME}/system/org/apache/felix/org.apache.felix.framework/${felix.framework.version}/org.apache.felix.framework-${felix.framework.version}.jar
+
+ exec $JAVA $JAVA_OPTS -Dkaraf.home="$KARAF_HOME" -Dkaraf.base="$KARAF_BASE" -Djava.util.logging.config.file=$KARAF_BASE/etc/java.util.logging.properties $OPTS -classpath "$CLASSPATH" org.apache.felix.karaf.gshell.admin.main.Execute "$@"
+}
+
+main() {
+ init
+ run "$@"
+}
+
+main "$@"
diff --git a/karaf/assembly/src/main/filtered-resources/bin/admin.bat b/karaf/assembly/src/main/filtered-resources/bin/admin.bat
new file mode 100644
index 0000000..d6458f0
--- /dev/null
+++ b/karaf/assembly/src/main/filtered-resources/bin/admin.bat
@@ -0,0 +1,97 @@
+@echo off
+rem
+rem
+rem Licensed to the Apache Software Foundation (ASF) under one or more
+rem contributor license agreements. See the NOTICE file distributed with
+rem this work for additional information regarding copyright ownership.
+rem The ASF licenses this file to You under the Apache License, Version 2.0
+rem (the "License"); you may not use this file except in compliance with
+rem the License. You may obtain a copy of the License at
+rem
+rem http://www.apache.org/licenses/LICENSE-2.0
+rem
+rem Unless required by applicable law or agreed to in writing, software
+rem distributed under the License is distributed on an "AS IS" BASIS,
+rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+rem See the License for the specific language governing permissions and
+rem limitations under the License.
+rem
+rem
+
+if not "%ECHO%" == "" echo %ECHO%
+
+setlocal
+set DIRNAME=%~dp0%
+set PROGNAME=%~nx0%
+set ARGS=%*
+
+goto BEGIN
+
+:warn
+ echo %PROGNAME%: %*
+goto :EOF
+
+:BEGIN
+
+rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+if not "%KARAF_HOME%" == "" (
+ call :warn Ignoring predefined value for KARAF_HOME
+)
+set KARAF_HOME=%DIRNAME%..
+if not exist "%KARAF_HOME%" (
+ call :warn KARAF_HOME is not valid: %KARAF_HOME%
+ goto END
+)
+
+if not "%KARAF_BASE%" == "" (
+ if not exist "%KARAF_BASE%" (
+ call :warn KARAF_BASE is not valid: %KARAF_BASE%
+ goto END
+ )
+)
+if "%KARAF_BASE%" == "" (
+ set KARAF_BASE=%KARAF_HOME%
+)
+
+set DEFAULT_JAVA_OPTS=-Dstorage.file="%KARAF_HOME%\etc\instances.properties"
+set DEFAULT_JAVA_DEBUG_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005
+
+rem Support for loading native libraries
+set PATH=%PATH%;%KARAF_BASE%\lib;%KARAF_HOME%\lib
+
+rem Setup the Java Virtual Machine
+if not "%JAVA%" == "" goto :Check_JAVA_END
+ set JAVA=java
+ if "%JAVA_HOME%" == "" call :warn JAVA_HOME not set; results may vary
+ if not "%JAVA_HOME%" == "" set JAVA=%JAVA_HOME%\bin\java
+ if not exist "%JAVA_HOME%" (
+ call :warn JAVA_HOME is not valid: "%JAVA_HOME%"
+ goto END
+ )
+:Check_JAVA_END
+
+if "%JAVA_OPTS%" == "" set JAVA_OPTS=%DEFAULT_JAVA_OPTS%
+
+if "%KARAF_DEBUG%" == "" goto :KARAF_DEBUG_END
+ rem Use the defaults if JAVA_DEBUG_OPTS was not set
+ if "%JAVA_DEBUG_OPTS%" == "" set JAVA_DEBUG_OPTS=%DEFAULT_JAVA_DEBUG_OPTS%
+
+ set "JAVA_OPTS=%JAVA_DEBUG_OPTS% %JAVA_OPTS%"
+ call :warn Enabling Java debug options: %JAVA_DEBUG_OPTS%
+:KARAF_DEBUG_END
+
+set CLASSPATH=%KARAF_HOME%\system\org\apache\felix\karaf\gshell\org.apache.felix.karaf.gshell.admin\${project.version}\org.apache.felix.karaf.gshell.admin-${project.version}.jar;%KARAF_HOME%\system\org\apache\felix\karaf\gshell\org.apache.felix.karaf.gshell.console\${project.version}\org.apache.felix.karaf.gshell.console-${project.version}.jar;%KARAF_HOME%\system\org\apache\felix\gogo\org.apache.felix.gogo.runtime\${felix.gogo.version}\org.apache.felix.gogo.runtime-${felix.gogo.version}.jar;%KARAF_HOME%\system\org\apache\geronimo\blueprint-bundle\${geronimo.blueprint.version}\blueprint-bundle-${geronimo.blueprint.version}.jar;%KARAF_HOME%\system\org\ops4j\pax\logging\pax-logging-api\${pax.logging.version}\pax-logging-api-${pax.logging.version}.jar;%KARAF_HOME%\system\org\apache\felix\org.apache.felix.framework\${felix.framework.version}\org.apache.felix.framework-${felix.framework.version}.jar
+
+:EXECUTE
+ if "%SHIFT%" == "true" SET ARGS=%2 %3 %4 %5 %6 %7 %8
+ if not "%SHIFT%" == "true" SET ARGS=%1 %2 %3 %4 %5 %6 %7 %8
+ rem Execute the Java Virtual Machine
+ "%JAVA%" %JAVA_OPTS% %OPTS% -classpath "%CLASSPATH%" -Dkaraf.home="%KARAF_HOME%" -Dkaraf.base="%KARAF_BASE%" -Djava.util.logging.config.file=%KARAF_BASE%\etc\java.util.logging.properties org.apache.felix.karaf.gshell.admin.main.Execute %ARGS%
+
+rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+:END
+
+endlocal
+
diff --git a/karaf/gshell/gshell-admin/pom.xml b/karaf/gshell/gshell-admin/pom.xml
index 4c6b459..c0c1300 100644
--- a/karaf/gshell/gshell-admin/pom.xml
+++ b/karaf/gshell/gshell-admin/pom.xml
@@ -56,10 +56,23 @@
</dependency>
<dependency>
+ <groupId>org.ops4j.pax.logging</groupId>
+ <artifactId>pax-logging-api</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
<groupId>org.apache.servicemix.bundles</groupId>
<artifactId>org.apache.servicemix.bundles.junit</artifactId>
<scope>test</scope>
</dependency>
+
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ <version>${easymock.version}</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
diff --git a/karaf/gshell/gshell-admin/src/main/java/org/apache/felix/karaf/gshell/admin/internal/AdminServiceImpl.java b/karaf/gshell/gshell-admin/src/main/java/org/apache/felix/karaf/gshell/admin/internal/AdminServiceImpl.java
index 5f7ea9f..c9caca8 100644
--- a/karaf/gshell/gshell-admin/src/main/java/org/apache/felix/karaf/gshell/admin/internal/AdminServiceImpl.java
+++ b/karaf/gshell/gshell-admin/src/main/java/org/apache/felix/karaf/gshell/admin/internal/AdminServiceImpl.java
@@ -148,10 +148,13 @@
copyFilteredResourceToDir(serviceMixBase, "etc/system.properties", props);
copyFilteredResourceToDir(serviceMixBase, "etc/org.apache.felix.karaf.shell.cfg", props);
if( System.getProperty("os.name").startsWith("Win") ) {
- copyFilteredResourceToDir(serviceMixBase, "bin/karaf.bat", props);
+ copyFilteredResourceToDir(serviceMixBase, "bin/start.bat", props);
+ copyFilteredResourceToDir(serviceMixBase, "bin/stop.bat", props);
} else {
- copyFilteredResourceToDir(serviceMixBase, "bin/karaf", props);
- chmod(new File(serviceMixBase, "bin/karaf"), "a+x");
+ copyFilteredResourceToDir(serviceMixBase, "bin/start", props);
+ copyFilteredResourceToDir(serviceMixBase, "bin/stop", props);
+ chmod(new File(serviceMixBase, "bin/start"), "a+x");
+ chmod(new File(serviceMixBase, "bin/stop"), "a+x");
}
Instance instance = new InstanceImpl(this, name, serviceMixBase.toString());
instances.put(name, instance);
@@ -188,7 +191,7 @@
File outFile = new File(target, resource);
if( !outFile.exists() ) {
println(Ansi.ansi().a("Creating file: ").a(Ansi.Attribute.INTENSITY_BOLD).a(outFile.getPath()).a(Ansi.Attribute.RESET).toString());
- InputStream is = getClass().getClassLoader().getResourceAsStream("/org/apache/felix/karaf/gshell/admin/" + resource);
+ InputStream is = getClass().getClassLoader().getResourceAsStream("org/apache/felix/karaf/gshell/admin/" + resource);
try {
if( text ) {
// Read it line at a time so that we can use the platform line ending when we write it out.
@@ -228,7 +231,7 @@
File outFile = new File(target, resource);
if( !outFile.exists() ) {
println(Ansi.ansi().a("Creating file: ").a(Ansi.Attribute.INTENSITY_BOLD).a(outFile.getPath()).a(Ansi.Attribute.RESET).toString());
- InputStream is = getClass().getClassLoader().getResourceAsStream("/org/apache/felix/karaf/gshell/admin/" + resource);
+ InputStream is = getClass().getClassLoader().getResourceAsStream("org/apache/felix/karaf/gshell/admin/" + resource);
try {
// Read it line at a time so that we can use the platform line ending when we write it out.
PrintStream out = new PrintStream(new FileOutputStream(outFile));
diff --git a/karaf/gshell/gshell-admin/src/main/java/org/apache/felix/karaf/gshell/admin/internal/InstanceImpl.java b/karaf/gshell/gshell-admin/src/main/java/org/apache/felix/karaf/gshell/admin/internal/InstanceImpl.java
index 0d22a08..873141f 100644
--- a/karaf/gshell/gshell-admin/src/main/java/org/apache/felix/karaf/gshell/admin/internal/InstanceImpl.java
+++ b/karaf/gshell/gshell-admin/src/main/java/org/apache/felix/karaf/gshell/admin/internal/InstanceImpl.java
@@ -147,7 +147,7 @@
+ " -Dkaraf.startRemoteShell=true"
+ " -classpath " + classpath.toString()
+ " org.apache.felix.karaf.main.Bootstrap";
- LOG.debug("Starting instance with command: " + command);
+ LOG.debug("Starting instance " + name + " with command: " + command);
this.process = ProcessBuilderFactory.newInstance().newBuilder()
.directory(new File(location))
.command(command)
diff --git a/karaf/gshell/gshell-admin/src/main/java/org/apache/felix/karaf/gshell/admin/main/Execute.java b/karaf/gshell/gshell-admin/src/main/java/org/apache/felix/karaf/gshell/admin/main/Execute.java
new file mode 100644
index 0000000..f970ce2
--- /dev/null
+++ b/karaf/gshell/gshell-admin/src/main/java/org/apache/felix/karaf/gshell/admin/main/Execute.java
@@ -0,0 +1,127 @@
+/*
+ * 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.felix.karaf.gshell.admin.main;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.felix.gogo.commands.Action;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.gogo.commands.basic.DefaultActionPreparator;
+import org.apache.felix.karaf.gshell.admin.internal.AdminServiceImpl;
+import org.apache.felix.karaf.gshell.admin.internal.commands.AdminCommandSupport;
+import org.apache.felix.karaf.gshell.admin.internal.commands.CreateCommand;
+import org.apache.felix.karaf.gshell.admin.internal.commands.DestroyCommand;
+import org.apache.felix.karaf.gshell.admin.internal.commands.ListCommand;
+import org.apache.felix.karaf.gshell.admin.internal.commands.StartCommand;
+import org.apache.felix.karaf.gshell.admin.internal.commands.StopCommand;
+import org.apache.felix.karaf.gshell.admin.internal.commands.ChangePortCommand;
+import org.fusesource.jansi.AnsiConsole;
+
+public class Execute {
+ static Class<? extends Action> x = CreateCommand.class;
+ private static final Class<?> [] COMMAND_CLASSES = new Class[] {
+ CreateCommand.class,
+ StartCommand.class,
+ StopCommand.class,
+ DestroyCommand.class,
+ ListCommand.class,
+ ChangePortCommand.class};
+ private static final Map<String, Class<?>> COMMANDS = new TreeMap<String, Class<?>>();
+ static {
+ for (Class<?> c : COMMAND_CLASSES) {
+ Command ann = c.getAnnotation(Command.class);
+ if (ann == null) {
+ continue;
+ }
+ COMMANDS.put(ann.name(), c);
+ }
+ }
+
+ // For testing
+ static boolean exitAllowed = true;
+
+ public static void main(String[] args) throws Exception {
+ AnsiConsole.systemInstall();
+
+ if (args.length == 0) {
+ listCommands();
+ exit(0);
+ }
+
+ Class<?> cls = COMMANDS.get(args[0]);
+ if (cls == null) {
+ System.err.println("Command not found: " + args[0]);
+ exit(-1);
+ }
+
+ String storage = System.getProperty("storage.file");
+ if (storage == null) {
+ System.err.println("System property 'storage.file' is not set. \n" +
+ "This property needs to be set to the full path of the instance.properties file.");
+ exit(-1);
+ }
+ File storageFile = new File(storage);
+ System.setProperty("user.dir", storageFile.getParentFile().getParentFile().getCanonicalPath());
+
+ Object command = cls.newInstance();
+ if (command instanceof AdminCommandSupport) {
+ execute((AdminCommandSupport) command, storageFile, args);
+ } else {
+ System.err.println("Not an admin command: " + args[0]);
+ exit(-1);
+ }
+ }
+
+ static void execute(AdminCommandSupport command, File storageFile, String[] args) throws Exception {
+ DefaultActionPreparator dap = new DefaultActionPreparator();
+ List<Object> params = new ArrayList<Object>(Arrays.asList(args));
+ params.remove(0); // this is the actual command name
+
+ if (!dap.prepare(command, null, params)) {
+ return;
+ }
+
+ AdminServiceImpl admin = new AdminServiceImpl();
+ admin.setStorageLocation(storageFile);
+ admin.init();
+ command.setAdminService(admin);
+ command.execute(null);
+ }
+
+ private static void listCommands() {
+ System.out.println("Available commands:");
+ for (Map.Entry<String, Class<?>> entry : COMMANDS.entrySet()) {
+ Command ann = entry.getValue().getAnnotation(Command.class);
+ System.out.printf(" %s - %s\n", entry.getKey(), ann.description());
+ }
+
+ System.out.println("Type 'command --help' for more help on the specified command.");
+ }
+
+ private static void exit(int rc) {
+ if (exitAllowed) {
+ System.exit(rc);
+ } else {
+ throw new RuntimeException("" + rc);
+ }
+ }
+}
diff --git a/karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/karaf b/karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/start
similarity index 92%
rename from karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/karaf
rename to karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/start
index 180092b..383845f 100644
--- a/karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/karaf
+++ b/karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/start
@@ -19,7 +19,6 @@
################################################################################
KARAF_HOME=${karaf.home}
-KARAF_BASE=${karaf.base}
-export KARAF_BASE
-${KARAF_HOME}/bin/karaf "$*"
+${KARAF_HOME}/bin/admin start ${karaf.name} "$@"
+
diff --git a/karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/karaf.bat b/karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/start.bat
similarity index 93%
copy from karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/karaf.bat
copy to karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/start.bat
index 1358ba7..2da0758 100644
--- a/karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/karaf.bat
+++ b/karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/start.bat
@@ -18,8 +18,6 @@
REM
REM =========================================================================
-SET KARAF_BASE=${karaf.base}
-SETLOCAL
SET KARAF_HOME=${karaf.home}
-%KARAF_HOME%\bin\karaf.bat %*
+%KARAF_HOME%\bin\admin.bat start ${karaf.name}
diff --git a/karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/karaf b/karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/stop
similarity index 92%
copy from karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/karaf
copy to karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/stop
index 180092b..1fbfc35 100644
--- a/karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/karaf
+++ b/karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/stop
@@ -19,7 +19,6 @@
################################################################################
KARAF_HOME=${karaf.home}
-KARAF_BASE=${karaf.base}
-export KARAF_BASE
-${KARAF_HOME}/bin/karaf "$*"
+${KARAF_HOME}/bin/admin stop ${karaf.name} "$@"
+
diff --git a/karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/karaf.bat b/karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/stop.bat
similarity index 93%
rename from karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/karaf.bat
rename to karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/stop.bat
index 1358ba7..fd6279e 100644
--- a/karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/karaf.bat
+++ b/karaf/gshell/gshell-admin/src/main/resources/org/apache/felix/karaf/gshell/admin/bin/stop.bat
@@ -18,8 +18,6 @@
REM
REM =========================================================================
-SET KARAF_BASE=${karaf.base}
-SETLOCAL
SET KARAF_HOME=${karaf.home}
-%KARAF_HOME%\bin\karaf.bat %*
+%KARAF_HOME%\bin\admin.bat stop ${karaf.name}
diff --git a/karaf/gshell/gshell-admin/src/test/java/org/apache/felix/karaf/gshell/admin/main/ExecuteTest.java b/karaf/gshell/gshell-admin/src/test/java/org/apache/felix/karaf/gshell/admin/main/ExecuteTest.java
new file mode 100644
index 0000000..5b96fba
--- /dev/null
+++ b/karaf/gshell/gshell-admin/src/test/java/org/apache/felix/karaf/gshell/admin/main/ExecuteTest.java
@@ -0,0 +1,160 @@
+/*
+ * 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.felix.karaf.gshell.admin.main;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+import org.apache.felix.karaf.gshell.admin.AdminService;
+import org.apache.felix.karaf.gshell.admin.internal.AdminServiceImpl;
+import org.apache.felix.karaf.gshell.admin.internal.commands.AdminCommandSupport;
+import org.easymock.IAnswer;
+import org.easymock.classextension.EasyMock;
+
+public class ExecuteTest extends TestCase {
+ private String userDir;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ Execute.exitAllowed = false;
+ userDir = System.getProperty("user.dir");
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ Execute.exitAllowed = true;
+ System.setProperty("user.dir", userDir);
+ }
+
+ public void testListCommands() throws Exception {
+ PrintStream oldOut = System.out;
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintStream capturedOut = new PrintStream(baos);
+ System.setOut(capturedOut);
+
+ try {
+ Execute.main(new String [] {});
+ } catch (RuntimeException re) {
+ assertEquals("0", re.getMessage());
+
+ String s = new String(baos.toByteArray());
+ assertTrue(s.contains("list"));
+ assertTrue(s.contains("create"));
+ assertTrue(s.contains("destroy"));
+ } finally {
+ System.setOut(oldOut);
+ }
+ }
+
+ public void testNonexistingCommand() throws Exception {
+ try {
+ Execute.main(new String [] {"bheuaark"});
+ } catch (RuntimeException re) {
+ assertEquals("-1", re.getMessage());
+ }
+ }
+
+ public void testNoStorageFile() throws Exception {
+ PrintStream oldErr = System.err;
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintStream capturedErr = new PrintStream(baos);
+ System.setErr(capturedErr);
+
+ try {
+ Execute.main(new String [] {"create"});
+ } catch (RuntimeException re) {
+ assertEquals("-1", re.getMessage());
+
+ String s = new String(baos.toByteArray());
+ assertTrue(s.contains("storage.file"));
+ assertTrue(s.contains("instance.properties"));
+ } finally {
+ System.setErr(oldErr);
+ }
+ }
+
+ public void testSetDir() throws Exception {
+ Properties oldProps = (Properties) System.getProperties().clone();
+ File tempFile = File.createTempFile(getName(), ".tmp");
+ assertFalse("Precondition failed",
+ tempFile.getParentFile().getParentFile().getCanonicalPath().equals(System.getProperty("user.dir")));
+
+ System.setProperty("storage.file", tempFile.getCanonicalPath());
+ try {
+ Execute.main(new String [] {"list"});
+ assertTrue(tempFile.getParentFile().getParentFile().getCanonicalPath().equals(System.getProperty("user.dir")));
+ } finally {
+ System.setProperties(oldProps);
+ assertNull("Postcondition failed", System.getProperty("storage.file"));
+ tempFile.delete();
+ }
+ }
+
+ public void testExecute() throws Exception {
+ final File tempFile = File.createTempFile(getName(), ".properties");
+ Properties p = new Properties();
+ p.setProperty("port", "1302");
+ FileOutputStream fos = new FileOutputStream(tempFile);
+ p.store(fos, "");
+ fos.close();
+
+ final List<AdminServiceImpl> admins = new ArrayList<AdminServiceImpl>();
+ try {
+ AdminCommandSupport mockCommand = EasyMock.createStrictMock(AdminCommandSupport.class);
+ mockCommand.setAdminService((AdminService) EasyMock.anyObject());
+ EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
+ public Object answer() throws Throwable {
+ AdminServiceImpl svc = (AdminServiceImpl) EasyMock.getCurrentArguments()[0];
+ assertEquals(tempFile, svc.getStorageLocation());
+ admins.add(svc);
+ return null;
+ }
+ });
+
+ EasyMock.expect(mockCommand.execute(null)).andAnswer(new IAnswer<Object>() {
+ public Object answer() throws Throwable {
+ // The Admin Service should be initialized at this point.
+ // One way to find this out is by reading out the port number
+ AdminServiceImpl admin = admins.get(0);
+ Field field = AdminServiceImpl.class.getDeclaredField("defaultPortStart");
+ field.setAccessible(true);
+ assertEquals(1302, field.get(admin));
+ return null;
+ }
+ });
+ EasyMock.replay(mockCommand);
+
+ Execute.execute(mockCommand, tempFile, new String [] {"test"});
+
+ EasyMock.verify(mockCommand);
+ } finally {
+ tempFile.delete();
+ }
+ }
+}