blob: 5be8afc2ba2ce30cd9106eaeb87d9ae403e22299 [file] [log] [blame]
/*
* This file is part of the QuickServer library
* Copyright (C) QuickServer.org
*
* Use, modification, copying and distribution of this software is subject to
* the terms and conditions of the GNU Lesser General Public License.
* You should have received a copy of the GNU LGP License along with this
* library; if not, you can download a copy from <http://www.quickserver.org/>.
*
* For questions, suggestions, bug-reports, enhancement-requests etc.
* visit http://www.quickserver.org
*
*/
package org.quickserver.net.qsadmin;
import java.io.*;
import java.util.*;
import java.net.*;
import org.quickserver.net.server.QuickServer;
import org.quickserver.util.xmlreader.*;
import org.quickserver.util.MyString;
import java.util.logging.*;
/**
* QSAdmin Command Shell.
* This class will auto increase the maxClient by 1 if for QSAdminServer
* maxClient is not equals to -1 and 0 (no other client except shell is allowed).
* @author Akshathkumar Shetty
* @since 1.3.2
*/
public class QSAdminShell extends Thread {
private static Logger logger = Logger.getLogger(
QSAdminShell.class.getName());
private String promptName = "QSAdmin";
private String promptPostFix = ":> ";
private String prompt = promptName+promptPostFix;
private String error = "Error: ";
private BufferedReader in;
private String command = "";
private Socket clientSocket = null;
private QuickServer server;
private InputStream s_in;
private OutputStream s_out;
private BufferedReader s_br;
private BufferedOutputStream s_bo;
private boolean gotResponse;
private boolean multilineResponse;
private boolean stop = false;
private static QSAdminShell qsAdminShell;
private static long oldMaxClient = -1;
public static QSAdminShell getInstance(QuickServer server, String promptName) {
if(qsAdminShell==null) {
if(server!=null) {
qsAdminShell = new QSAdminShell(server, promptName);
qsAdminShell.start();
} else {
return null;
}
} else {
if(server!=null)
qsAdminShell.server = server;
if(promptName!=null)
qsAdminShell.promptName = promptName;
qsAdminShell.stop = false;
}
return qsAdminShell;
}
private QSAdminShell(QuickServer server, String promptName) {
super("GUIAdminShell");
setDaemon(true);
this.server = server;
if(promptName!=null)
setPromptName(promptName);
boolean isConsole = true;
try {
if(System.console()==null) {
isConsole = false;
}
} catch(Throwable e) {
//ignore..
}
if(isConsole) {
try {
in = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
} catch(UnsupportedEncodingException e) {
logger.warning("UTF-8 was not supported: "+e);
in = new BufferedReader(new InputStreamReader(System.in));
}
logger.fine("Starting QSAdmin Shell");
} else {
System.out.println("QuickServer: System does not have console so not starting QSAdmin Shell!");
}
}
public void setPromptName(String name) {
if(name==null) return;
promptName = name;
prompt = promptName+promptPostFix;
}
public String getPromptName() {
return promptName;
}
public void stopShell() throws IOException {
stop = true;
clientSocket.close();
}
public void run() {
if(in==null) {
logger.warning("We do not have System.in.. So stopping QSAdminShell.");
return;
}
try {
for(int i=0;i<3;i++) {
sleep(500);
if(server.getQSAdminServer().getServer().isClosed()==false) {
connect();
break;
}
if(i==3) {
logger.warning(error+"QSAdminServer is not running!! So stopping QSAdminShell.");
return;
}
}
} catch(Exception e) {
logger.fine(error+e.getMessage());
}
while(stop==false) {
try {
print(prompt);
command = in.readLine();
if(stop) {
if(command.trim().equals("")==false)
System.out.println("Command ignored since shell was closed.");
break;
}
if(command==null) {
System.out.println("");
logger.severe("User must have forced an exit at shell!");
continue;
}
if(command.equals("FullThreadDump")) {
tryFullThreadDump();
continue;
}
/*
if(command.toLowerCase().startsWith("shellto")) {
try {
StringTokenizer st =
new StringTokenizer(command, " ");
if(st.countTokens()!=3) {
throw new Exception("Bad param sent to shellto command!");
}
clientSocket.close();
clientSocket = null;
st.nextToken();
connect(st.nextToken(),
Integer.parseInt(st.nextToken()));
continue;
} catch(Exception e) {
logger.fine(error+e.getMessage());
}
} else */
if(command.toLowerCase().startsWith("disconnect")) {
try {
clientSocket.close();
s_bo.close();
s_br.close();
} catch(Exception er) {
println("-ERR "+er);
}
break;
}
if(command.trim().equals("")==false) {
if(clientSocket==null) {
if(connect()==false)
continue;
}
sendCommand(command);
} else {
if(clientSocket==null) {
connect();
}
}
} catch(Exception e) {
println("-ERR "+e);
}
}//end while
qsAdminShell = null;
}
private void print(String text) {
System.out.print(text);
}
private void println(String text) {
System.out.println(text);
}
private boolean connect() throws IOException {
try {
server.getQSAdminServer().getServer().nextClientIsTrusted();
int port = server.getQSAdminServer().getServer().getPort();
String host =
server.getQSAdminServer().getServer().getBindAddr().getHostAddress();
connect(host, port);
return true;
} catch(Exception e) {
println(error+e.getMessage());
logger.warning(MyString.getStackTrace(e));
if(clientSocket!=null) {
try {
clientSocket.close();
} catch(Exception ignore) {/*ignore*/}
clientSocket = null;
}
return false;
}
}
private void connect(String host, int port) throws IOException {
clientSocket = new Socket(host, port);
clientSocket.setSoTimeout(0);
s_in = clientSocket.getInputStream();
s_out = clientSocket.getOutputStream();
s_br = new BufferedReader(new InputStreamReader(s_in, "UTF-8"));
s_bo = new BufferedOutputStream(s_out);
String temp = null;
//skip header
temp = s_br.readLine();
temp = s_br.readLine();
temp = s_br.readLine();
if(oldMaxClient==-1) {
//increase maxClient for self by 1
try {
long maxC = -1;
sendCommand("get self maxClient", false);
temp = s_br.readLine();
maxC = Long.parseLong(temp.substring(4));
if(maxC!=-1 && maxC!=0) {
oldMaxClient = maxC;
maxC++;
sendCommand("set self maxClient "+maxC, false);
temp = s_br.readLine();
if(temp.startsWith("+OK")==false) {
println(error+"Could not increase max client from QSAdmin : "+s_br);
}
}
} catch(IOException ioe) {
throw ioe;
} catch(Exception ignoreEx) {
println(error+ignoreEx.getMessage());
}
}
startSocketListener();
}
private synchronized void sendCommand(String command) throws IOException {
sendCommand(command, true);
}
private synchronized void sendCommand(String command, boolean wait)
throws IOException {
if(clientSocket==null)
println(error+"Not connected yet");
command += QuickServer.getNewLine();
gotResponse = false;
byte d[] = command.getBytes();
s_bo.write(d, 0, d.length);
s_bo.flush();
try {
while(wait==true && gotResponse==false)
sleep(100);
} catch(InterruptedException e) {
logger.fine(error+e.getMessage());
}
}
public void startSocketListener() {
final String pad = "";
Thread t = new Thread() {
public void run() {
String rec = "";
while(true) {
try {
rec = s_br.readLine();
} catch(IOException e) {
logger.info("Shell Closed! "+e.getMessage());
break;
}
if(rec==null) {
clientSocket=null;
break;
}
if(rec.equals("+OK info follows"))
multilineResponse = true;
println(pad+rec);
if(multilineResponse==false)
gotResponse=true;
else {
if(rec.equals(".")) {
gotResponse=true;
multilineResponse=false;
}
}
} //end of while
try {
clientSocket.close();
clientSocket = null;
} catch(Exception e) {
logger.fine(error+e.getMessage());
}
}
};
t.setDaemon(true);
t.setName("GUIAdminShell-SocketListener");
t.start();
}
public static void tryFullThreadDump() {
System.out.println("Trying to get Full Thread Dump @ "+new java.util.Date());
String os = System.getProperty("os.name");
if(os!=null && os.toLowerCase().startsWith("windows")) {
try {
java.awt.Robot robot = new java.awt.Robot();
robot.keyPress(java.awt.event.KeyEvent.VK_CONTROL);
robot.keyPress(java.awt.event.KeyEvent.VK_CANCEL);
robot.keyRelease(java.awt.event.KeyEvent.VK_CANCEL);
robot.keyRelease(java.awt.event.KeyEvent.VK_CONTROL);
} catch(Exception ignore) {
logger.warning("Could not press: Ctrl+Break");
}
} else {
try {
java.awt.Robot robot = new java.awt.Robot();
robot.keyPress(java.awt.event.KeyEvent.VK_CONTROL);
robot.keyPress(java.awt.event.KeyEvent.VK_BACK_SLASH);
robot.keyRelease(java.awt.event.KeyEvent.VK_BACK_SLASH);
robot.keyRelease(java.awt.event.KeyEvent.VK_CONTROL);
} catch(Exception ignore) {
logger.warning("Could not press: Ctrl+\\");
}
}
}
}