costin 00/12/29 11:59:20 Modified: src/share/org/apache/tomcat/startup StopTomcat.java src/share/org/apache/tomcat/modules/server Ajp12.java Ajp12Interceptor.java PoolTcpConnector.java Log: Small change in the stop protocol: added a "secret" ( used only for stopping, all other Ajp12 requests are equivalent with HTTP requests, and need no secret ). The secret is optional ( for backward compatibility - "useSecret" attribute will enable its use ). There are 2 choices for secret - the user can set it ( secret="xxxx" ), or ( much better ) let the server generate it ( using the simple Math.random() - IMHO still better than "changeit" ). The server will save the random secret in a "stop.id" file, in conf ( XXX should it be work/private ? ). Since read access to that directory would allow reading of server.xml too - the method is equivalent. The main advantage is that the user doesn't have to configure anything. Another small usability improvement - now it's possible to do "java -jar stop-tomcat.jar " ( or double-click the jar - no scripts needed on JDK1.2 machines, the scripts only needed for 1.1 ) Revision Changes Path 1.2 +117 -69 jakarta-tomcat/src/share/org/apache/tomcat/startup/StopTomcat.java Index: StopTomcat.java =================================================================== RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/startup/StopTomcat.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- StopTomcat.java 2000/12/29 00:20:22 1.1 +++ StopTomcat.java 2000/12/29 19:59:19 1.2 @@ -58,20 +58,14 @@ */ package org.apache.tomcat.startup; -import org.apache.tomcat.core.*; -import org.apache.tomcat.util.*; -import org.apache.tomcat.helper.*; -import org.apache.tomcat.util.xml.*; -import org.apache.tomcat.util.log.*; +import org.apache.tomcat.util.StringManager; import java.io.*; import java.net.*; import java.util.*; -// Used to stop tomcat -//import org.apache.tomcat.service.PoolTcpConnector; -//import org.apache.tomcat.service.connector.Ajp12ConnectionHandler; -import org.apache.tomcat.modules.server.Ajp12Interceptor; +// Depends: StringManager, resources + /** * This task will stop tomcat * @@ -84,7 +78,6 @@ String configFile; String tomcatHome; - Log loghelper = new Log("tc_log", "StopTomcat"); public StopTomcat() { @@ -113,15 +106,15 @@ } // -------------------- Ant execute -------------------- + public void execute() throws Exception { System.out.println(sm.getString("tomcat.stop")); try { stopTomcat(); // stop serving } - catch (TomcatException te) { - if (te.getRootCause() instanceof java.net.ConnectException) - System.out.println(sm.getString("tomcat.connectexception")); - else + catch (java.net.ConnectException ex) { + System.out.println(sm.getString("tomcat.connectexception")); + } catch (Exception te ) { throw te; } return; @@ -129,75 +122,130 @@ // -------------------- Implementation -------------------- - /** Stop tomcat using the configured cm - * The manager is set up using the same configuration file, so - * it will have the same port as the original instance ( no need - * for a "log" file). - * It uses the Ajp12 connector, which has a built-in "stop" method, - * that will change when we add real callbacks ( it's equivalent - * with the previous RMI method from almost all points of view ) - */ - void stopTomcat() throws TomcatException { - XmlMapper xh=new XmlMapper(); - xh.setDebug( 0 ); - ContextManager cm=new ContextManager(); + void stopTomcat() throws Exception { + String tchome=getTomcatInstall(); + int port=8007; + InetAddress address=null; - ServerXmlHelper sxml=new ServerXmlHelper(); - - sxml.setConnectorHelper( xh ); - String tchome=sxml.getTomcatInstall(); - // load server.xml - File f = null; - if (configFile != null) - f=new File(configFile); - else - f=new File(tchome, DEFAULT_CONFIG); - cm.setInstallDir( tchome); - try { - xh.readXml(f,cm); - } catch( Exception ex ) { - throw new TomcatException("Fatal exception reading " + f, ex); + BufferedReader rd=new BufferedReader + ( new FileReader( tchome + "/conf/ajp12.id")); + String portLine=rd.readLine(); + + try { + port=Integer.parseInt( portLine ); + } catch(NumberFormatException ex ) { + ex.printStackTrace(); + } + String addLine=rd.readLine(); + if( addLine!=null && !"".equals( addLine )) { + try { + address=InetAddress.getByName( addLine ); + } catch( UnknownHostException ex ) { + ex.printStackTrace(); + } + } + String secret=rd.readLine(); + if( "".equals( secret ) ) + secret=null; + + System.out.println("Stoping tomcat on " + address + ":" +port +" " + + secret); + stopTomcat( address,port, secret ); + + } catch( IOException ex ) { + ex.printStackTrace(); } - - execute( cm ); + } + public String getTomcatInstall() { + // Use the "tomcat.home" property to resolve the default filename + String tchome = System.getProperty("tomcat.home"); + if (tchome == null) { + System.out.println(sm.getString("tomcat.nohome")); + tchome = "."; + // Assume current working directory + } + return tchome; + } - /** This particular implementation will search for an AJP12 - connector ( that have a special stop command ). - */ - public void execute(ContextManager cm) - throws TomcatException + /** + * This particular implementation will search for an AJP12 + * connector ( that have a special stop command ). + */ + public void stopTomcat(InetAddress address, int portInt, String secret ) + throws IOException { - // Find Ajp12 connector - int portInt=8007; - InetAddress address=null; - BaseInterceptor ci[]=cm.getContainer().getInterceptors(); - for( int i=0; i<ci.length; i++ ) { - Object con=ci[i]; - if( con instanceof Ajp12Interceptor ) { - Ajp12Interceptor tcpCon=(Ajp12Interceptor) con; - portInt=tcpCon.getPort(); - address=tcpCon.getAddress(); - } - } - // use Ajp12 to stop the server... try { if (address == null) address = InetAddress.getLocalHost(); Socket socket = new Socket(address, portInt); OutputStream os=socket.getOutputStream(); - byte stopMessage[]=new byte[2]; - stopMessage[0]=(byte)254; - stopMessage[1]=(byte)15; - os.write( stopMessage ); - socket.close(); - } catch(Exception ex ) { - throw new TomcatException("Error stopping Tomcat with Ajp12 on " + - address + ":" + portInt, ex); + sendAjp12Stop( os, secret ); + os.flush(); + os.close(); + // socket.close(); + } catch(IOException ex ) { + System.out.println("Error stopping Tomcat with Ajp12 on " + + address + ":" + portInt + " " + ex); + throw ex; } } + + /** Small AJP12 client util + */ + public void sendAjp12Stop( OutputStream os, String secret ) + throws IOException + { + byte stopMessage[]=new byte[2]; + stopMessage[0]=(byte)254; + stopMessage[1]=(byte)15; + os.write( stopMessage ); + if(secret!=null ) + sendAjp12String( os, secret ); + } + + /** Small AJP12 client util + */ + public void sendAjp12String( OutputStream os, String s ) + throws IOException + { + int len=s.length(); + os.write( len/256 ); + os.write( len%256 ); + os.write( s.getBytes() );// works only for ascii + } + /** Process arguments - set object properties from the list of args. + */ + public boolean processArgs(String[] args) { + for (int i = 0; i < args.length; i++) { + String arg = args[i]; + + if (arg.equals("-h") || arg.equals("-home")) { + i++; + if (i < args.length) + System.getProperties().put("tomcat.home", args[i]); + else + return false; + } + } + return true; + } + + public static void main(String args[] ) { + try { + StopTomcat tomcat=new StopTomcat(); + tomcat.processArgs( args ); + tomcat.execute(); + } catch(Exception ex ) { + System.out.println(sm.getString("tomcat.fatal")); + ex.printStackTrace(); + System.exit(1); + } + } + + } 1.11 +13 -3 jakarta-tomcat/src/share/org/apache/tomcat/modules/server/Ajp12.java Index: Ajp12.java =================================================================== RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/server/Ajp12.java,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- Ajp12.java 2000/12/26 23:35:34 1.10 +++ Ajp12.java 2000/12/29 19:59:19 1.11 @@ -79,6 +79,7 @@ boolean shutdown=false; boolean isPing=false; boolean doLog; + String secret=null; public Ajp12() { } @@ -102,6 +103,10 @@ sin = s.getInputStream(); ajpin = new BufferedInputStream(sin); } + + public void setSecret( String s ) { + secret=s; + } public void readNextRequest(Request req) throws IOException { String dummy,token1,token2; @@ -241,11 +246,15 @@ // not corrupted InetAddress serverAddr = socket.getLocalAddress(); InetAddress clientAddr = socket.getInetAddress(); - sin.close(); if ( (signal== 15) && isSameAddress(serverAddr, clientAddr) ) { - // Shutdown - probably apache was stoped with - // apachectl stop + if( secret!=null ) { + String stopMsg=readString(ajpin, ""); + if( ! secret.equals( stopMsg ) ) { + req.getContextManager().log("Attempt to stop with the wrong secret"); + return; + } + } req.getContextManager().stop(); // same behavior as in past, because it seems // that stopping everything doesn't work - @@ -256,6 +265,7 @@ shutdown=true; return; } + sin.close(); } catch (Exception ignored) { req.getContextManager().log("Ignored exception " + "processing signal " + 1.9 +40 -21 jakarta-tomcat/src/share/org/apache/tomcat/modules/server/Ajp12Interceptor.java Index: Ajp12Interceptor.java =================================================================== RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/server/Ajp12Interceptor.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- Ajp12Interceptor.java 2000/12/29 01:34:42 1.8 +++ Ajp12Interceptor.java 2000/12/29 19:59:19 1.9 @@ -77,6 +77,8 @@ public class Ajp12Interceptor extends PoolTcpConnector implements TcpConnectionHandler{ private boolean tomcatAuthentication=true; + String secret; + public Ajp12Interceptor() { super(); } @@ -86,30 +88,41 @@ ep.setConnectionHandler( this ); } + /** Enable the use of a stop secret. The secret will be + * randomly generated. + */ + public void setUseSecret(boolean b ) { + secret=Double.toString(Math.random()); + } + + /** Explicitely set the stop secret + */ + public void setSecret( String s ) { + secret=s; + } + public void engineInit(ContextManager cm ) throws TomcatException { - super.engineInit( cm ); - BaseInterceptor ci[]=cm.getContainer().getInterceptors(); - for( int i=0; i<ci.length; i++ ) { - Object con=ci[i]; - if( con instanceof Ajp12Interceptor ) { - Ajp12Interceptor tcpCon=(Ajp12Interceptor) con; - int portInt=tcpCon.getPort(); - InetAddress address=tcpCon.getAddress(); - try { - PrintWriter stopF=new PrintWriter - (new FileWriter(cm.getHome() + "/conf/ajp12.id")); - stopF.println( portInt ); - if( address==null ) - stopF.println( "" ); - else - stopF.println( address.toString() ); - stopF.close(); - } catch( IOException ex ) { - log( "Can't create ajp12.id " + ex ); - } - } + super.engineInit(cm); + Ajp12Interceptor tcpCon=this; + int portInt=tcpCon.getPort(); + InetAddress address=tcpCon.getAddress(); + try { + PrintWriter stopF=new PrintWriter + (new FileWriter(cm.getHome() + "/conf/ajp12.id")); + stopF.println( portInt ); + if( address==null ) + stopF.println( "" ); + else + stopF.println( address.toString() ); + if( secret !=null ) + stopF.println( secret ); + else + stopF.println(); + stopF.close(); + } catch( IOException ex ) { + log( "Can't create ajp12.id " + ex ); } } @@ -118,6 +131,7 @@ public Object[] init() { Object thData[]=new Object[2]; AJP12Request reqA=new AJP12Request(); + reqA.setSecret( secret ); AJP12Response resA=new AJP12Response(); cm.initRequest( reqA, resA ); thData[0]=reqA; @@ -159,6 +173,7 @@ if( reqA==null || resA==null ) { reqA = new AJP12Request(); + reqA.setSecret( secret ); ((AJP12Request)reqA).setTomcatAuthentication( isTomcatAuthentication()); resA=new AJP12Response(); @@ -195,6 +210,10 @@ public AJP12Request() { } + void setSecret( String s ) { + ajp12.setSecret( s ); + } + public boolean internalAjp() { return ajp12.isPing || ajp12.shutdown; 1.3 +9 -0 jakarta-tomcat/src/share/org/apache/tomcat/modules/server/PoolTcpConnector.java Index: PoolTcpConnector.java =================================================================== RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/server/PoolTcpConnector.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- PoolTcpConnector.java 2000/09/29 21:09:47 1.2 +++ PoolTcpConnector.java 2000/12/29 19:59:19 1.3 @@ -106,6 +106,15 @@ try { localInit(); + } catch( Exception ex ) { + throw new TomcatException( ex ); + } + } + + /** Called when the ContextManger is started + */ + public void engineStart(ContextManager cm) throws TomcatException { + try { if( socketFactory!=null ) { Enumeration attE=attributes.keys(); while( attE.hasMoreElements() ) { --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]