Write commands to running process - java

I've searched quite a bit for answers, but haven't found anything that really helps, and the threads I found were zombies.
My problem: I'm creating a UI for Bukkit servers, but for end-users to execute commands in the server, I have to write to the process using an OutputStreamWriter.
I have all the code, but the command isn't getting sent to the process.
So far, this is the code I'm using to execute the server and get all the streams:
#SuppressWarnings("null")
private void startServer() throws InterruptedException, IOException {
setTitleText("BukkitUI by Beatsleigher [Starting...]");
setStatusImg(ServerState.BOOTING);
Thread.sleep(1000);
setTitleText("BukkitUI by Beatsleigher [Loading components...]");
runServer = true;
process = new ProcessBuilder();
// Set attibutes
process.redirectErrorStream(true);
java.util.List<String> jvmArgs = new ArrayList<>(4);
jvmArgs.add(JVMManager.getJava().toString()); // If you don't know what this does, you should not consider yourself a programmer.
jvmArgs.add("-jar");
jvmArgs.add(JVMManager.getProcessedInitHeapSize()); // Add Java VM arg[0]
//jvmArgs.add(JVMManager.getProcessedMaxHeapSize()); // Add Java VM arg[1]
jvmArgs.add(PreferenceManager.getBukkitLocation().getAbsolutePath()); // Add Java VM arg[2]
jvmArgs.add("-o"); // Add CraftBukkit arg[0]
jvmArgs.add("true"); // Add CraftBukkit arg[1]
process.command(jvmArgs);
// Start process
pr = process.start();
setTitleText("BukkitUI by Beatsleigher [Running]");
consoleWriter = new BufferedWriter(new OutputStreamWriter(pr.getOutputStream()));
processServer();
}
private void processServer() throws IOException {
new Thread() {
#Override
public void run() {
try {
setStatusImg(ServerState.ONLINE);
jTextPane1.setText("");
consoleReader = new BufferedReader(new InputStreamReader(pr.getInputStream()));
while ((consoleOutput = consoleReader.readLine()) != null && (runServer)) {
jTextPane1.setText(jTextPane1.getText() + "\n" + consoleOutput);
highlight();
}
jTextPane1.setText(jTextPane1.getText() + "\n[INFO] [BukkitUI] Server has Stopped!");
highlight();
stopServer();
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
pr.destroy();
try {
consoleReader.close();
} catch (IOException ex1) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex1);
}
setStatusImg(ServerState.OFFLINE);
setTitleText("BukkitUI by Beatsleigher [ERROR! Server has stopped!]");
}
}
}.start();
}
The server starts and runs fine, I get all the process output I need, but, as mentioned before, any commands I send to the console using following code won't work.
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String inputCmd = jTextField1.getText();
try {
if (inputCmd != null | !inputCmd.equals("")) {
if (inputCmd.startsWith("/")) {
String[] cmd = inputCmd.split("/");
consoleWriter.write(cmd[1]);
clearCmd();
return;
} else if (inputCmd.startsWith("cmd;")) {
String[] cmd = inputCmd.split("cmd;");
consoleWriter.write(cmd[1]);
clearCmd();
return;
}
if (inputCmd.startsWith("bcast;")) {
String[] msg = inputCmd.split("bcast;");
consoleWriter.write("broadcast " + msg[1]);
clearCmd();
return;
}
if (inputCmd.startsWith("appnd;")) {
String[] msg = inputCmd.split("appnd;");
jTextPane1.setText(jTextPane1.getText() + "\n[BUKKITUI] " + msg[1]);
clearCmd();
return;
}
if (inputCmd.equals("--h")) { showHelp(); clearCmd(); return; }
consoleWriter.write("say " + inputCmd);
clearCmd();
}
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
Any help with this matter is greatly appreciated.

Related

How can i stop the groupMonitor.run method from crashing my ScheduledExecutorService?

groupMonitor.run("", "") is listening via IP Network to some electrical components.
The problem: is that all 5-6 hours groupMonitor.run("", "") crashes and needs to be called again. Quickly said: groupMonitor.run("", "") has to listen all the time via IP Network.
Another problem is: when groupMonitor.run("", "") crashes it prints all 100ms "redo groupMonitor ..." and is spaming my network so heavily that my IP Gateway (which accepts the connections) gets stuck and refuses all future incoming requests
This is the minimied main so to say
GroupMonitorOrig groupMonitor = new GroupMonitorOrig();
//when new groupMonitor is created the boolean MonitorExited is initialized with true
while (true) {
if (groupMonitor.monitorExited) { //this part gets executed when groupMonitor.run("", "") method has "crashed"
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
System.out.println("redo groupMonitor ... ");
groupMonitor.run("192.168.1.7", 2169);
} catch (Exception ex) {
}
}
};
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleAtFixedRate(runnable, 0, 100, TimeUnit.MILLISECONDS);
}
try {
TimeUnit.SECONDS.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
This is groupmonitor's run function
public void run(String remoteHost, int port) {
final InetSocketAddress remote = new InetSocketAddress(remoteHost, port);
try (KNXNetworkLink knxLink = KNXNetworkLinkIP.newTunnelingLink(null, remote, false, TPSettings.TP1);
ProcessCommunicator pc = new ProcessCommunicatorImpl(knxLink)) {
// start listening to group notifications using a process listener
pc.addProcessListener(this);
System.out.println("Monitoring network using net/IP server " + remoteHost + " ...");
while (knxLink.isOpen()) {
Thread.sleep(1000);
}
monitorExited = false;
pc.detach();
} catch (final KNXException | InterruptedException | RuntimeException e) {
System.err.println(e);
monitorExited = true;
}
}
I can't test run but can you try below -
The while(true) can be avoided
GroupMonitorOrig groupMonitor = new GroupMonitorOrig();
//when new groupMonitor is created the boolean MonitorExited is initialized with true
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
if (groupMonitor.monitorExited) {
System.out.println("starting new groupMonitor ... ");
groupMonitor.run("192.168.1.7", 2169);
}
} catch (Exception ex) {
System.err.println("Error in Runnable - " + ex.getMessage());
}
}
};
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleAtFixedRate(runnable, 0, 100, TimeUnit.MILLISECONDS);
public void run(String remoteHost, int port) {
monitorExited = false;
final InetSocketAddress remote = new InetSocketAddress(remoteHost, port);
KNXNetworkLink knxLink = null;
ProcessCommunicator pc = null;
try {
knxLink = KNXNetworkLinkIP.newTunnelingLink(null, remote, false, TPSettings.TP1);
pc = new ProcessCommunicatorImpl(knxLink);
pc.addProcessListener(this);
System.out.println("Monitoring network using net/IP server " + remoteHost + " ...");
while (knxLink.isOpen()) {
Thread.sleep(1000);
}
safeDetach(pc);
safeClose(knxLink);
} catch (final KNXException | InterruptedException | RuntimeException e) {
System.err.println("Error in checking liveliness - " + e.getMessage());
safeDetach(pc);
safeClose(knxLink);
}
monitorExited = true;
}
private void safeDetach(ProcessCommunicator pc) {
try {
if (pc != null) pc.detach();
} catch (Exception e) {
System.err.println("Could not safely detach pc - " + e.getMessage());
}
}
private void safeClose(KNXNetworkLink knxLink) {
try {
if (knxLink != null) knxLink.close();
} catch (Exception e) {
System.err.println("Could not safely close link - " + e.getMessage());
}
}

