001: /*****************************************************************************
002: * Java Plug-in Framework (JPF)
003: * Copyright (C) 2004-2007 Dmitry Olshansky
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: *****************************************************************************/package org.java.plugin.boot;
019:
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.io.OutputStream;
023: import java.net.InetAddress;
024: import java.net.ServerSocket;
025: import java.net.Socket;
026:
027: import org.apache.commons.logging.Log;
028: import org.apache.commons.logging.LogFactory;
029:
030: /**
031: * @version $Id$
032: */
033: final class ControlThread extends Thread {
034: static boolean isApplicationRunning(final InetAddress host,
035: final int port) {
036: try {
037: Socket socket = new Socket(host, port);
038: try {
039: socket.setKeepAlive(true);
040: String test = "" + System.currentTimeMillis(); //$NON-NLS-1$
041: OutputStream out = socket.getOutputStream();
042: InputStream in = null;
043: try {
044: System.out
045: .println("found running control service on " //$NON-NLS-1$
046: + host + ":" + port); //$NON-NLS-1$
047: out.write(("PING " + test).getBytes()); //$NON-NLS-1$
048: out.flush();
049: socket.shutdownOutput();
050: in = socket.getInputStream();
051: StringBuilder commandResult = new StringBuilder();
052: byte[] buf = new byte[16];
053: int len;
054: while ((len = in.read(buf)) != -1) {
055: commandResult.append(new String(buf, 0, len));
056: }
057: socket.shutdownInput();
058: if (commandResult.toString().startsWith("OK") //$NON-NLS-1$
059: && (commandResult.toString().indexOf(test) != -1)) {
060: System.out.println("PING command succeed"); //$NON-NLS-1$
061: return true;
062: }
063: System.out.println("PING command failed"); //$NON-NLS-1$
064: } finally {
065: try {
066: out.close();
067: } catch (IOException ioe) {
068: // ignore
069: }
070: if (in != null) {
071: try {
072: in.close();
073: } catch (IOException ioe) {
074: // ignore
075: }
076: }
077: }
078: } finally {
079: socket.close();
080: }
081: } catch (IOException ioe) {
082: System.out
083: .println("seems that there is no control service running on " //$NON-NLS-1$
084: + host + ":" + port); //$NON-NLS-1$
085: //ioe.printStackTrace();
086: }
087: return false;
088: }
089:
090: static boolean stopRunningApplication(final InetAddress host,
091: final int port) {
092: boolean result = false;
093: try {
094: Socket socket = new Socket(host, port);
095: try {
096: socket.setKeepAlive(true);
097: OutputStream out = socket.getOutputStream();
098: InputStream in = null;
099: try {
100: System.out
101: .println("found running control service on " //$NON-NLS-1$
102: + host + ":" + port); //$NON-NLS-1$
103: out.write("STOP".getBytes()); //$NON-NLS-1$
104: out.flush();
105: socket.shutdownOutput();
106: in = socket.getInputStream();
107: StringBuilder commandResult = new StringBuilder();
108: byte[] buf = new byte[16];
109: int len;
110: while ((len = in.read(buf)) != -1) {
111: commandResult.append(new String(buf, 0, len));
112: }
113: socket.shutdownInput();
114: if (commandResult.toString().startsWith("OK")) { //$NON-NLS-1$
115: System.out.println("STOP command succeed"); //$NON-NLS-1$
116: result = true;
117: } else {
118: System.out.println("STOP command failed"); //$NON-NLS-1$
119: }
120: } finally {
121: try {
122: out.close();
123: } catch (IOException ioe) {
124: // ignore
125: }
126: if (in != null) {
127: try {
128: in.close();
129: } catch (IOException ioe) {
130: // ignore
131: }
132: }
133: }
134: } finally {
135: socket.close();
136: }
137: } catch (IOException ioe) {
138: System.out
139: .println("seems that there is no control service running on " //$NON-NLS-1$
140: + host + ":" + port); //$NON-NLS-1$
141: //ioe.printStackTrace();
142: }
143: if (result) {
144: try {
145: Thread.sleep(2000);
146: } catch (InterruptedException ie) {
147: // ignore
148: }
149: }
150: return result;
151: }
152:
153: private Log log;
154:
155: private ServerSocket serverSocket;
156: private final ServiceApplication application;
157: private boolean appRunning;
158:
159: ControlThread(final InetAddress host, final int port,
160: final ServiceApplication server) throws Exception {
161: log = LogFactory.getLog(this .getClass());
162: application = server;
163: serverSocket = new ServerSocket(port, 1, host);
164: appRunning = true;
165: setName("jpf-application-control-thread"); //$NON-NLS-1$
166: }
167:
168: /**
169: * @see java.lang.Runnable#run()
170: */
171: @Override
172: public void run() {
173: try {
174: while (true) {
175: try {
176: Socket clientSocket = serverSocket.accept();
177: try {
178: if (handleRequest(clientSocket)) {
179: break;
180: }
181: } finally {
182: try {
183: clientSocket.close();
184: } catch (IOException ioe) {
185: // ignore
186: }
187: }
188: } catch (Exception e) {
189: warn("error on server socket", e); //$NON-NLS-1$
190: break;
191: }
192: }
193: } catch (Exception e) {
194: error(e);
195: } finally {
196: try {
197: serverSocket.close();
198: } catch (IOException ioe) {
199: warn("error closing server socket", ioe); //$NON-NLS-1$
200: }
201: if (appRunning) {
202: stopApplication();
203: }
204: }
205: }
206:
207: private synchronized boolean handleRequest(final Socket clientSocket) {
208: debug("handling control request"); //$NON-NLS-1$
209: if (!isValidRemoteHost(clientSocket.getInetAddress())) {
210: warn("incoming connection to control socket registered" //$NON-NLS-1$
211: + " from REMOTE address " + clientSocket.getInetAddress() //$NON-NLS-1$
212: + ", attempt to execute command was IGNORED"); //$NON-NLS-1$
213: try {
214: clientSocket.close();
215: } catch (IOException e) {
216: // ignore
217: }
218: return false;
219: }
220: debug("processing control request"); //$NON-NLS-1$
221: boolean result = false;
222: try {
223: String commandResult;
224: InputStream in = clientSocket.getInputStream();
225: OutputStream out = null;
226: try {
227: StringBuilder command = new StringBuilder();
228: byte[] buf = new byte[16];
229: int len;
230: while ((len = in.read(buf)) != -1) {
231: command.append(new String(buf, 0, len));
232: }
233: clientSocket.shutdownInput();
234: debug("got command - " + command); //$NON-NLS-1$
235: if ("STOP".equals(command.toString())) { //$NON-NLS-1$
236: stopApplication();
237: result = true;
238: commandResult = "OK: stop done"; //$NON-NLS-1$
239: } else if (command.toString().startsWith("PING")) { //$NON-NLS-1$
240: commandResult = "OK: " //$NON-NLS-1$
241: + command.substring("PING".length()); //$NON-NLS-1$
242: } else {
243: commandResult = "ERROR: unknown command"; //$NON-NLS-1$
244: }
245: //debug("command executed");
246: //debug("sending command result - " + commandResult);
247: out = clientSocket.getOutputStream();
248: out.write(commandResult.getBytes());
249: out.flush();
250: clientSocket.shutdownOutput();
251: //debug("command result sent");
252: } finally {
253: try {
254: in.close();
255: } catch (IOException ioe) {
256: // ignore
257: }
258: if (out != null) {
259: try {
260: out.close();
261: } catch (IOException ioe) {
262: // ignore
263: }
264: }
265: }
266: } catch (IOException ioe) {
267: error("error processing control request", ioe); //$NON-NLS-1$
268: }
269: return result;
270: }
271:
272: private void stopApplication() {
273: if (!appRunning) {
274: debug("application not running"); //$NON-NLS-1$
275: return;
276: }
277: appRunning = false;
278: debug("stopping application"); //$NON-NLS-1$
279: try {
280: Boot.stopApplication(application);
281: log = null;
282: } catch (Exception e) {
283: error("an error has occurred while stopping" //$NON-NLS-1$
284: + " application", e); //$NON-NLS-1$
285: }
286: debug("application stopped from control thread"); //$NON-NLS-1$
287: }
288:
289: private boolean isValidRemoteHost(final InetAddress addr) {
290: byte[] localAddr = serverSocket.getInetAddress().getAddress();
291: byte[] remoteAddr = addr.getAddress();
292: if (localAddr.length != remoteAddr.length) {
293: return false;
294: }
295: for (int i = 0; i < remoteAddr.length; i++) {
296: if (localAddr[i] != remoteAddr[i]) {
297: return false;
298: }
299: }
300: return true;
301: }
302:
303: private void debug(final String msg) {
304: if (log != null) {
305: log.debug(msg);
306: } else {
307: System.out.println(msg);
308: }
309: }
310:
311: private void warn(final String msg) {
312: if (log != null) {
313: log.warn(msg);
314: } else {
315: System.out.println(msg);
316: }
317: }
318:
319: private void warn(final String msg, final Exception e) {
320: if (log != null) {
321: log.warn(msg, e);
322: } else {
323: System.out.println(msg);
324: e.printStackTrace();
325: }
326: }
327:
328: private void error(final String msg, final Exception e) {
329: if (log != null) {
330: log.error(msg, e);
331: } else {
332: System.err.println(msg);
333: e.printStackTrace();
334: }
335: }
336:
337: private void error(final Exception e) {
338: if (log != null) {
339: log.error(e);
340: } else {
341: e.printStackTrace();
342: }
343: }
344: }
|