001: /*
002: * This file is part of the QuickServer library
003: * Copyright (C) QuickServer.org
004: *
005: * Use, modification, copying and distribution of this software is subject to
006: * the terms and conditions of the GNU Lesser General Public License.
007: * You should have received a copy of the GNU LGP License along with this
008: * library; if not, you can download a copy from <http://www.quickserver.org/>.
009: *
010: * For questions, suggestions, bug-reports, enhancement-requests etc.
011: * visit http://www.quickserver.org
012: *
013: */
014:
015: package org.quickserver.net.qsadmin;
016:
017: import java.io.*;
018: import java.util.*;
019: import java.net.*;
020: import org.quickserver.net.server.QuickServer;
021: import org.quickserver.util.xmlreader.*;
022: import org.quickserver.util.MyString;
023: import java.util.logging.*;
024:
025: /**
026: * QSAdmin Command Shell.
027: * This class will auto increase the maxClient by 1 if for QSAdminServer
028: * maxClient is not equals to -1 and 0 (no other client except shell is allowed).
029: * @author Akshathkumar Shetty
030: * @since 1.3.2
031: */
032: public class QSAdminShell extends Thread {
033: private static Logger logger = Logger.getLogger(QSAdminShell.class
034: .getName());
035:
036: private String promptName = "QSAdmin";
037: private String promptPostFix = ":> ";
038: private String prompt = promptName + promptPostFix;
039:
040: private String error = "Error: ";
041:
042: private BufferedReader in;
043: private String command = "";
044:
045: private Socket clientSocket = null;
046: private QuickServer server;
047:
048: private InputStream s_in;
049: private OutputStream s_out;
050: private BufferedReader s_br;
051: private BufferedOutputStream s_bo;
052:
053: private boolean gotResponse;
054: private boolean multilineResponse;
055: private boolean stop = false;
056:
057: private static QSAdminShell qsAdminShell;
058: private static long oldMaxClient = -1;
059:
060: public static QSAdminShell getInstance(QuickServer server,
061: String promptName) {
062: if (qsAdminShell == null) {
063: if (server != null) {
064: qsAdminShell = new QSAdminShell(server, promptName);
065: qsAdminShell.start();
066: } else {
067: return null;
068: }
069: } else {
070: if (server != null)
071: qsAdminShell.server = server;
072: if (promptName != null)
073: qsAdminShell.promptName = promptName;
074: qsAdminShell.stop = false;
075: }
076: return qsAdminShell;
077: }
078:
079: private QSAdminShell(QuickServer server, String promptName) {
080: super ("GUIAdminShell");
081: setDaemon(true);
082: this .server = server;
083: if (promptName != null)
084: setPromptName(promptName);
085: in = new BufferedReader(new InputStreamReader(System.in));
086: logger.fine("Starting QSAdmin Shell");
087: }
088:
089: public void setPromptName(String name) {
090: if (name == null)
091: return;
092: promptName = name;
093: prompt = promptName + promptPostFix;
094: }
095:
096: public String getPromptName() {
097: return promptName;
098: }
099:
100: public void stopShell() throws IOException {
101: stop = true;
102: clientSocket.close();
103: }
104:
105: public void run() {
106: try {
107: for (int i = 0; i < 3; i++) {
108: sleep(500);
109: if (server.getQSAdminServer().getServer().isClosed() == false) {
110: connect();
111: break;
112: }
113: if (i == 3) {
114: logger
115: .warning(error
116: + "QSAdminServer is not running!! So stopping QSAdminShell.");
117: return;
118: }
119: }
120: } catch (Exception e) {
121: logger.fine(error + e.getMessage());
122: }
123: while (stop == false) {
124: try {
125: print(prompt);
126: command = in.readLine();
127:
128: if (stop) {
129: if (command.trim().equals("") == false)
130: System.out
131: .println("Command ignored since shell was closed.");
132: break;
133: }
134:
135: if (command == null) {
136: System.out.println("");
137: logger
138: .severe("User must have forced an exit at shell!");
139: continue;
140: }
141:
142: if (command.equals("FullThreadDump")) {
143: tryFullThreadDump();
144: continue;
145: }
146:
147: /*
148: if(command.toLowerCase().startsWith("shellto")) {
149: try {
150: StringTokenizer st =
151: new StringTokenizer(command, " ");
152: if(st.countTokens()!=3) {
153: throw new Exception("Bad param sent to shellto command!");
154: }
155:
156: clientSocket.close();
157: clientSocket = null;
158: st.nextToken();
159: connect(st.nextToken(),
160: Integer.parseInt(st.nextToken()));
161: continue;
162: } catch(Exception e) {
163: logger.fine(error+e.getMessage());
164: }
165: } else */
166: if (command.toLowerCase().startsWith("disconnect")) {
167: try {
168: clientSocket.close();
169: s_bo.close();
170: s_br.close();
171: } catch (Exception er) {
172: println("-ERR " + er);
173: }
174: break;
175: }
176:
177: if (command.trim().equals("") == false) {
178: if (clientSocket == null) {
179: if (connect() == false)
180: continue;
181: }
182: sendCommand(command);
183: } else {
184: if (clientSocket == null) {
185: connect();
186: }
187: }
188: } catch (Exception e) {
189: println("-ERR " + e);
190: }
191: }//end while
192: qsAdminShell = null;
193: }
194:
195: private void print(String text) {
196: System.out.print(text);
197: }
198:
199: private void println(String text) {
200: System.out.println(text);
201: }
202:
203: private boolean connect() throws IOException {
204: try {
205: server.getQSAdminServer().getServer().nextClientIsTrusted();
206: int port = server.getQSAdminServer().getServer().getPort();
207: String host = server.getQSAdminServer().getServer()
208: .getBindAddr().getHostAddress();
209: connect(host, port);
210: return true;
211: } catch (Exception e) {
212: println(error + e.getMessage());
213: logger.warning(MyString.getStackTrace(e));
214: if (clientSocket != null) {
215: try {
216: clientSocket.close();
217: } catch (Exception ignore) {/*ignore*/
218: }
219: clientSocket = null;
220: }
221: return false;
222: }
223: }
224:
225: private void connect(String host, int port) throws IOException {
226: clientSocket = new Socket(host, port);
227: clientSocket.setSoTimeout(0);
228: s_in = clientSocket.getInputStream();
229: s_out = clientSocket.getOutputStream();
230: s_br = new BufferedReader(new InputStreamReader(s_in));
231: s_bo = new BufferedOutputStream(s_out);
232:
233: String temp = null;
234: //skip header
235: temp = s_br.readLine();
236: temp = s_br.readLine();
237: temp = s_br.readLine();
238:
239: if (oldMaxClient == -1) {
240: //increase maxClient for self by 1
241: try {
242: long maxC = -1;
243: sendCommand("get self maxClient", false);
244: temp = s_br.readLine();
245: maxC = Long.parseLong(temp.substring(4));
246: if (maxC != -1 && maxC != 0) {
247: oldMaxClient = maxC;
248: maxC++;
249: sendCommand("set self maxClient " + maxC, false);
250: temp = s_br.readLine();
251: if (temp.startsWith("+OK") == false) {
252: println(error
253: + "Could not increase max client from QSAdmin : "
254: + s_br);
255: }
256: }
257: } catch (IOException ioe) {
258: throw ioe;
259: } catch (Exception ignoreEx) {
260: println(error + ignoreEx.getMessage());
261: }
262: }
263: startSocketListener();
264: }
265:
266: private synchronized void sendCommand(String command)
267: throws IOException {
268: sendCommand(command, true);
269: }
270:
271: private synchronized void sendCommand(String command, boolean wait)
272: throws IOException {
273: if (clientSocket == null)
274: println(error + "Not connected yet");
275: command += QuickServer.getNewLine();
276: gotResponse = false;
277: byte d[] = command.getBytes();
278: s_bo.write(d, 0, d.length);
279: s_bo.flush();
280:
281: try {
282: while (wait == true && gotResponse == false)
283: sleep(100);
284: } catch (InterruptedException e) {
285: logger.fine(error + e.getMessage());
286: }
287: }
288:
289: public void startSocketListener() {
290: final String pad = "";
291: Thread t = new Thread() {
292: public void run() {
293: String rec = "";
294: while (true) {
295: try {
296: rec = s_br.readLine();
297: } catch (IOException e) {
298: logger.info("Shell Closed! " + e.getMessage());
299: break;
300: }
301: if (rec == null) {
302: clientSocket = null;
303: break;
304: }
305:
306: if (rec.equals("+OK info follows"))
307: multilineResponse = true;
308:
309: println(pad + rec);
310:
311: if (multilineResponse == false)
312: gotResponse = true;
313: else {
314: if (rec.equals(".")) {
315: gotResponse = true;
316: multilineResponse = false;
317: }
318: }
319: } //end of while
320: try {
321: clientSocket.close();
322: clientSocket = null;
323: } catch (Exception e) {
324: logger.fine(error + e.getMessage());
325: }
326: }
327: };
328: t.setDaemon(true);
329: t.setName("GUIAdminShell-SocketListener");
330: t.start();
331: }
332:
333: public static void tryFullThreadDump() {
334: System.out.println("Trying to get Full Thread Dump @ "
335: + new java.util.Date());
336: String os = System.getProperty("os.name");
337: if (os != null && os.toLowerCase().startsWith("windows")) {
338: try {
339: java.awt.Robot robot = new java.awt.Robot();
340: robot.keyPress(java.awt.event.KeyEvent.VK_CONTROL);
341: robot.keyPress(java.awt.event.KeyEvent.VK_CANCEL);
342: robot.keyRelease(java.awt.event.KeyEvent.VK_CANCEL);
343: robot.keyRelease(java.awt.event.KeyEvent.VK_CONTROL);
344: } catch (Exception ignore) {
345: logger.warning("Could not press: Ctrl+Break");
346: }
347: } else {
348: try {
349: java.awt.Robot robot = new java.awt.Robot();
350: robot.keyPress(java.awt.event.KeyEvent.VK_CONTROL);
351: robot.keyPress(java.awt.event.KeyEvent.VK_BACK_SLASH);
352: robot.keyRelease(java.awt.event.KeyEvent.VK_BACK_SLASH);
353: robot.keyRelease(java.awt.event.KeyEvent.VK_CONTROL);
354: } catch (Exception ignore) {
355: logger.warning("Could not press: Ctrl+\\");
356: }
357: }
358: }
359: }
|