create a java server socket that waits for messages from client using Thread Pool

#FXML
private TextArea textarea;
#FXML
private ImageView imagev;
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
Serverth Server = new Serverth();
Server.start();
}
class Serverth extends Thread {
#Override
public void run() {
try {
final int NUM_THREAD = 99;
ServerSocket socket = new ServerSocket(8078);
ExecutorService exec = Executors.newFixedThreadPool(NUM_THREAD);
System.out.println("SERVER SOCKET CREATED");
while (!isInterrupted()) {
Socket in = socket.accept();
Runnable r = new ThreadedHandler(in);
exec.execute(r);
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
class ThreadedHandler implements Runnable {
private Socket incoming;
public ThreadedHandler(Socket in) {
incoming = in;
}
public void run() {
try {
try {
ObjectInputStream is=new ObjectInputStream(incoming.getInputStream());
while(true) {
if (is.available() > 0) {
String line = is.readUTF();
textarea.appendText("\n" + "[" + new java.util.Date() + "] : " + line);
if (line.contains("inviato")) {
Object obj = is.readObject();
Email ema = (Email) obj;
try {
SimpleDateFormat formatter = new SimpleDateFormat("dd-M-yyyy-hh-mm-ss");
FileOutputStream fileOut = new FileOutputStream("src/Server/" + ((Email) obj).getDestinat() + "/" + formatter.format(((Email) obj).getData()) + ".txt");
ObjectOutputStream objectOut = new ObjectOutputStream(fileOut);
objectOut.writeObject(ema);
objectOut.flush();
objectOut.close();
System.out.println("The Object was succesfully written to a file");
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
} catch(IOException ex) {
ex.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
incoming.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
Inside the run method (in Serveth class), I create a server socket and call exec.execute method.
Inside the run method (in ThreadedHandler class), the server is waiting for messages from the client (in this specific case, it creates a new .txt file but it is not important).
Everything works but causes excessive use of the CPU and lag!!!
InputSteam.available method returns a value instantly, telling you no bytes are available to be read, so this code runs a very "hot" spin loop:
while(true) {
if (is.available() > 0) {
...
}
}
The available method is rarely useful and often gives confusing results (see for example inputstream.available() is 0 always). I would suggest you get rid of the if statement altogether:
while(true) {
String line = is.readUTF();
textarea.appendText("\n" + "[" + new java.util.Date() + "] : " + line);
...
}
There's no way for this your code to exit the loop normally. You may want to add a mechanism for the client to disconnect from the server.

Using addShutdownHook in java

I want to do following operation in ordered wise
1. Stop jetty server
2. Delete used resource from jetty
3. Restart jetty server.
I have done this above using shutdownhook in java as below :
<code>
Thread restartThread = new Thread(){
public void run(){
try {
sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String osName = System.getProperty("os.name");
logger.debug("OS name:" + osName);
if (osName != null
&& osName.toUpperCase().startsWith("WINDOWS")) {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try {
List<String> cmdLine = new ArrayList<String>();
cmdLine.add("cmd.exe");
cmdLine.add("/C");
cmdLine.add("start");
cmdLine.add("\"\"");
cmdLine.add(getBaseDir() + File.separator + "restart.bat");
final ProcessBuilder pb = new ProcessBuilder(cmdLine);
Process process = pb.start();
if (process.exitValue() == 0) {
// after stopping server delete stores
deleteCertificates();
// restores files
restoreFiles(tmpdir, backupfilelist);
}
//p.waitFor();
} catch (IOException e) {
logger.error("Failed to restart:" + e.getMessage(), e);
}
}
});
System.exit(0);
} else {
try {
Runtime.getRuntime().exec("service appservice restart");
} catch (IOException e) {
logger.error("Failed to restart:" + e.getMessage(), e);
}
}
}
};
restartThread.start();
<code>
my concern is will it do it sequentially execution, otherwise application will fail to restore.

Launch java program in eclipse plugin failed

I try to launch a java program in a eclipse plugin, but failed.
What I try to do is to let the example from "Contribution to eclipse" to work.
In the example, the plugin contribute an menu item to eclipse,
when you select a test class, you can use the menu to run test cases in the class.
To run the test case, there are two class TestRunner and SocketTestRunner.
TestRunner launch the SocketTestRunner as a seperate java program, and communicate
through socket.
Code of TestRunner related to launch java program:
final String MAIN_CLASS = "org.eclipse.contribution.junit.SocketTestRunner";
public TestRunner() {
}
public void run(IType type) throws CoreException {
project = type.getJavaProject();
run(new IType[] { type });
}
public void run(IType[] classes) throws CoreException {
IVMInstall vmInstall = JavaRuntime.getVMInstall(project);
if (vmInstall == null)
vmInstall = JavaRuntime.getDefaultVMInstall();
if (vmInstall == null)
return;
IVMRunner vmRunner = vmInstall.getVMRunner(ILaunchManager.RUN_MODE);
if (vmRunner == null)
return;
String[] classPath = computeClasspath();
// prepare arguments:
// Argument[0] = port
// Argument[1-n] = types
port = SocketUtil.findFreePort();
String[] args = new String[classes.length + 1];
args[0] = Integer.toString(port);
for (int i = 0; i < classes.length; i++) {
args[1 + i] = classes[i].getFullyQualifiedName();
}
VMRunnerConfiguration vmConfig = new VMRunnerConfiguration(MAIN_CLASS,
classPath);
vmConfig.setProgramArguments(args);
ILaunch launch = new Launch(null, ILaunchManager.RUN_MODE, null);
vmRunner.run(vmConfig, launch, null);
connect();
}
Code of SocketTestRunner:
public static void main(String[] args) {
try {
logger = new PrintWriter(new FileWriter("log.txt"), true);
logger.println("main");
for (int i = 0; i < args.length; i++) {
logger.println(args[i]);
}
new SocketTestRunner().runTests(args);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (logger != null) {
logger.close();
}
}
}
private void runTests(String[] args) {
port = Integer.parseInt(args[0]);
logger.println("port: " + port);
openClientSocket();
try {
logger.println("Befor new TestSuite");
TestSuite suite = new TestSuite();
for (int i = 1; i < args.length; i++) {
logger.println("add TestSuite");
suite.addTestSuite(Class.forName(args[i]).asSubclass(TestCase.class));
}
logger.println("starting tests " + suite.countTestCases());
//writer.println("starting tests " + suite.countTestCases());
logger.println("Before TestResult");
TestResult result = new TestResult();
logger.println("After TestResult");
result.addListener(this);
suite.run(result);
//writer.println("ending tests ");
logger.println("ending tests ");
} catch (Exception e) {
logger.println("exception: " + e.getMessage());
logger.println(e.toString());
e.printStackTrace(logger);
e.printStackTrace();
} finally {
closeClientSocket();
}
}
private void closeClientSocket() {
logger.println("closeClientSocket");
if (writer != null) {
writer.close();
}
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void openClientSocket() {
logger.println("openClientSocket");
try {
socket = new Socket("localhost", port);
writer = new PrintWriter(socket.getOutputStream(), true);
return;
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
When I test in eclipse(3.6.0 HELIOS), I create a simple JUnit test case in runtime eclipse,
select the test class and click the menu item in context menu,
then the runtime eclipse will not response any further interaction,
let the ServerSocket still keep listening, and no test log I add for debug.
And I can get the command line which eclipse used to launch the SocketTestRunner:
"C:\Program Files\Java\jre6\bin\javaw.exe" -classpath C:\Users\User\workspace\org.eclipse.contribution.junit\bin;C:\Users\User\workspace\org.eclipse.contribution.junit\plugins\org.eclipse.contribution.junit_1.0.0.201009102354.jar;C:\Users\User\runtime-EclipseApplication\Hello\bin;C:\Users\User\workspace\org.junit\junit.jar;"C:\Program Files\eclipse\plugins\org.hamcrest.core_1.1.0.v20090501071000.jar" org.eclipse.contribution.junit.SocketTestRunner 41872 org.eclipse.contribution.hello.HelloTest
When I use this command manually, I can run the test case succeed(after comments the socket related writer), as I can get test log.
main
41872
org.eclipse.contribution.hello.HelloTest
port: 41872
openClientSocket
Befor new TestSuite
add TestSuite
starting tests 1
Before TestResult
After TestResult
starting test testSayHi(org.eclipse.contribution.hello.HelloTest)
failing test testSayHi(org.eclipse.contribution.hello.HelloTest)
END TRACE
ending tests
closeClientSocket
Any advise will be appreciated, Thanks.
Finally I get this plugin to run.
You should set working directory.
vmConfig.setWorkingDirectory("C:\\Users\\User");
When I try to get working directory, I get null.
You can't set breakpoint at the line which invoke connect() function.
private void connect() {
try {
ServerSocket server = new ServerSocket(port);
try {
Socket socket = server.accept();
try {
readMessage(socket);
} finally {
socket.close();
}
} finally {
server.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
But I don't know why, any advise will be appreciated.
You can, but the problem arise just before the connect method is called. So the plugin hooks before connect is called waiting for SocketTestRunner is launched.

Sign in button has no visible effect in a Java application

I have two applications, one is a server and the other is a client. At first, I run my server application. Then I will run the client application. When running the client application, a window will be shown to prompt for a username and password and if they were correct, another window will be shown. When I click on the “Sign In” button, nothing happens. What's wrong?
Main class in Server application:
public static void main(String[] args) {
System.out.println("Server is starting...");
ServerSocket server = null;
try {
server = new ServerSocket(5000);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Server is listening...");
while (true) {
try {
Socket socket = server.accept();
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Client Connected...");
}
}
Client class which has a socket in it:
private static InformationClass info = new InformationClass();
private static Socket c;
static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
/**
* #param args the command line arguments
*/
public static void runAClient() {
try {
c = new Socket("localhost", 5000);
} catch (UnknownHostException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void clienT(){
try {
BufferedReader read = new BufferedReader(new InputStreamReader(c.getInputStream()));
BufferedWriter write = new BufferedWriter(new OutputStreamWriter(c.getOutputStream()));
while (true) {
String string = reader.readLine();
write.write(string, 0, string.length());
write.newLine();
write.flush();
System.out.println(read.readLine());
}
} catch (Exception e) {
System.err.println(e);
}
}
public static boolean connected() {
boolean bool = false;
if (c.isConnected()) {
info.setSituation("Connected");
bool = true;
} else {
info.setSituation("disconnected");
bool = false;
}
return bool;
}
The main window in the client application, which I start after when I run the server application. A part of that is for the “Sign In” button.
private void submit() {
String id = idField.getText();
char[] pass1 = passField.getPassword();
String pass = new String(pass1);
if (id.equals("") || pass.equals("")) {
ErrorFrame frame = new ErrorFrame();
frame.setVisible(true);
} else {
boolean b = Manager.Test(id, pass);
if (b == true) {
Main.runAClient();
boolean boOl = Main.connected();
if(boOl==true){
this.setVisible(false);
ListFrame fRAme = new ListFrame(client);
fRAme.setVisible(true);
}
else{
JOptionPane.showConfirmDialog(this, "You couldn't connect successfully,please try again!","sign_In Problem",JOptionPane.ERROR_MESSAGE);
return;
}
} else {
JOptionPane.showConfirmDialog(this, "You have entered wrong datas,try it again");
return;
}
}
}
Have you tried stepping through your code using a debugger to work out precisely which line of code is not working correctly? Simply stating that "nothing happens" when you click on the sign-in button doesn't give us much to go on.
Are you sure your submit() method is called when you click 'Sign In' button?
Another thing, Main.RunAClient() never returns constantly asking user to enter a line in system console.

Categories