You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by gn...@apache.org on 2010/01/18 15:34:27 UTC

svn commit: r900408 - in /felix/trunk/karaf: assembly/src/main/distribution/unix-shell/bin/ assembly/src/main/distribution/windows-text/bin/ assembly/src/main/filtered-resources/etc/ main/src/main/java/org/apache/felix/karaf/main/

Author: gnodet
Date: Mon Jan 18 14:34:26 2010
New Revision: 900408

URL: http://svn.apache.org/viewvc?rev=900408&view=rev
Log:
FELIX-1970: the stop script should always work even if the default user / password / host has been changed

Added:
    felix/trunk/karaf/main/src/main/java/org/apache/felix/karaf/main/Stop.java
Modified:
    felix/trunk/karaf/assembly/src/main/distribution/unix-shell/bin/karaf
    felix/trunk/karaf/assembly/src/main/distribution/unix-shell/bin/stop
    felix/trunk/karaf/assembly/src/main/distribution/windows-text/bin/karaf.bat
    felix/trunk/karaf/assembly/src/main/distribution/windows-text/bin/stop.bat
    felix/trunk/karaf/assembly/src/main/filtered-resources/etc/config.properties
    felix/trunk/karaf/main/src/main/java/org/apache/felix/karaf/main/Main.java

Modified: felix/trunk/karaf/assembly/src/main/distribution/unix-shell/bin/karaf
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/assembly/src/main/distribution/unix-shell/bin/karaf?rev=900408&r1=900407&r2=900408&view=diff
==============================================================================
--- felix/trunk/karaf/assembly/src/main/distribution/unix-shell/bin/karaf (original)
+++ felix/trunk/karaf/assembly/src/main/distribution/unix-shell/bin/karaf Mon Jan 18 14:34:26 2010
@@ -266,7 +266,12 @@
 
 run() {
     OPTS="-Dkaraf.startLocalConsole=true -Dkaraf.startRemoteShell=true"
+    MAIN=org.apache.felix.karaf.main.Bootstrap
     case "$1" in
+        'stop')
+            MAIN=org.apache.felix.karaf.main.Stop
+            shift
+            ;;
         'console')
             shift
             ;;
@@ -286,7 +291,7 @@
         CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
     fi
     cd $KARAF_BASE
-    exec $JAVA $JAVA_OPTS -Dstorage.location="${KARAF_HOME}/instances" -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 -Dstorage.location="${KARAF_HOME}/instances" -Dkaraf.home="$KARAF_HOME" -Dkaraf.base="$KARAF_BASE" -Djava.util.logging.config.file=$KARAF_BASE/etc/java.util.logging.properties $OPTS -classpath "$CLASSPATH" $MAIN "$@"
 }
 
 main() {

Modified: felix/trunk/karaf/assembly/src/main/distribution/unix-shell/bin/stop
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/assembly/src/main/distribution/unix-shell/bin/stop?rev=900408&r1=900407&r2=900408&view=diff
==============================================================================
--- felix/trunk/karaf/assembly/src/main/distribution/unix-shell/bin/stop (original)
+++ felix/trunk/karaf/assembly/src/main/distribution/unix-shell/bin/stop Mon Jan 18 14:34:26 2010
@@ -21,20 +21,6 @@
 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}: $*"
 }
@@ -44,13 +30,6 @@
     exit 1
 }
 
-maybeSource() {
-    file="$1"
-    if [ -f "$file" ] ; then
-        . $file
-    fi
-}
-
 detectOS() {
     # OS specific support (must be 'true' or 'false').
     cygwin=false;
@@ -79,34 +58,6 @@
     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"
@@ -131,137 +82,15 @@
     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="-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() {
@@ -270,7 +99,11 @@
         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 -jar "$KARAF_HOME/lib/karaf-client.jar" osgi:shutdown "$@"
+    # Ensure the log directory exists -- we need to have a place to redirect stdout/stderr
+    if [ ! -d "$KARAF_HOME/data/log" ]; then
+        mkdir -p "$KARAF_HOME/data/log"
+    fi
+    exec "$KARAF_HOME"/bin/karaf stop "$@"
 }
 
 main() {
@@ -279,3 +112,4 @@
 }
 
 main "$@"
