I want to execute a command with the terminal in linux. Now in order to do this I can't hard code cmd like I do windows. How do I get the terminal name programatically as String from java?
new ProcessBuilder(new String[] {"xfce4-terminal", "--title="+windowTitle, "--hold", "-x", "java", "-jar", decodedPath, "run"}).start();
Notice the string "xfce4-terminal". This changes depending on what distribution of linux they have. What reliable way is there to get the terminal exe for java commands. In my opinion it should by System.getProperty("os.terminal") but, that doesn't exist.
here is a cross platform way to determine the os terminal. supports windows, mac and linux
public static String osName = System.getProperty("os.name");
public static String[] windows_terminals = new String[]
{
"cmd",
"powershell",//seems to freak out and seems to be beta even in 2020 with all it's bugs
};
public static String[] mac_terminals = new String[]
{
"bin/bash"
};
public static String[] linux_terminals = new String[]
{
"/usr/bin/gcm-calibrate",
"/usr/bin/gnome-terminal",
"/usr/bin/mosh-client",
"/usr/bin/mosh-server",
"/usr/bin/mrxvt",
"/usr/bin/mrxvt-full",
"/usr/bin/roxterm",
"/usr/bin/rxvt-unicode",
"/usr/bin/urxvt",
"/usr/bin/urxvtd",
"/usr/bin/vinagre",
"/usr/bin/x-terminal-emulator",
"/usr/bin/xfce4-terminal",
"/usr/bin/xterm",
"/usr/bin/aterm",
"/usr/bin/guake",
"/usr/bin/Kuake",
"/usr/bin/rxvt",
"/usr/bin/rxvt-unicode",
"/usr/bin/Terminator",
"/usr/bin/Terminology",
"/usr/bin/tilda",
"/usr/bin/wterm",
"/usr/bin/Yakuake",
"/usr/bin/Eterm",
"/usr/bin/gnome-terminal.wrapper",
"/usr/bin/koi8rxterm",
"/usr/bin/konsole",
"/usr/bin/lxterm",
"/usr/bin/mlterm",
"/usr/bin/mrxvt-full",
"/usr/bin/roxterm",
"/usr/bin/rxvt-xpm",
"/usr/bin/rxvt-xterm",
"/usr/bin/urxvt",
"/usr/bin/uxterm",
"/usr/bin/xfce4-terminal.wrapper",
"/usr/bin/xterm",
"/usr/bin/xvt"
};
public static String getTerminal()
{
String[] cmds = getTerminals(osName);
for(String cmd : cmds)
{
try
{
Runtime.getRuntime().exec(cmd + " cd " + System.getProperty("user.dir"));
return cmd;
}
catch (Throwable e) {}
}
return null;
}
public static String[] getTerminals(String os)
{
return os.contains("windows") ? windows_terminals : os.contains("mac") ? mac_terminals : os.contains("linux") ? linux_terminals : null;
}
Related
I have two options (-n and -t) under a command where if -n is used, then -t is required, but bothare not required. However, I keep getting an error about
I am trying to send the options as a parameter to another method (with business logic) as a parameter.
Valid Usage:
agent.bat install -n -t <blahblah>
agent.bat install -t <blahblah> -n
agent.bat install -t <blah blah>
agent.bat install -t <----This is on interactive so it would ask for a parameter later
Invalid Usage:
agent.bat install -n
agent.bat install -n -t
Current output with valid usage:
agent.bat install -t
Missing required parameter: '<arg0>'
Usage: agent install [-hV] <arg0>
Setup or update the agent service program by install token.
<arg0>
public class Agent implements Callable<Integer> {
static class InstallArgs {
#Option(names = {"-t", "--token"},
order = 0,
arity = "0..1",
interactive = true,
description = "The agent install token.",
required = true) String installToken ;
#Option(names = {"-n", "--noninteractive"},
order = 1,
description = "Sets installation to non-interactive",
required = false) boolean nonInteractive ;
public String toString() {
return String.format("%s,%s", installToken, nonInteractive);
}
}
private static String[] programArgs;
#ArgGroup(exclusive = false, multiplicity = "1")
#CommandLine.Command(name = AgentCommand.INSTALL_COMMAND, mixinStandardHelpOptions = true,
description = "Setup or update the agent service program by install token.")
void install(InstallArgs installArgs) {
String[] installArgsValues = installArgs.toString().split(",");
String installToken = installArgsValues[0];
boolean nonInteractive = Boolean.parseBoolean(installArgsValues[1]);
IcbProgram.initProgramMode(ProgramMode.INSTALL);
MainService mainService = MainService.createInstallInstance(configFile, agentUserFile, backupAgentUserFile, installToken, nonInteractive);
}
public static void main(String... args) {
if (ArgumentValidator.validateArgument(args)) {
programArgs = args;
int exitCode = new CommandLine(new Agent()).execute(args);
System.exit(exitCode);
} else
//Exit with usage error
System.exit(ExitCode.USAGE);
}
}
Can you try using arity=1 for installToken?
static class InstallArgs {
#Option(names = {"-t", "--token"},
order = 0,
arity = "1",
interactive = true,
description = "The agent install token.",
required = true) String installToken ;
When I pass arguments to my program to be parsed by the CommandLineParser, it doesn't take my arguments from passed to the main method.
The code:
public class Main {
private static final Option ARG_HELP = new Option("h", "help", false, "HELP - Prints command line arguments and their uses");
private static final Option ARG_SERVER = new Option("s", "server", true, "SERVER_URL - Full HTTP(s) url of the server");
private static final Option ARG_USER = new Option("u", "user", true, "USERNAME - Username used for authentication");
private static final Option ARG_PASSWORD = new Option("p", "password", true, "PASSWORD - Password used for authentication");
private static final Option ARG_TARGET = new Option("t", "target", true, "TARGET_DIR - Base directory used for pushing or pulling files");
private static final Option ARG_PUSH = new Option("push", "push", false, "PUSH - Push xml config to server");
private static final Option ARG_PULL = new Option("pull", "pull", false, "PULL - pull xml config from server");
public static void main(String[] args) {
CommandLineParser clp = new DefaultParser();
Options options = new Options();
options.addOption(ARG_HELP);
options.addOption(ARG_SERVER);
options.addOption(ARG_USER);
options.addOption(ARG_PASSWORD);
options.addOption(ARG_TARGET);
options.addOption(ARG_PUSH);
options.addOption(ARG_PULL);
try{
CommandLine cl = clp.parse(options, args);
if(cl.getArgList().size() < 5){
ArrayList<String> arguments = new ArrayList<String>(cl.getArgList());
}
else{
printHelp(options);
System.exit(0);
}
}
catch(Exception e){
e.printStackTrace();
}
finally{
System.exit(0);
}
}
When I set a breakpoint at the if statement and check my cl object, the args are 0. But when I look at args passed in the clp.parse(options, args) method they're the arguments that I passed when I ran the program.
Example arguments passed: -s https://localhost:8443 -u admin -p admin -t C:\users\admin -pull
That is the correct behaviour.
According to the CommandLine.getArgList() JavaDoc:
Retrieve any left-over non-recognized options and arguments
Since all the arguments from your command line are recognized as options and arguments there are no left-over arguments.
I would like to provide a search string for my program like:
cmd.execute("getDevices", "-h 1.2.3.4", "-p myPSW", "-u myUser", "-n red|blue&black,-nonprod");
I want to create predicates to search for hostNames that contain red OR blue AND Black, but NOT nonprod. It is unclear to me how to go about parsing this the logical operators along with the Strings in Picocli to create a Predicate. Is there a simple and Straight forward way to parse a String to a predicate?
My CLI is set up as follows:
#Command(name = "HostMagicCLI", mixinStandardHelpOptions = true,
version = "1.0",
description = "Do Stuff With Hosts"
,
subcommands = {TufinDevices.class}
)
public class HostMagicCLI implements Runnable {
public static void main(String[] args) {
CommandLine cmd = new CommandLine(new InterfaceMagicCLI());
cmd.setExecutionStrategy(new RunAll());
cmd.getHelpSectionMap().put(SECTION_KEY_COMMAND_LIST, new MyCommandListRenderer());
cmd.usage(System.out);
cmd.execute("getDevices", "-h1.2.3.4", "-p myPSW", "-u myUser", "-n red|blue&black");
}
#Override
public void run() {
System.out.println("Running..");
}
}
#Command(name = "getDevices", aliases = {"l"}, description = "SpecifyTufin Credentials", subcommands = {InterfaceCommand.class})
class TufinDevices implements Runnable {
.
.//Options to collect user,psw, host etc.
.
#CommandLine.Option(names = {"-n", "--n"}, split = ",", arity = "0..*", description = "Hostname Contains")
String[] hostNameContains;
private void filter(TufinDeviceCollection<TufinDevice> devices) {
if (hostNameContains != null) {
Predicate< ? super TufinDevice> deviceFilter = device -> Arrays.stream(hostNameContains)
.allMatch(input -> device.getHostName().toLowerCase().contains(input.toLowerCase()));
devices = devices.stream()
.sequential()
.filter(deviceFilter)
.collect(Collectors.toCollection(TufinDeviceCollection<TufinDevice>::new));
}
#Override
public void run() {
try {
TufinDeviceCollection<TufinDevice> FETCH_DEVICES = Tufin.FETCH_DEVICES(user.trim(), password.trim(), hostName.trim());
this.filter(FETCH_DEVICES);
} catch (IOException | NoSuchAlgorithmException | KeyManagementException | IPConverter.InvalidIPException ex) {
Logger.getLogger(TufinDevices.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
I suspect you may want to use a library for parsing the string that the end user specifies as the filter expression (the -n parameter). It may be an idea to look at libraries like Spring Expression Language, OGNL, JXPath, there may be others. Alternatively, if it is easy to write such a filter in Groovy or BeanShell, these languages can be called from Java, so you can call that filter from the Java command.
CAUTION:
I notice the example passes parameter to the picocli parser like this:
cmd.execute("getDevices", "-h 1.2.3.4", "-p myPSW", "-u myUser", "-n red|blue&black,-nonprod");
This will probably give an error explaining that "there is no -p myPSW option defined".
In your testing, if you call the execute method directly, make sure to pass parameters separately like this:
cmd.execute("getDevices", "-h", "1.2.3.4", "-p", "myPSW", "-u", "myUser", "-n", "red|blue&black,-nonprod");
The Java app I am developing is an internal tool for others to use to help our daily activities. When the tool is used (on a JButton press which calls the code below) I want it to open a new Outlook EMail for the user to see/edit.
At first I was developing this app in a 64 bit Eclipse and could not get SWT to open Outlook despite all my research. After I had some issues running 64bit versus 32bit SWT, I had the idea to check Outlook, and sure enough the company using is 32 bit. I loaded up a 32 bit eclipse, imported my project, switch SWT to 32 bit and it worked exactly as intended.
I noticed the process that was running was javaw.exe*32 but the 64bit Eclipse was using the process javaw.exe. I exported the JAR from the 32bit Eclipse and gave it a shot and no EMail showed up. I checked the JRE's installed and saw both 32bit and 64bit but my company had a policy that forced only the 64bit JRE in the Java Control Panel. I worked with some others and got both installed and enabled as seen here. Still the JAR fails to open the EMail. I even tried disabling the 64bit and it still does not work.
Is there anything that can be done to remedy this situation? Please let me know if I can elaborate better or provide more info!
package EDM_PKG;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.ole.win32.OLE;
import org.eclipse.swt.ole.win32.OleAutomation;
import org.eclipse.swt.ole.win32.OleClientSite;
import org.eclipse.swt.ole.win32.OleFrame;
import org.eclipse.swt.ole.win32.Variant;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class CreateEmail {
private static Display display = new Display();
public static void sendEMail(String env) {
//String currUser = System.getProperty("user.name");
String msg = getMessage(env);
String sub = getSubject(env);
Shell shell = new Shell(display);
OleFrame frame = new OleFrame(shell, SWT.NONE);
// This should start outlook if it is not running yet
//OleClientSite site = new OleClientSite(frame, SWT.NONE,"OVCtl.OVCtl");
//site.doVerb(OLE.OLEIVERB_INPLACEACTIVATE);
// Now get the outlook application
OleClientSite site2 = new OleClientSite(frame, SWT.NONE, "Outlook.Application");
OleAutomation outlook = new OleAutomation(site2);
OleAutomation mail = invoke(outlook, "CreateItem", 0 /* Mail item */).getAutomation();
setProperty(mail, "BodyFormat", 2 /* HTML */);
setProperty(mail, "Subject", sub);
setProperty(mail, "To", "example#gmail.com");
setProperty(mail, "HtmlBody", msg);
invoke(mail, "Display" /* or "Send" */);
display = null;
}
private static String getMessage(String env) {
String msg = "";
if (env.equalsIgnoreCase("quas")) {
msg = "<html><body>The <b>USER</b> excel has been migrated to <b>QUAS.</b><br><br> This email was generated by Excel Datatable Migrator.</body></html>";
} else if (env.equalsIgnoreCase("prod")) {
msg = "<html><body>The <b>QUAS</b> excel has been migrated to <b>PROD.</b><br><br>This email was generated by Excel Datatable Migrator.</body></html>";
} else {
msg = "Somthing happened with the automated message of EDM. Please contact the user with the eCode: "+System.getProperty("user.name")+".</body></html>";
}
return msg;
}
private static String getSubject(String env) {
String sub = "";
if (env.equalsIgnoreCase("quas")) {
sub = "EDM has been used to move USER to QUAS...";
} else if (env.equalsIgnoreCase("prod")) {
sub = "EDM has been used to move QUAS to PROD...";
} else {
sub = "Somthing didnt quite work right...";
}
return sub;
}
private static OleAutomation getProperty(OleAutomation auto, String name) {
Variant varResult = auto.getProperty(property(auto, name));
if (varResult != null && varResult.getType() != OLE.VT_EMPTY) {
OleAutomation result = varResult.getAutomation();
varResult.dispose();
return result;
}
return null;
}
private static Variant invoke(OleAutomation auto, String command,
String value) {
return auto.invoke(property(auto, command),
new Variant[] { new Variant(value) });
}
private static Variant invoke(OleAutomation auto, String command) {
return auto.invoke(property(auto, command));
}
private static Variant invoke(OleAutomation auto, String command, int value) {
return auto.invoke(property(auto, command),
new Variant[] { new Variant(value) });
}
private static boolean setProperty(OleAutomation auto, String name,
String value) {
return auto.setProperty(property(auto, name), new Variant(value));
}
private static boolean setProperty(OleAutomation auto, String name,
int value) {
return auto.setProperty(property(auto, name), new Variant(value));
}
private static int property(OleAutomation auto, String name) {
return auto.getIDsOfNames(new String[] { name })[0];
}
}
There's no need to use the heavyweight and difficult to use Ole classes.
If all you want is to send an email, just call this:
Program.launch("mailto:bla#blubb.com&subject=Subject&body=Message here");
This will work on all architectures and operating systems.
I am trying to write an app to use Files.find method in it.
Below program works perfectly :
package ehsan;
/* I have removed imports for code brevity */
public class Main {
public static void main(String[] args) throws IOException {
Path p = Paths.get("/home/ehsan");
final int maxDepth = 10;
Stream<Path> matches = Files.find(p,maxDepth,(path, basicFileAttributes) -> String.valueOf(path).endsWith(".txt"));
matches.map(path -> path.getFileName()).forEach(System.out::println);
}
}
This works fine and gives me a list of files ending with .txt ( aka text files ) :
hello.txt
...
But below program does not show anything :
package ehsan;
public class Main {
public static void main(String[] args) throws IOException {
Path p = Paths.get("/home/ehsan");
final int maxDepth = 10;
Stream<Path> matches = Files.find(p,maxDepth,(path, basicFileAttributes) -> path.getFileName().equals("workspace"));
matches.map(path -> path.getFileName()).forEach(System.out::println);
}
}
But it does not show anything :(
Here is my home folder hiearchy (ls result) :
blog Projects
Desktop Public
Documents Templates
Downloads The.Purge.Election.Year.2016.HC.1080p.HDrip.ShAaNiG.mkv
IdeaProjects The.Purge.Election.Year.2016.HC.1080p.HDrip.ShAaNiG.mkv.aria2
Music Videos
Pictures workspace
So whats going wrong with path.getFileName().equals("workspace")?
Path.getFilename() does not return a String, but a Path object, do this:
getFilename().toString().equals("workspace")
Use the following and look at the console. Maybe none of your files contains workspace in it
Files.find(p,maxDepth,(path, basicFileAttributes) -> {
if (String.valueOf(path).equals("workspace")) {
System.out.println("FOUND : " + path);
return true;
}
System.out.println("\tNOT VALID : " + path);
return false;
});