I'm have a story where I need to supply the JSON config file path and a tool path and pass these two paths to the python script?
when I try to add a second path next to tool path it uses all the string after the path as path :/
is there a way how to supply two paths in 'Given'?
story looks like
Scenario: Verify Certificate and Cipher misconfiguration
Given TestSSL tool path 'C:\Users\Desktop\SSLTLS\testssl.sh-3.0'
Then Certificate and Cipher check should return 0 for successful security-check
java code
#Given("TestSSL tool path '$path'")
public void get_TestSSL_path(#Named("path") String path)
{
try
{
Paths.get(path);
toolPath = path;
}
catch (InvalidPathException | NullPointerException ex)
{
}
}
#Then("Certificate and Cipher check should return 0 for successful security-check")
public void verify_cipher_and_certificate_attributes() throws IOException, InterruptedException
{
String pythonFileName = "./scripts/python/security_misconfiguration_SSL_TLS.py";
String fullcmdCommand = jsonpath + " " + toolPath ;
System.out.println("Full path : " +fullcmdCommand);
int script_result = Utilities.runPythonScript(pythonFileName, fullcmdCommand);
Assert.assertEquals(0, script_result);
}
You should change the step input parameter to Collection, for example:
#Given("TestSSL tool paths '$paths'")
public void get_TestSSL_path(#Named("paths") List<String> paths)
...
Separate input data using comma, for example:
Given TestSSL tool paths 'C:\Users\Desktop\SSLTLS\testssl.sh-3.0, C:\Users\Desktop\SSLTLS\testssl.sh-4.0'
Related
I've made a class which takes in any string of one format (eg. UNIX) and coverts into whatever OS the java is running on.
enum OperatingSystem {
WINDOWS,
LINUX;
static OperatingSystem initOS() {
String osName = System.getProperty("os.name");
switch (osName) {
case "Windows 8.1":
return WINDOWS;
case "Linux":
return LINUX;
default:
return LINUX;
}
}
}
public class OSSP {
public static final OperatingSystem USEROS = OperatingSystem.initOS();
// Auxilarry methods to return OSAppropriateString
private static String makeLinuxCompatible(String[] path) {
return String.join("/", path);
}
private static String makeWindowsCompatible(String[] path) {
return String.join("\\", path);
}
public static String getOSSpecificPath(String path) {
String[] splittedPath = {""}, subpath = {""};
String finalPath = "";
if(path.contains("\\")) {
splittedPath = path.split("\\\\",-1);
}
else if (path.contains("/")) {
splittedPath = path.split("/",-1);
}
if (USEROS == OperatingSystem.LINUX) {
finalPath = makeLinuxCompatible(splittedPath);
}
else if (USEROS == OperatingSystem.WINDOWS) {
finalPath = makeWindowsCompatible(splittedPath);
}
return finalPath;
}
}
This is fine if you're working on small code and you'd have to do it often.
But, I have a huge GUI code where I'd have to insert this function wherever there is path specified in the program. Is there a way to make path like strings automatically OS specific?
Otherwise a setting where any OS function which takes a path automatically changes accordingly under the hood.
Use Path with Files.
Path path = Paths.get(".../...");
Path path = Paths.get("...", "...");
// path.resolve, relativize, normalize, getFileSystem
This class is a generalisation of File which is only for pure file system files.
A path might point in a subdirectory of a .zip using a zip file system and so on.
For established File using APIs one can use Path.toFile() and File.toPath().
Paths.get is very versatile, also due to the Posix compatibility of Windows (accepting / besides \). You can get a canonical normalized path anyway.
path.toRealPath()
The old File you can use:
String separator = File.separator;
For a path which can point to different file systems:
String separator = path.getFileSystem().getSeparator();
In general Path is a nifty class storing the name parts, the file system.
It covers many aspects like "..".
The best way to deal with this kind of situation is to not try to detect the OS since that can be rather hit-or-miss. Instead the Java API does provide a way to tell you what character to use as a path separator. Look at this API documentation on File: https://docs.oracle.com/javase/8/docs/api/java/io/File.html and look for the specific static field separator. I would highly suggest you parse the path using the File class then if you need the path as an string simply call toURI().toString() to get it into a format that the OS can recognize.
I have a problem extracting an archive to the desired category using Java 10 ProcessBuilder and 7z.exe (18.05) with command line. The exact same command works as intended when I use Windows CMD, but no longer functions when issued by my JavaFX application using ProcessBuilder:
public static void decompress7ZipEmbedded(File source, File destination) throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder(
getSevenZipExecutablePath(),
EXTRACT_WITH_FULL_PATHS_COMMAND,
quotifyPath(source.getAbsolutePath()),
OUTPUT_DIRECTORY_SWITCH + quotifyPath(destination.getAbsolutePath())
);
processWithSevenZipEmbedded(pb);
}
private static void processWithSevenZipEmbedded(ProcessBuilder pb) throws IOException, InterruptedException {
LOG.info("7-zip command issued: " + String.join(" ", pb.command()));
Process p = pb.start();
new Thread(new InputConsumer(p.getInputStream())).start();
System.out.println("Exited with: " + p.waitFor());
}
public static class InputConsumer implements Runnable {
private InputStream is;
InputConsumer(InputStream is) {
this.is = is;
}
#Override
public void run() {
try {
int value = -1;
while ((value = is.read()) != -1) {
System.out.print((char) value);
}
} catch (IOException exp) {
exp.printStackTrace();
}
LOG.debug("Output stream completed");
}
}
public static String getSevenZipExecutablePath() {
return FileUtil.quotifyPath(getDirectory() + "7z" + "/" + "7z");
}
public static String quotifyPath(String path) {
return '"' + path + '"';
}
public class Commands {
public static final String EXTRACT_COMMAND = "e";
public static final String EXTRACT_WITH_FULL_PATHS_COMMAND = "x";
public static final String PACK_COMMAND = "a";
public static final String DELETE_COMMAND = "d";
public static final String BENCHMARK_COMMAND = "b";
public static final String LIST_COMMAND = "l";
}
public class Switches {
public static final String OUTPUT_DIRECTORY_SWITCH = "-o";
public static final String RECURSIVE_SWITCH = "-r";
public static final String ASSUME_YES = "y";
}
The command looks like this:
"C:/Users/blood/java_projects/AppRack/target/classes/7z/7z" x "D:\Pulpit\AppRack Sandbox\test\something\Something 2\Something2.7z" -o"D:\Pulpit\AppRack Sandbox\Something2"
And the output from ProcessBuilder:
7-Zip 18.05 (x64) : Copyright (c) 1999-2018 Igor Pavlov : 2018-04-30
Scanning the drive for archives:
1 file, 59177077 bytes (57 MiB)
Extracting archive: D:\Pulpit\AppRack Sandbox\test\Something\Something 2\Something2.7z
--
Path = D:\Pulpit\AppRack Sandbox\test\Something\Something 2\Something2.7z
Type = 7z
Physical Size = 5917Exited with: 0
7077
Headers Size = 373
Method = LZMA2:26 LZMA:20 BCJ2
Solid = +
Blocks = 2
No files to process
Everything is Ok
Files: 0
Size: 0
Compressed: 59177077
It doesn't do ANYTHING. Doesn't create a desired folder, nothing. Using CMD it works like a charm (here log from Windows 10 CMD using the same command):
7-Zip 18.05 (x64) : Copyright (c) 1999-2018 Igor Pavlov : 2018-04-30
Scanning the drive for archives:
1 file, 59177077 bytes (57 MiB)
Extracting archive: D:\Pulpit\AppRack Sandbox\test\Something\Something 2\Something2.7z
--
Path = D:\Pulpit\AppRack Sandbox\test\Something\Something 2\Something2.7z
Type = 7z
Physical Size = 59177077
Headers Size = 373
Method = LZMA2:26 LZMA:20 BCJ2
Solid = +
Blocks = 2
Everything is Ok
Folders: 1
Files: 5
Size: 64838062
Compressed: 59177077
Do you have any idea what causes a difference here and why it says "No files to process, everything is ok" without doing anything? I've tried already to create a folder first using File class but it doesn't seem to be an issue because the results are the same whether the destination folder exists prior to extracting or not.
I've already tried everything that has come to my mind and I run out of ideas at the moment. Please share with me any suggestions that you may have regarding this issue. Thanks a lot.
Thank you very much for your help.
Don’t quote your arguments. Quotes are for the command shell’s benefit. ProcessBuilder is not a command shell; it executes a command directly, so any quotes are seen as part of the argument itself (that is, the file name). Also, pb.inheritIO(); is a better way to see the output of the child process than manually consuming process streams.
Thank you #VGR it seemed to be the issue - after I remove the method to quote paths in the mentioned command it works like a charm and extracting archive without any problem! So the conclusion is I shouldn't have used quotes in paths while using Java ProcessBuilder.
I've also used pb.inheritIO() and you are right it is much better and easier to manage it this way.
public static void decompress7ZipEmbedded(File source, File destination) throws IOException {
ProcessBuilder pb = new ProcessBuilder().inheritIO().command(
getSevenZipExecutablePath(),
EXTRACT_WITH_FULL_PATHS_COMMAND,
source.getAbsolutePath(),
OUTPUT_DIRECTORY_SWITCH + destination.getAbsolutePath(),
OVERWRITE_WITHOUT_PROMPT
);
processWithSevenZipEmbedded(pb);
}
private static void processWithSevenZipEmbedded(ProcessBuilder pb) throws IOException {
LOG.info("7-zip command issued: " + String.join(" ", pb.command()));
pb.start();
}
public class Commands {
public static final String EXTRACT_WITH_FULL_PATHS_COMMAND = "x";
}
public class Switches {
public static final String OUTPUT_DIRECTORY_SWITCH = "-o";
public static final String OVERWRITE_WITHOUT_PROMPT = "-aoa";
}
Double click on file 7zip.chm or start 7-Zip and open the Help and read the help page Command Line Version - Syntax with first line 7z [...] [...]. There is clearly explained that first the command x must be specified, next should be the switches like -o with best last switch being --, then the archive file name and last further arguments like names of files/folders to extract. Switches can be also specified after archive file name, but that is not recommended although examples on help page for -o are also with -o at end.
Thank you #Mofi for the tip. I used -aoa switch instead of -y and it finally started to work as I wanted - to overwrite files without any prompt. I left the rest of the command the way it was as it works as intended, so it finally looks like this:
C:/Users/blood/java_projects/AppRack/target/classes/7z/7z" x D:\Pulpit\AppRack Sandbox\test\Test\Test 2\Test.7z -oD:\Desktop\AppRack Sandbox\Test 2 -aoa
Thanks a lot for help once again!
I have a java web service which executes a batch file. I have finished my controller class. In the controller class, there is a parameter and the variable is String fileName. I am not sure how to code to make the fileName to carry out its function.
I will show my codes then explain about what fileName is supposed to do.
RunBatchFile.java
public ResultFormat runBatch(String fileName) {
String var = fileName;
String filePath = ("C:/Users/attsuap1/Desktop" + var);
try {
Process p = Runtime.getRuntime().exec(filePath);
int exitVal = p.waitFor();
return new ResultFormat(exitVal == 0);
} catch (Exception e) {
e.printStackTrace();
return new ResultFormat(false);
}
}
BatchFileController.java
private static final String template = "Sum, %s!";
#RequestMapping("/runbatchfileparam/{param}")
public ResultFormat runbatchFile(#PathVariable("param") String fileName) {
RunBatchFile rbf = new RunBatchFile();
return rbf.runBatch(fileName);
}
When the user types in http://localhost:8080/runbatchfileparam/test.bat as URL, the test.bat file must be executed. When the user types in test123.bat instead of test.bat, the test123.batch file must be executed. Therefore i cannot code the String filePath to be "C:/Users/attsuap1/Desktop/test.bat" as that will execute the test.bat file. I want to allow users to choose the batch file that they want to execute. I think this is simple to achieve however i am not sure on how to do that.
How do i code to link the String fileName variable to make it carry out what it is supposed to do? I tried some ways however they do not give the results that i want.
Someone please do help me thank you so much.
I think you have already done the job here.
There are two ways that you can execute the desired batch file.
Dont include ".bat" in URL param,
Rather append .bat in your runBatch() method, to whatever file you get in the param
e.g.
public ResultFormat runBatch(String fileName) {
String var = fileName;
String filePath = ("C:/Users/attsuap1/Desktop/" + var+".bat");
try {
Process p = Runtime.getRuntime().exec(filePath);
But if you do want to include .bat in your URl, you will have to use the below regex-mapping so that spring does not ignore the filename trailing the dot.
#RequestMapping("/runbatchfileparam/{param:.+}")
public ResultFormat runbatchFile(#PathVariable("param") String fileName)
{
RunBatchFile rbf = new RunBatchFile();
return rbf.runBatch(fileName);
}
This is my code. I am able to open browser but it will not load the html source.
class Browser {
public static void main(String[]args) {
try {
Runtime rtime = Runtime.getRuntime();
String url = "C:/Program Files (x86)/Internet Explorer/DD.html";
String brow = "C:/Program Files (x86)/Internet Explorer/iexplore.exe";
Process pc = rtime.exec(brow + url);
pc.waitFor();
} catch (Exception e) {
System.out.println("\n\n" + e.getMessage());
}
}
}
Use this:
Desktop.getDesktop().browse(URI);
You have too many spaces in the brow value - I presume that's just a formatting issue in the question.
Using the single-argument version of exec splits the input string by spaces, so your code will try to execute a command C:/Program and pass it arguments "Files", "(x86)/Internet", "Explorer/iexplore.exeC:/Program", "Files", etc.
Note that "Explorer/iexplore.exeC:/Program" - because you concatenated the two strings without a space.
You could resolve these issues by passing an array of strings to exec() instead of using the single-string version, but you're better off using Desktop.getDesktop().browse(URI);
Does any one know of any Java libraries I could use to generate canonical paths (basically remove back-references).
I need something that will do the following:
Raw Path -> Canonical Path
/../foo/ -> /foo
/foo/ -> /foo
/../../../ -> /
/./foo/./ -> /foo
//foo//bar -> /foo/bar
//foo/../bar -> /bar
etc...
At the moment I lazily rely on using:
new File("/", path).getCanonicalPath();
But this resolves the path against the actual file system, and is synchronised.
java.lang.Thread.State: BLOCKED (on object monitor)
at java.io.ExpiringCache.get(ExpiringCache.java:55)
- waiting to lock <0x93a0d180> (a java.io.ExpiringCache)
at java.io.UnixFileSystem.canonicalize(UnixFileSystem.java:137)
at java.io.File.getCanonicalPath(File.java:559)
The paths that I am canonicalising do not exist on my file system, so just the logic of the method will do me fine, thus not requiring any synchronisation. I'm hoping for a well tested library rather than having to write my own.
I think you can use the URI class to do this; e.g. if the path contains no characters that need escaping in a URI path component, you can do this.
String normalized = new URI(path).normalize().getPath();
If the path contains (or might contain) characters that need escaping, the multi-argument constructors will escape the path argument, and you can provide null for the other arguments.
Notes:
The above normalizes a file path by treating it as a relative URI. If you want to normalize an entire URI ... including the (optional) scheme, authority, and other components, don't call getPath()!
URI normalization does not involve looking at the file system as File canonicalization does. But the flip side is that normalization behaves differently to canonicalization when there are symbolic links in the path.
Using Apache Commons IO (a well-known and well-tested library)
public static String normalize(String filename)
will do exactly what you're looking for.
Example:
String result = FilenameUtils.normalize(myFile.getAbsolutePath());
If you don't need path canonization but only normalization, in Java 7 you can use java.nio.file.Path.normalize method.
According to http://docs.oracle.com/javase/7/docs/api/java/nio/file/Path.html:
This method does not access the file system; the path may not locate a file that exists.
If you work with File object you can use something like this:
file.toPath().normalize().toFile()
You could try an algorithm like this:
String collapsePath(String path) {
/* Split into directory parts */
String[] directories = path.split("/");
String[] newDirectories = new String[directories.length];
int i, j = 0;
for (i=0; i<directories.length; i++) {
/* Ignore the previous directory if it is a double dot */
if (directories[i].equals("..") && j > 0)
newDirectories[j--] = "";
/* Completely ignore single dots */
else if (! directories[i].equals("."))
newDirectories[j++] = directories[i];
}
/* Ah, what I would give for String.join() */
String newPath = new String();
for (i=0; i < j; i++)
newPath = newPath + "/" + newDirectories[i];
return newPath;
}
It isn't perfect; it's linear over the number of directories but does make a copy in memory.
Which kind of path is qualified as a Canonical Path is OS dependent.
That's why Java need to check it on the filesystem.
So there's no simple logic to test the path without knowing the OS.
So, while normalizing can do the trick, here is a procedure that exposes a little more of the Java API than would simply calling Paths.normalize()
Say I want to find a file that is not in my current directory on the file system.
My working code file is
myproject/src/JavaCode.java
Located in myproject/src/. My file is in
../../data/myfile.txt
I'm testing my program running my code from JavaCode.java
public static void main(String[] args) {
findFile("../../data","myfile.txt");
System.out.println("Found it.");
}
public static File findFile(String inputPath, String inputFile) {
File dataDir = new File("").getAbsoluteFile(); // points dataDir to working directory
String delimiters = "" + '\\' + '/'; // dealing with different system separators
StringTokenizer st = new StringTokenizer(inputPath, delimiters);
while(st.hasMoreTokens()) {
String s = st.nextToken();
if(s.trim().isEmpty() || s.equals("."))
continue;
else if(s.equals(".."))
dataDir = dataDir.getParentFile();
else {
dataDir = new File(dataDir, s);
if(!dataDir.exists())
throw new RuntimeException("Data folder does not exist.");
}
}
return new File(dataDir, inputFile);
}
Having placed a file at the specified location, this should print "Found it."
I'm assuming you have strings and you want strings, and you have Java 7 available now, and your default file system uses '/' as a path separator, so try:
String output = FileSystems.getDefault().getPath(input).normalize().toString();
You can try this out with:
/**
* Input Output
* /../foo/ -> /foo
* /foo/ -> /foo
* /../../../ -> /
* /./foo/./ -> /foo
* //foo//bar -> /foo/bar
* //foo/../bar -> /bar
*/
#Test
public void testNormalizedPath() throws URISyntaxException, IOException {
String[] in = new String[]{"/../foo/", "/foo/", "/../../../", "/./foo/./",
"//foo/bar", "//foo/../bar", "/", "/foo"};
String[] ex = new String[]{"/foo", "/foo", "/", "/foo", "/foo/bar", "/bar", "/", "/foo"};
FileSystem fs = FileSystems.getDefault();
for (int i = 0; i < in.length; i++) {
assertEquals(ex[i], fs.getPath(in[i]).normalize().toString());
}
}