You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by lu...@apache.org on 2015/07/10 19:20:29 UTC
svn commit: r1690291 - in /directory/apacheds/trunk:
installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/archive/apacheds.sh
service/src/main/java/org/apache/directory/server/UberjarMain.java
Author: lucastheisen
Date: Fri Jul 10 17:20:29 2015
New Revision: 1690291
URL: http://svn.apache.org/r1690291
Log:
DIRSERVER-2080: Add a way to politely stop apacheds from apacheds.sh
Modified:
directory/apacheds/trunk/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/archive/apacheds.sh
directory/apacheds/trunk/service/src/main/java/org/apache/directory/server/UberjarMain.java
Modified: directory/apacheds/trunk/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/archive/apacheds.sh
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/archive/apacheds.sh?rev=1690291&r1=1690290&r2=1690291&view=diff
==============================================================================
--- directory/apacheds/trunk/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/archive/apacheds.sh (original)
+++ directory/apacheds/trunk/installers-maven-plugin/src/main/resources/org/apache/directory/server/installers/archive/apacheds.sh Fri Jul 10 17:20:29 2015
@@ -23,8 +23,8 @@
#
# Environment Variable Prerequisites
#
-# Do not set the variables in this script. Instead put them into a script
-# setenv.sh in CATALINA_BASE/bin to keep your customizations separate.
+# Do not set the variables in this script. Instead put them into
+# $ADS_HOME/bin/setenv.sh to keep your customizations separate.
#
# ADS_HOME (Optional) The directory that contains your apacheds
# install. Defaults to the parent directory of the
@@ -37,12 +37,19 @@
#
# ADS_EXTENDED_OPERATIONS
# Extended operations to register.
+# ADS_SHUTDOWN_PORT
+# (Optional) If specified, it must be a valid port number
+# on which ApacheDS will listen for a connection to trigger
+# a polite shutdown. Defaults to 10390.
#
# JAVA_HOME (Optional) The java installation directory. If not
# not specified, the java from $PATH will be used.
#
# JAVA_OPTS (Optional) Any additional java options (ex: -Xms:256m)
+# Defaults
+ADS_SHUTDOWN_PORT=10390
+
# Detect ads home (http://stackoverflow.com/a/630387/516433)
PROGRAM_DIR="`dirname \"$0\"`"
[ -z "$ADS_HOME" ] && ADS_HOME="`(cd \"$PROGRAM_DIR/..\" && pwd)`"
@@ -143,6 +150,7 @@ if [ "$ADS_ACTION" = "start" ]; then
# Launching ApacheDS
eval "\"$RUN_JAVA\"" $JAVA_OPTS $ADS_CONTROLS $ADS_EXTENDED_OPERATIONS \
-Dlog4j.configuration="\"file:$ADS_INSTANCE/conf/log4j.properties\"" \
+ -Dapacheds.shutdown.port="\"$ADS_SHUTDOWN_PORT\"" \
-Dapacheds.log.dir="\"$ADS_INSTANCE/log\"" \
-classpath "\"$CLASSPATH\"" \
org.apache.directory.server.UberjarMain "\"$ADS_INSTANCE\"" \
@@ -156,6 +164,7 @@ elif [ "$ADS_ACTION" = "run" ]; then
eval "\"$RUN_JAVA\"" $JAVA_OPTS $ADS_CONTROLS $ADS_EXTENDED_OPERATIONS \
-Dlog4j.configuration="\"file:$ADS_INSTANCE/conf/log4j.properties\"" \
-Dapacheds.log.dir="\"$ADS_INSTANCE/log\"" \
+ -Dapacheds.shutdown.port="\"$ADS_SHUTDOWN_PORT\"" \
-classpath "\"$CLASSPATH\"" \
org.apache.directory.server.UberjarMain "\"$ADS_INSTANCE\""
elif [ "$ADS_ACTION" = "status" ]; then
@@ -176,7 +185,17 @@ elif [ "$ADS_ACTION" = "stop" ]; then
[ $HAVE_TTY -eq 1 ] && echo "Stopping ApacheDS instance '$ADS_INSTANCE_NAME' running as $PID"
# Terminate the process
- kill -15 $PID > /dev/null 2>&1
+ if [ $ADS_SHUTDOWN_PORT -gt 0 ]; then
+ eval "\"$RUN_JAVA\"" $JAVA_OPTS $ADS_CONTROLS $ADS_EXTENDED_OPERATIONS \
+ -Dlog4j.configuration="\"file:$ADS_INSTANCE/conf/log4j.properties\"" \
+ -Dapacheds.log.dir="\"$ADS_INSTANCE/log\"" \
+ -Dapacheds.shutdown.port="\"$ADS_SHUTDOWN_PORT\"" \
+ -classpath "\"$CLASSPATH\"" \
+ org.apache.directory.server.UberjarMain "\"$ADS_INSTANCE\"" stop
+ else
+ # No port specified so try term signal instead
+ kill -15 $PID > /dev/null 2>&1
+ fi
ATTEMPTS_REMAINING=10
while [ $ATTEMPTS_REMAINING -gt 0 ]; do
Modified: directory/apacheds/trunk/service/src/main/java/org/apache/directory/server/UberjarMain.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/service/src/main/java/org/apache/directory/server/UberjarMain.java?rev=1690291&r1=1690290&r2=1690291&view=diff
==============================================================================
--- directory/apacheds/trunk/service/src/main/java/org/apache/directory/server/UberjarMain.java (original)
+++ directory/apacheds/trunk/service/src/main/java/org/apache/directory/server/UberjarMain.java Fri Jul 10 17:20:29 2015
@@ -1,25 +1,36 @@
/*
- * 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.
- *
+ * 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.directory.server;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+
import org.apache.directory.server.core.api.InstanceLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -28,41 +39,138 @@ import org.slf4j.LoggerFactory;
/**
* The command line main for the server.
*
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory
+ * Project</a>
*/
public class UberjarMain
{
/** A logger for this class */
private static final Logger LOG = LoggerFactory.getLogger( UberjarMain.class );
+ /** The key of the property use to specify the shutdown port */
+ private static final String PROPERTY_SHUTDOWN_PORT = "apacheds.shutdown.port";
/** The ApacheDS service */
private ApacheDsService service;
-
/**
- * Takes a single argument, the path to the installation home, which contains
- * the configuration to load with server startup settings.
+ * Takes a single argument, the path to the installation home, which
+ * contains the configuration to load with server startup settings.
*
- * @param args the arguments
+ * @param args
+ * the arguments
*/
public static void main( String[] args ) throws Exception
{
- if ( ( args != null ) && ( args.length == 1 ) )
+ if ( (args == null) || (args.length < 1) )
{
- UberjarMain uberjarMain = new UberjarMain();
+ throw new IllegalArgumentException(
+ "Instance directory argument is missing" );
+ }
- uberjarMain.start( args );
+ final String instanceDirectory = args[0];
+ Action action = (args.length == 2) ? Action.fromString( args[1] ) : Action.START;
+
+ final UberjarMain instance = new UberjarMain();
+ final int shutdownPort = getShutdownPort();
+ switch ( action )
+ {
+ case START:
+ LOG.debug( "Staring runtime" );
+ final String shutdownPassword = writeShutdownPassword( instanceDirectory,
+ UUID.randomUUID().toString() );
+ try {
+ new Thread( new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ try (ServerSocket shutdownSocket = new ServerSocket( shutdownPort ))
+ {
+ writeShutdownPort( instanceDirectory, shutdownSocket.getLocalPort() );
+
+ Socket socket;
+ LOG.info( "Start the shutdown listener on port [{}]", shutdownPort );
+ while ( (socket = shutdownSocket.accept()) != null )
+ {
+ if ( shutdownPassword == null || shutdownPassword.isEmpty() ) {
+ instance.stop();
+ break;
+ }
+ else
+ {
+ try (InputStreamReader reader = new InputStreamReader( socket.getInputStream() ))
+ {
+ CharBuffer buffer = CharBuffer.allocate( 2048 );
+ while ( reader.read( buffer ) >= 0 );
+ buffer.flip();
+ String password = buffer.toString();
+ if ( shutdownPassword.equals( password ) )
+ {
+ instance.stop();
+ break;
+ }
+ else
+ {
+ LOG.warn( "Illegal attempt to shutdown, incorrect password [{}]", password );
+ }
+ }
+ }
+ }
+ }
+ catch ( IOException e )
+ {
+ e.printStackTrace();
+ LOG.error( "Failed to start the shutdown listener.", e );
+ }
+
+ }
+ } ).start();
+ }
+ catch ( Exception e ) {
+ e.printStackTrace();
+ LOG.error( "Failed to start the service.", e );
+ System.exit( 1 );
+ }
+ instance.start( instanceDirectory );
+ break;
+ case STOP:
+ LOG.debug( "Stopping runtime" );
+ try (Socket socket = new Socket( "localhost", readShutdownPort( instanceDirectory ) );
+ PrintWriter writer = new PrintWriter( socket.getOutputStream() ))
+ {
+ writer.print( readShutdownPassword( instanceDirectory ) );
+ }
+ break;
}
- else
+ }
+
+ private static int getShutdownPort()
+ {
+ int shutdownPort = Integer.parseInt( System.getProperty( PROPERTY_SHUTDOWN_PORT, "0" ) );
+ if ( shutdownPort < 1024 || shutdownPort > 65536 )
{
- // TODO default to the current directory.
- throw new IllegalArgumentException(
- "Program must be launched with 1 arguement, the path to the instance directory." );
+ throw new IllegalArgumentException( "Shutdown port [" + shutdownPort + "] is an illegal port number" );
}
+ return shutdownPort;
+ }
+
+ private static int readShutdownPort( String instanceDirectory ) throws IOException
+ {
+ return Integer.parseInt( new String( Files.readAllBytes(
+ Paths.get( new InstanceLayout( instanceDirectory ).getRunDirectory().getAbsolutePath(),
+ ".shutdown.port" ) ),
+ Charset.forName( "utf-8" ) ) );
}
+ private static String readShutdownPassword( String instanceDirectory ) throws IOException
+ {
+ return new String( Files.readAllBytes(
+ Paths.get( new InstanceLayout( instanceDirectory ).getRunDirectory().getAbsolutePath(),
+ ".shutdown.pwd" ) ),
+ Charset.forName( "utf-8" ) );
+ }
- public void start( String[] args )
+ public void start( String... args )
{
// Creating ApacheDS service
service = new ApacheDsService();
@@ -73,6 +181,7 @@ public class UberjarMain
// Initializing the service
try
{
+ LOG.info( "Starting the service." );
service.start( instanceLayout );
}
catch ( Exception e )
@@ -83,13 +192,13 @@ public class UberjarMain
}
}
-
public void stop()
{
if ( service != null )
{
try
{
+ LOG.info( "Stopping the service." );
service.stop();
}
catch ( Exception e )
@@ -100,4 +209,43 @@ public class UberjarMain
}
}
}
+
+ private static String writeShutdownPassword( String instanceDirectory, String password ) throws IOException
+ {
+ Files.write(
+ Paths.get( new InstanceLayout( instanceDirectory ).getRunDirectory().getAbsolutePath(),
+ ".shutdown.pwd" ),
+ password.getBytes( Charset.forName( "utf-8" ) ) );
+ return password;
+ }
+
+ private static int writeShutdownPort( String instanceDirectory, int portNumber ) throws IOException
+ {
+ Files.write(
+ Paths.get( new InstanceLayout( instanceDirectory ).getRunDirectory().getAbsolutePath(),
+ ".shutdown.port" ),
+ Integer.toString( portNumber ).getBytes( Charset.forName( "utf-8" ) ) );
+ return portNumber;
+ }
+
+ private static enum Action
+ {
+ START, STOP;
+
+ private static Map<String, Action> lookup;
+
+ static
+ {
+ lookup = new HashMap<String, Action>();
+ for ( Action action : values() )
+ {
+ lookup.put( action.name(), action );
+ }
+ }
+
+ public static Action fromString( String actionString )
+ {
+ return lookup.get( actionString.toUpperCase() );
+ }
+ }
}