001: /*
002: * ========================================================================
003: *
004: * Copyright 2001-2003 The Apache Software Foundation.
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: *
018: * ========================================================================
019: */
020: package org.apache.cactus.integration.ant.container;
021:
022: import java.io.IOException;
023: import java.net.ServerSocket;
024: import java.net.Socket;
025: import java.util.Vector;
026:
027: /**
028: * Abstract class for starting/stopping an application server. When this
029: * application is first called to start the server, a listener socket is
030: * set up. Then, we it is later called to stop the server, we connect to the
031: * listener socket and tell the server to stop.
032: *
033: * @version $Id: AbstractServerRun.java 238918 2004-04-18 12:21:50Z vmassol $
034: */
035: public abstract class AbstractServerRun extends Thread {
036: /**
037: * Internal socket port that we use to stop the server.
038: */
039: private int port = 7777;
040:
041: /**
042: * Host name. We assume the server is started and stoppped in the same
043: * local machine
044: */
045: private String host = "127.0.0.1";
046:
047: /**
048: * The command line arguments
049: */
050: private String[] args;
051:
052: /**
053: * Flag that specifies if the server is already started to prevent
054: * starting it if it is.
055: */
056: private boolean isStarted = false;
057:
058: /**
059: * Thread in which the server is running
060: */
061: private Thread runningServerThread;
062:
063: /**
064: * @param theArgs the command line arguments
065: */
066: public AbstractServerRun(String[] theArgs) {
067: this .args = theArgs;
068: }
069:
070: /**
071: * Starts the server (in a blocking mode) and set up a socket listener.
072: *
073: * @return the thread in which the server has been started
074: * @param theArgs the command line arguments
075: * @exception Exception if any error happens when starting the server
076: */
077: protected abstract Thread doStartServer(String[] theArgs)
078: throws Exception;
079:
080: /**
081: * Stops the server by connecting to the socket set up when the server
082: * was started.
083: *
084: * @param theArgs the command line arguments
085: * @param theRunningServerThread the thread in which the server is running.
086: * This is useful for example if there is no simple way to stop the
087: * server and thus you need to simply try to stop the running thread.
088: * @exception Exception if any error happens when stopping the server
089: */
090: protected abstract void doStopServer(String[] theArgs,
091: Thread theRunningServerThread) throws Exception;
092:
093: /**
094: * Parse and process the command line to start/stop the server.
095: */
096: protected final void doRun() {
097: // Look for a -start or -stop flag
098: boolean isStart = true;
099: Vector newArgs = new Vector();
100:
101: for (int i = 0; i < this .args.length; i++) {
102: if (this .args[i].equalsIgnoreCase("-start")) {
103: isStart = true;
104: } else if (this .args[i].equalsIgnoreCase("-stop")) {
105: isStart = false;
106: } else if (this .args[i].equalsIgnoreCase("-port")) {
107: this .port = Integer.parseInt(this .args[i + 1]);
108: i++;
109: } else {
110: newArgs.add(this .args[i]);
111: }
112: }
113:
114: // Remove the command line arguments that should not be part of the
115: // server command line (i.e. our own arguments).
116: String[] strArgs = new String[0];
117:
118: this .args = (String[]) newArgs.toArray(strArgs);
119:
120: if (isStart) {
121: startServer();
122: } else {
123: stopServer();
124: }
125: }
126:
127: /**
128: * Starts the server.
129: */
130: private void startServer() {
131: // If the server is already started, do nothing
132: if (this .isStarted) {
133: return;
134: }
135:
136: try {
137: this .runningServerThread = doStartServer(this .args);
138: } catch (Exception e) {
139: e.printStackTrace();
140: throw new RuntimeException("Error starting server");
141: }
142:
143: // Server is now started
144: this .isStarted = true;
145:
146: // Start a socket listener that will listen for stop commands.
147: start();
148: }
149:
150: /**
151: * Stops the running server.
152: */
153: private void stopServer() {
154: // Open socket connection
155: Socket clientSocket = null;
156:
157: try {
158: clientSocket = new Socket(this .host, this .port);
159: } catch (Exception e) {
160: e.printStackTrace();
161: throw new RuntimeException("Error opening socket to "
162: + this .host + ":" + this .port + "]");
163: } finally {
164: try {
165: if (clientSocket != null) {
166: clientSocket.close();
167: }
168: } catch (IOException e) {
169: throw new RuntimeException("Cannot close client socket");
170: }
171: }
172: }
173:
174: /**
175: * Sets up a listener socket and wait until we receive a request on it to
176: * stop the running server.
177: */
178: public void run() {
179: ServerSocket serverSocket = setUpListenerSocket();
180:
181: // Accept a client socket connection
182: try {
183: serverSocket.accept();
184: } catch (IOException e) {
185: throw new RuntimeException(
186: "Error accepting connection for "
187: + "server socket [" + serverSocket + "]");
188: } finally {
189: // Stop server socket
190: try {
191: serverSocket.close();
192: } catch (IOException e) {
193: throw new RuntimeException(
194: "Cannot close server socket [" + serverSocket
195: + "]");
196: }
197: }
198:
199: // Stop server
200: try {
201: this .doStopServer(this .args, this .runningServerThread);
202: } catch (Exception e) {
203: e.printStackTrace();
204: throw new RuntimeException("Cannot stop server");
205: }
206:
207: // Stop server socket
208: try {
209: serverSocket.close();
210: } catch (IOException e) {
211: throw new RuntimeException("Cannot close server socket ["
212: + serverSocket + "]");
213: }
214: }
215:
216: /**
217: * Sets up the listener socket.
218: *
219: * @return the listener socket that has been set up
220: */
221: private ServerSocket setUpListenerSocket() {
222: ServerSocket serverSocket = null;
223:
224: try {
225: serverSocket = new ServerSocket(this .port);
226: } catch (IOException e) {
227: e.printStackTrace();
228: throw new RuntimeException("Error setting up the server "
229: + "listener socket");
230: }
231:
232: return serverSocket;
233: }
234: }
|