+

Modified: felix/trunk/karaf/assembly/src/main/distribution/windows-text/bin/karaf.bat
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/assembly/src/main/distribution/windows-text/bin/karaf.bat?rev=900408&r1=900407&r2=900408&view=diff
==============================================================================
--- felix/trunk/karaf/assembly/src/main/distribution/windows-text/bin/karaf.bat (original)
+++ felix/trunk/karaf/assembly/src/main/distribution/windows-text/bin/karaf.bat Mon Jan 18 14:34:26 2010
@@ -128,12 +128,19 @@
 
 :RUN
     SET OPTS=-Dkaraf.startLocalConsole=true -Dkaraf.startRemoteShell=true
+    SET MAIN=org.apache.felix.karaf.main.Bootstrap
     SET SHIFT=false
+    if "%1" == "stop" goto :EXECUTE_STOP
     if "%1" == "console" goto :EXECUTE_CONSOLE
     if "%1" == "server" goto :EXECUTE_SERVER
     if "%1" == "client" goto :EXECUTE_CLIENT
     goto :EXECUTE
 
+:EXECUTE_STOP
+    SET MAIN=org.apache.felix.karaf.main.Stop
+    SET SHIFT=true
+    goto :EXECUTE
+
 :EXECUTE_CONSOLE
     SET SHIFT=true
     goto :EXECUTE    

Modified: felix/trunk/karaf/assembly/src/main/distribution/windows-text/bin/stop.bat
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/assembly/src/main/distribution/windows-text/bin/stop.bat?rev=900408&r1=900407&r2=900408&view=diff
==============================================================================
--- felix/trunk/karaf/assembly/src/main/distribution/windows-text/bin/stop.bat (original)
+++ felix/trunk/karaf/assembly/src/main/distribution/windows-text/bin/stop.bat Mon Jan 18 14:34:26 2010
@@ -16,9 +16,9 @@
 rem    See the License for the specific language governing permissions and
 rem    limitations under the License.
 rem
-rem 
+rem
 rem $Id: karaf.bat 979 2005-11-30 22:50:55Z bsnyder $
-rem 
+rem
 
 if not "%ECHO%" == "" echo %ECHO%
 
@@ -58,77 +58,8 @@
   set KARAF_BASE=%KARAF_HOME%
 )
 
-set LOCAL_CLASSPATH=%CLASSPATH%
-set DEFAULT_JAVA_OPTS=-server -Xmx512M -Dderby.system.home="%KARAF_BASE%\data\derby" -Dderby.storage.fileSyncTransactionLog=true -Dcom.sun.management.jmxremote
-set CLASSPATH=%LOCAL_CLASSPATH%;%KARAF_BASE%\conf
-set DEFAULT_JAVA_DEBUG_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
-
-if "%LOCAL_CLASSPATH%" == "" goto :KARAF_CLASSPATH_EMPTY
-    set CLASSPATH=%LOCAL_CLASSPATH%;%KARAF_BASE%\conf
-    goto :KARAF_CLASSPATH_END
-:KARAF_CLASSPATH_EMPTY
-    set CLASSPATH=%KARAF_BASE%\conf
-:KARAF_CLASSPATH_END
-
-rem Setup Karaf Home
-if exist "%KARAF_HOME%\conf\karaf-rc.cmd" call %KARAF_HOME%\conf\karaf-rc.cmd
-if exist "%HOME%\karaf-rc.cmd" call %HOME%\karaf-rc.cmd
-
-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
-
-if "%KARAF_PROFILER%" == "" goto :KARAF_PROFILER_END
-    set KARAF_PROFILER_SCRIPT=%KARAF_HOME%\conf\profiler\%KARAF_PROFILER%.cmd
-    
-    if exist "%KARAF_PROFILER_SCRIPT%" goto :KARAF_PROFILER_END
-    call :warn Missing configuration for profiler '%KARAF_PROFILER%': %KARAF_PROFILER_SCRIPT%
-    goto END
-:KARAF_PROFILER_END
-
-rem Setup the classpath
-pushd "%KARAF_HOME%\lib"
-for %%G in (*.*) do call:APPEND_TO_CLASSPATH %%G
-popd
-goto CLASSPATH_END
-
-: APPEND_TO_CLASSPATH
-set filename=%~1
-set suffix=%filename:~-4%
-if %suffix% equ .jar set CLASSPATH=%CLASSPATH%;%KARAF_HOME%\lib\%filename%
-goto :EOF
-
-:CLASSPATH_END
-
-rem Execute the JVM or the load the profiler
-if "%KARAF_PROFILER%" == "" goto :RUN
-    rem Execute the profiler if it has been configured
-    call :warn Loading profiler script: %KARAF_PROFILER_SCRIPT%
-    call %KARAF_PROFILER_SCRIPT%
-
-:RUN
-    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" -jar "%KARAF_HOME%\lib\karaf-client.jar" "osgi:shutdown" %ARGS%
+:EXECUTE
+    "%KARAF_HOME%\bin\karaf.bat" stop
 
 rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 
