I need some coding advice. I've written a simple Java program which runs within one of my company's internal websites. Its a command line program where users enter commands like copy file1 to remote1 and compare file1 to file2 archive diff and so on. My colleagues like it and use it frequently.
The problem is the users' commands tend to be long and repetitive. They have asked me if it is possible to implement a command history in the program. This way, they can use the up arrow or something to scroll through, edit, and resubmit previous commands. There's no need to remember commands entered in previous sessions, only the current session.
I've thought about it, and I think I could come up with a solution from scratch... but it would take a few weeks to develop. I'd much rather implement an available package or module, if one exists and isn't too much trouble. I know this is an open-ended question, but can anyone recommend such a resource?
I don't see why it should take so long to develop. Here's a rudimentary solution:
class CommandSession {
private List<Command> commands = new ArrayList<>();
private ListIterator<Command> scroller;
public void execute(Command command) {
scroller = null;
commands.add(command);
command.execute();
}
public Command scrollUp() {
if (scroller == null) {
scroller = commands.listIterator(commands.size());
}
if (scroller.hasPrevious()) {
return scroller.previous();
}
return null;
}
}
You could tweak this in various ways for more advanced functionality, but overall it's a pretty basic concept.
if you are using a *nix environment then rlwrap may be what's you're looking for.
rlwrap tries to be completely transparent - you (or your shell) shouldn't notice any difference between command and rlwrap command -
except the added readline functionality, of course. This should even
hold true when you are re-directing, piping and sending signals from
and to command, or when command manipulates its terminal settings.
There are many options to add (programmable) completion, handle
multi-line input, colour and re-write prompts. If you don't need them
(and you probably don't), you can skip the rest of this manpage.
if not, you can use cygwin to be able to use it
I've used CRaSH in my project. It's basically a SSH shell that the user is expected to connect to (supports username/password too) and yes, supports history in commands. Commands are written in Groovy.
Related
So I asked this question concerning how to combine 3 different applications into 1 Combining Processing Applications into 1 Big Executable?
From lurking I have learned the following methods I could go about to do this:
use Java and embed my sketches in a Swing interface (rewrite
programs into some complicated Java monstrosity)
Rewitre code to launch separate windows using G4P
http://www.lagers.org.uk/g4p/ex-windows/index.html (seems better
than option 1 but still a pain in the ass because trying to write
functions to get the LEAP motion api calls to work in the separate
windows wont be easy)
Use Open() at the end of each program to run
the next program (quick and dirty, just the way I like it!)
Combine all 3 into a batch file. (I dont really understand how to go about doing this but seems similar to previous option).
Now theoretically I could get more functionality from 1 and 2 (in terms of program flow and better user interface) and would probably learn more and be better off in my future efforts, however time is of the essence at the moment. Each of the programs creates csv data files from user input that I will use to create a visualization so the manner in which I get the programs to run is somewhat irrelevant at this point. Only problem is I cant get open() to work correctly. See below:
void setup() {
size(200, 200);
}
void draw() {
// draw() must be present for mousePressed() to work
}
void mousePressed() {
open("C:/Users/corbett2/Documents/Processing/test/application.windows64/test.bat"); //doesn't work
open(new String[] { "cmd", "/c", "start", "/w", "C:/Users/corbett2/Documents/Processing/test/application.windows64/test.bat"}); //also doesn't work
}
I've tried a bunch of different ways to use open() but it wont run the program. I'm using windows 8. I exported the application "test" which created the "test.bat" located in C:/Users/corbett2/Documents/Processing/test/application.windows64. I believe you have to export your sketch before you can try to use open() on it right? As said before, the idea here is to use a call to open() at the close of each of my 3 applications in order to run them.
So my specific questions are as follows:
Which of the 4 methods I listed would you recommend I pursue for my issue? If none, please feel free to suggest something else.
Will option 3 using open() work? Why or why not?
Correct my open() issue.
Thanks in advance!
When I export application it creates test.exe for windows32 bit architecture (but running on 64bit OS) and then using your second case of open() works fine for me:
void mousePressed() {
//open second window with test app running
open("C:/Users/corbett2/Documents/Processing/test/application.windows32/test.exe");
//this will close first window
exit();
}
[but this didn't work with export to 64bit architecture (for me) so your problem should be with some settings of platform's launcher]
Anyway this approach works fine just you also need to close first window so user will not be confused.
I have been on this for a while now, and for the past three days have ripped apart the Internet for ways to effectively clear the console in Java.
Ways I have seen it "done"
This way
for(int x = 0; x!=100; x++){
System.out.println();
} Sucks, as you can just scroll up and see the printed statements again.
Console.Clear(); and all variations of it, have not worked for me.
Runtime.getRuntime().exec("cls"); has not worked in any cases i have tried to use it in.
(I use JCreator to code, I have no idea if this has anything to do with my issue)
This way by joesumbody122, looked interesting:
private static void clearLine()
{
Console.Write(new string(' ', Console.BufferWidth - Console.CursorLeft));
}
and
private static void clearLine(int left, int top)
{
int pLeft = Console.CursorLeft;
int pTop = Console.CursorTop;
Console.setCursorPosition(left, top);
Console.Write(new string(' ', Console.BufferWidth - Console.CursorLeft));
Console.setCursorPosition(pLeft, pTop);
}
But sadly i could not get it to work for me. It gave me errors that all the methods that he called from Console did not exist. java.io.*; was imported His method clears one line specifically, so if someone could get this working, (Again, I use JCreator to code, I have no idea if this has anything to do with my issue) I could see it being looped to clear all the lines.
Ways to make less sucky?
Back to this for(int x = 0; x!=100; x++){
System.out.println();
} Is there a way to prevent the user from scrolling up in the command line? To set the cursor to the top left of the prompt? That would make this method a whole lot more useful.
Another Theory
Is there a way to simply tell java to stop printing in one command line, start printing in another, and close the window of the first so it only appears to have cleared the console, but instead created an entirely new one? I have pondered this the last two hours, and in theory it would work, but i don't know if the code to do so even exists.
There is no reliable way that works everywhere. You've already mostly discovered this.
Generally, command-line output goes into a terminal scrollback buffer, of which only the last n lines are displayed, but previous lines are available through a scrolling mechanism. A command-line program does not write directly to this buffer, but writes to stdout which is, in most cases, piped to the terminal process which then displays the data.
Some terminal programs (i.e. those supporting ANSI escapes) might let you clear the visible portion of the screen. As far as I know, only Windows' cmd.exe responds to a 'clear screen' request by clearing the entire scrollback buffer. On Linux AFAIK it's not possible to discard the buffer completely. And, on Windows, cls is not an executable command but a shell builtin, so you cannot run it from Java System.exec().
Also, any command-line program can have its output redirected to a file with out the program being aware of it, in which case 'clear screen' doesn't have much meaning.
If you MUST have this level of control then you will have to write your own display window using Swing, AWT or GWT or whatever and manage all interaction there.
If it's a command-line app and the terminal/shell you're running the app in supports ANSI escape codes then you can just do this:
System.out.print("\033[H\033[2J");
System.out.flush();
The answer depends on weather or not you are using Linux or Windows OS. If you are using linux and want to clear the console then try:
try {
new ProcessBuilder("/usr/bin/clear").inheritIO().start().waitFor();
} catch(Exception e) {}
If you are using windows try:
try {
new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();
} catch(Exception e) {}
You can handle the exception any way you want.It does not matter becasue you will not get one.
My Java application has to work like this:
User select bash commands in GUI and press "send."
Application return distinct and independent answers for each command
(e.g. we could store them in different files).
Commands each run interactively, not in a batch (it can't be
something like "ls\n pwd \n" etc)
After each command, the application will wait and check if the
results are ok. If so, it will send the next command.
We need to execute su on the remote host.
I've used ExpectJ (with a little hack of output stream). It has resolved points 1,3,4,5.
But there is a problem with point 2. In my app I need to get separated answer. But we will not know their length. Command prompts can be different. Anyone knows how to "hack" ExpectJ so it will be some how more synchronized? I am looking for acting like this : send , wait for full answer, send, wait... I've tried some basic synchronization tricks but this end in timeouts and connection lost usually.
This question is related to my older one :
Java library to run multiple unrelated commands on a remote server via ssh
the problem basically is that expectj sends and listens at the same time, buffering inputs and outputs in separate threads, so you have to know when the response has ended so you can delimit each request/response block. If you don't care about expect "interact" mode, you can try to hack expect4J, expect-for-java (https://github.com/ronniedong/Expect-for-Java) or even apache mina sshd.
I am facing exactly the same problem right now, and since I need interact(), I don't have any other option right now. So, this solution below is not elegant, but may do the job. Too bad we don't have a decent expect java implementation. I hope we will in java 8, when (I hope) we'll have closure.
ExpectJ ex = new ExpectJ(50);
Spawn spawn = ex.spawn(new SshSpawn("192.168.56.101", 22, "alice", "password"));
String command = "hostname -s;expr 123456788 + 1";
spawn.send(command+"\n");
spawn.expect("123456789");
String lsResults = spawn.getCurrentStandardOutContents().split("123456788 \\+ 1\r\n")[2].split("123456789")[0];
String[] lsRows = lsResults.split("\r\n");
for(int i=0;i<lsRows.length;i++){
System.out.println(i+":"+lsRows[i]);
}
I need to create a desktop application that will run third party code, and I need to avoid the third party code from export by any way (web, clipboard, file io) informations from the application.
Somethig like:
public class MyClass {
private String protectedData;
public void doThirdPartyTask() {
String unprotedtedData = unprotect(protectedData);
ThirdPartyClass.doTask(unprotectedData);
}
private String unprotect(String data) {
// ...
}
}
class ThirdPartyClass {
public static void doTask(String unprotectedData) {
// Do task using unprotected data.
// Malicious code may try to externalize the data.
}
}
I'm reading about SecurityManager and AccessControler, but I'm still not sure what's the best approach to handle this.
What should I read about to do this implementation?
First of all, there is pretty much no way you can stop every information leak on a local computer. You can certainly restrict network access, and even a lot of file system access, but there is nothing that would stop the gui from popping up a dialog showing the information to the user on the screen, or any other 100 ways you could "leak" data.
Secondly, you keep talking about the policy file being changeable by the user. yes, it is. it sounds like you are basically trying to recreate DRM. I'd suggest reading up on DRM and the general futility of it. It essentially boils down to giving someone a locked box and the key to the box and telling them not to open it. If someone has physical access to your program, there is almost nothing you can do to stop them from getting data out of it, in java or pretty much any other programming language (at least, not on computers as they are built today).
A general approach would be to run your jvm with a security policy that grants java.security.AllPermission to your codebase (i.e. jar) and no permissions whatsoever to the third-party codebase. Here is some documentation on how to run with a policy file and what to put in said file.
I'm not too familiar with Linux/Bash, so I can't really find the right terms to search for.
Take the snippet:
public class Main {
public static void main(String[] args) {
java.util.Scanner keyboard = new java.util.Scanner(System.in);
while(true) {
System.out.print("$ ");
String in = keyboard.nextLine();
if(in.equals("q")) break;
System.out.println(" "+in);
}
}
}
If I run it on my Linux box using Bash, I can't use any of the arrow buttons (I'm only interested in the left- and right button, btw). For example, if I type "test" and then try to go back by pressing the left button, ^[[D appears instead of my cursor going back one place:
$ test^[[D
I've tried the newer Console class as well, but the end result is the same. On Windows' cmd.exe shell, I don't have this problem.
So, the question is: is there a way to change my Java code so that I can use the arrow keys without Bash transforming them in sequences like ^[[D but actually move the cursor instead?
I'm hoping that I can solve this on a "programming level". If this is not possible, then I guess I'd better try my luck on Superuser to see if there's something I need to change on my Bash console.
Thanks in advance.
Bash is the shell, not the terminal; from your program you're talking to the terminal. To provide that functionality, bash and many other programs use readline - there appears to be a Java wrapper for it but I've never used it. I'm sure someone else will come along with a more definitive answer.
Another option would be a Java curses library.