@@ -138,5 +69,4 @@
 
 if not "%PAUSE%" == "" pause
 
-:END_NO_PAUSE
-
+:END_NO_PAUSE
\ No newline at end of file

Modified: felix/trunk/karaf/assembly/src/main/filtered-resources/etc/config.properties
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/assembly/src/main/filtered-resources/etc/config.properties?rev=900408&r1=900407&r2=900408&view=diff
==============================================================================
--- felix/trunk/karaf/assembly/src/main/filtered-resources/etc/config.properties (original)
+++ felix/trunk/karaf/assembly/src/main/filtered-resources/etc/config.properties Mon Jan 18 14:34:26 2010
@@ -51,6 +51,8 @@
 org.osgi.framework.startlevel.beginning=100
 karaf.startlevel.bundle=60
 
+karaf.shutdown.port.file=${karaf.base}/data/port
+
 #
 # FileMonitor properties
 #

Modified: felix/trunk/karaf/main/src/main/java/org/apache/felix/karaf/main/Main.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/main/src/main/java/org/apache/felix/karaf/main/Main.java?rev=900408&r1=900407&r2=900408&view=diff
==============================================================================
--- felix/trunk/karaf/main/src/main/java/org/apache/felix/karaf/main/Main.java (original)
+++ felix/trunk/karaf/main/src/main/java/org/apache/felix/karaf/main/Main.java Mon Jan 18 14:34:26 2010
@@ -18,18 +18,16 @@
  */
 package org.apache.felix.karaf.main;
 
-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.BufferedReader;
+import java.io.*;
 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.net.URLClassLoader;
+import java.security.AccessControlException;
 import java.security.Provider;
 import java.security.Security;
 import java.util.ArrayList;
@@ -38,11 +36,13 @@
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Properties;
+import java.util.Random;
 import java.util.StringTokenizer;
+import java.util.logging.Level;
 import java.util.logging.Logger;
-import java.util.concurrent.CountDownLatch;
 import java.lang.reflect.Method;
-import java.lang.reflect.Constructor;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.apache.felix.karaf.main.Utils;
 import org.osgi.framework.Bundle;
@@ -134,6 +134,18 @@
     
     public static final String KARAF_FRAMEWORK = "karaf.framework";
 
+    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();
 
     Logger LOG = Logger.getLogger(this.getClass().getName());
@@ -166,7 +178,7 @@
         System.setProperty(PROP_KARAF_BASE, karafBase.getPath());
 
         // Load system properties.
-        loadSystemProperties();
+        loadSystemProperties(karafBase);
 
         updateInstancePid();
 
@@ -654,7 +666,7 @@
      * arbitrary URL.
      * </p>
      */
-    private void loadSystemProperties() {
+    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.
@@ -794,7 +806,7 @@
         return configProps;
     }
 
-    private static Properties loadPropertiesFile(URL configPropURL) throws Exception {
+    protected static Properties loadPropertiesFile(URL configPropURL) throws Exception {
         // Read the properties file.
         Properties configProps = new Properties();
         InputStream is = null;
@@ -823,7 +835,7 @@
         return configProps;
     }
 
-    private static void copySystemProperties(Properties configProps) {
+    protected static void copySystemProperties(Properties configProps) {
         for (Enumeration e = System.getProperties().propertyNames();
              e.hasMoreElements();) {
             String key = (String) e.nextElement();
@@ -1111,6 +1123,7 @@
                         if (lockLogged) {
                             LOG.info("Lock acquired.");
                         }
+                        setupShutdown(props);
                         setStartLevel(defaultStartLevel);
                         for (;;) {
                             if (!lock.isAlive()) {
@@ -1150,4 +1163,120 @@
         sl.setStartLevel(level);
     }
 
+
+    private Random random = null;
+    private ServerSocket shutdownSocket;
+
+    protected void setupShutdown(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();
+        }
+        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 Thread() {
+                    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 = -1;
+                                    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) {
+                                    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) {
+                            }
+                        }
+                    }
+                };
+                thread.setDaemon(true);
+                thread.start();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
 }

Added: felix/trunk/karaf/main/src/main/java/org/apache/felix/karaf/main/Stop.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/main/src/main/java/org/apache/felix/karaf/main/Stop.java?rev=900408&view=auto
==============================================================================
--- felix/trunk/karaf/main/src/main/java/org/apache/felix/karaf/main/Stop.java (added)
+++ felix/trunk/karaf/main/src/main/java/org/apache/felix/karaf/main/Stop.java Mon Jan 18 14:34:26 2010
@@ -0,0 +1,76 @@
+/*
+ * 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.main;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.net.Socket;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Properties;
+
+/**
+ * Main class used to stop the root Karaf instance
+ */
+public class Stop {
+
+    public static void main(String[] args) throws Exception {
+        File karafHome = Utils.getKarafHome();
+        File karafBase = Utils.getKarafBase(karafHome);
+
+        System.setProperty(Main.PROP_KARAF_HOME, karafHome.getPath());
+        System.setProperty(Main.PROP_KARAF_BASE, karafBase.getPath());
+
+        // Load system properties.
+        Main.loadSystemProperties(karafBase);
+
+        File file = new File(new File(karafBase, "etc"), Main.CONFIG_PROPERTIES_FILE_NAME);
+        URL configPropURL = file.toURI().toURL();
+        Properties props = Main.loadPropertiesFile(configPropURL);
+        Main.copySystemProperties(props);
+
+        // Perform variable substitution for system properties.
+        for (Enumeration e = props.propertyNames(); e.hasMoreElements();) {
+            String name = (String) e.nextElement();
+            props.setProperty(name,
+                    Main.substVars(props.getProperty(name), name, null, props));
+        }
+
+        int port = Integer.parseInt(props.getProperty(Main.KARAF_SHUTDOWN_PORT, "0"));
+        String host = props.getProperty(Main.KARAF_SHUTDOWN_HOST, "localhost");
+        String portFile = props.getProperty(Main.KARAF_SHUTDOWN_PORT_FILE);
+        String shutdown = props.getProperty(Main.KARAF_SHUTDOWN_COMMAND, Main.DEFAULT_SHUTDOWN_COMMAND);
+        if (port == 0 && portFile != null) {
+            BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(portFile)));
+            String portStr = r.readLine();
+            port = Integer.parseInt(portStr);
+            r.close();
+        }
+        if (port > 0) {
+            Socket s = new Socket(host, port);
+            s.getOutputStream().write(shutdown.getBytes());
+            s.close();
+        } else {
+            System.err.println("Unable to find port...");
+        }
+
+    }
+}