Java location path regex split - java

I've "inherited" existing Java Selenium & Cucumber framework which was written mostly for OS usage. I'm using Windows and I'm trying to fix & run it on Windows.
My first problem is specifing corrent file path, this is how it was written for OS:
private String getProjectName(Scenario scenario) {
return Arrays.asList(scenario.getUri().getPath().replace(System.getProperty("user.dir"), "").split("/")).get(5);
}
Error which I'm receiving is:
java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 1
As for Windows we're using backlashes I've tried switching "/" into "" but as error appears (+ after my investigations) I've tried with "\\\\" but actually error remains the same as above.
I'm aware that providing only portion of my code and it may be hard but for the first glance can you tell me:
If that method may work on Windows or this should be completely refactored?
Is System.getProperty("user.dir") correct solution?
How to correctly pass backslashes?
Why they're taking .get(5)?

I can guess:
This method is taking the project name that is likely the name of a certain folder in the folder structure where scenario file located.
This is why they took 5th element. Because on the 5th level there was the folder which represented the project.
The used approach look very arguable. At least because there are some redundent steps like converting to list.
Now. How would you go:
The proper way is to use java.nio.file.Path (starts from Java 7) that takes care of differnt OS-specific things.
So your code might look like:
private String getProjectName(Scenario scenario) {
return Path.of(scenario.getUri()).getName(5)
}
P.S. - of course you have to change 5 to catch a proper position of the required folder in your structure.

Related

Why does Path.relativize behave differently on Java 8 and Java 11?

Why does the method relativize behave differently on java-8 and java-11?
Path path1 = Paths.get("/a/./b/../image.png");
Path path2 = Paths.get("/a/file.txt");
Path path = path1.relativize(path2);
System.out.println(path);
java-8 (1.8.0_66 to be exact) prints ../../../../file.txt. JavaDoc.
java-11 (11.0.4 to be exact) prints ../file.txt. JavaDoc.
The JavaDoc description of both versions is equal. I feel the java-11 way looks like a correct behavior to me:
path1: /a/./b/../image.png normalizes to /a/b/../image.png which normalizes to /a/image.png
path2: /a/file.txt
the way to navigate from /a/image.png and /a/file.txt is ../file.txt
Questions
How is the java-8 way supposed to be calculated? Doesn't it normalize the path? I don't understand how to get the result from head.
Why is there a difference between these two versions that is not documented at all?
Maybe this bug will answer your question:
https://bugs.openjdk.java.net/browse/JDK-8066943
This affected relativizing paths containing . or .. and was fixed for Java 9.
So that's why you see a difference between 8 and 11.
Windows based source-code answer here.
From the observation of the source codes (let's take a look at sun.nio.fs.WindowsPath, one of the implementations of Path) in java-11 is has additional code including normalization compared to java-8.
java-8 sun.nio.fs.WindowsPath source code at GitHub
java-11 sun.nio.fs.WindowsPath source code at GitHub
The key line of the latter implementation starts at the line 411, so basically, the latter implementation normalizes the paths before taking into calculation of the relative path:
WindowsPath base = this;
if (base.hasDotOrDotDot() || child.hasDotOrDotDot()) {
base = base.normalize();
child = child.normalize();
}
Digging further, the implementation changes between jdk8-b120 (source) and jdk-9+95 (source). Since the modular system was introduced, both the classes implementation and location differ:
Java 8 and below: /jdk/src/windows/classes/sun/nio/fs/WindowsPath.java
Java 9 and above: /jdk/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java
How is the java-8 way supposed to be calculated? Doesn't it normalize the path? I don't understand how to get the result from head.
The most straightforward way to go is to normalize both paths first before relativizing them. But I have no idea whether it completely covers all the java.nio.file.Path implementations and is safe to do so.
Path path = path1.normalize().relativize(path2.normalize());

How to autodetect the file location in Java?

I just wondered if there are any ways to let your program find a file you want to use by just giving the name without writing the whole search path like this.
Scanner betalningsservice = new Scanner(new File("/afs/nada.kth.se/home/i/u1vxrjgi/betalningsservice.txt"));
String line1 = betalningsservice.nextLine();
You can see that its a pretty long path and I would like the program to be able to detect the file "betalningsservice.txt" whereever the file is located in the computer (in case the file has been moved to somewhere else). Any tips guys? :)
Thanks in advance
Since there's some debate about what exactly is wanted in this question, I'll post another answer.
If you're using Java 8, finding a file is made somewhat simpler by using the Files.find function. It has the advantage of being able to limit how deep the search goes, keeping search speed under control. Here's an example that sticks the Paths of all matching files into a List. If you find more than one matching file you can have the user choose the right one:
final String SEARCH_FILE = "betalningsservice.txt"; // the file you're looking for
final String SEARCH_ROOT = "/afs/nada.kth.se/home/i/"; // where to start the search (top folder)
final int SEARCH_DEPTH = 4; // how many nested subfolders to delve into
final List<Path> files = new LinkedList<>();
Files.find(Paths.get(SEARCH_ROOT), SEARCH_DEPTH, (p, a) -> p.endsWith(SEARCH_FILE))
.forEach(e -> files.add(e));
It's debatable whether one big-ass statement that does all of the logic of the search is more readable or less readable, but that's Java 8 for you.
If you want to get advanced, you can also append FileVisitOptions to the find function's parameter list (for example, to follow symbolic links).
It's interesting to note that in Java 8, Path has generally replaced File as the way to represent files and folders, hence the List of Paths. Once you've selected the correct Path (we'll say it's in a variable called path), you can use it similarly to how you would use a File:
Scanner betalningsservice = new Scanner(path);
The rest is as before.
File can also create files using a relative path. Just don't start the file name with a slash. For example, if you run the program from the folder "/afs/nada.kth.se/home/i/u1vxrjgi/", you can just use:
new File("betalningsservice.txt")
...and that will get you the file you want.
There is not a practical/reliable way to just find the file anywhere on the computer.
You can, however, utilize relative file paths if you know your working directory. So if your working directory were /afs/nada.kth.se/home/i/u1vxrjgi, you could refer to the file just by new File("betalningsservice.txt"). Similarly, if your working diretory were /afs/nada.kth.se/home/i, you could refer to the file as new File("u1vxrjgi/betalningsservice.txt").
Another option would be to read from the classpath. This can be accomplished by getting the classloader to get a resource.

In dalvik, what expression will generate instructions 'not-int' and 'const-string/jumbo'?

I am new on learning dalvik, and I want to dump out every instruction in dalvik.
But there are still 3 instructions I can not get no matter how I write the code.
They are 'not-int', 'not-long', 'const-string/jumbo'.
I written like this to get 'not-int' but failed:
int y = ~x;
Dalvik generated an 'xor x, -1' instead.
and I know 'const-string/jumbo' means that there is more than 65535 strings in the code and the index is 32bit. But when I decleared 70000 strings in the code, the compiler said the code was too long.
So the question is: how to get 'not-int' and 'const-string/jumbo' in dalvik by java code?
const-string/jumbo is easy. As you noted, you just need to define more than 65535 strings, and reference one of the later ones. They don't all need to be in a single class file, just in the same DEX file.
Take a look at dalvik/tests/056-const-string-jumbo, in particular the "build" script that generates a Java source file with a large number of strings.
As far as not-int and not-long go, I don't think they're ever generated. I ran dexdump -d across a pile of Android 4.4 APKs and didn't find a single instance of either.

Compare Code Submissions with Previous Submissions?

Users submit code (mainly java) on my site to solve simple programming challenges, but sending the code to a server to compile and execute it can sometimes take more than 10 seconds.
To speed up this process, I plan to first check the submissions database to see if equivalent code has been submitted before. I realize this will cause Random methods to always return the same result, but that doesn't matter much. Is there any other potential problem that could be caused by not running the code?
To find matches, I remove comments and whitespace when comparing code. However, the same code can still be written in different ways, such as with different variable names. Is there a way to compare code that will find more equivalent code?
You could store a SHA1 hash of the code to compare with a previous submission. You are right that different variable names would give different hashes. Try running the code through a minifier or obfuscator. That way, variable cat and dog will both end up like a1, then you could see if they are unique. The only other way would be to actually compile it into bytecode, but then it's too late.
Instead of analyzing the source code, why not speed up the compilation? Try having a servlet container always running with a custom ClassLoader, and use the JDK tools.jar to compile on the fly. You could even submit the code via AJAX REST and get the results back the same way.
Consider how Eclipse compiles your files in the background.
Also, consider how http://ideone.com implements their online compiler.
FYI It is a big security risk to allow random code execution. You have to be very careful about hackers.
Variable names:
You can write code to match variable names in one file with the variable names in the other, then you can replace both sets with a consistent variable name.
File 1:
var1 += this(var1 - 1);
File 2:
sum += this(sum - 1);
After you read File 1, you look for what variable name File 2 is using in the place of sum, then make the variable names the same across both files.
*Note, if variables are used in similar ways you may get incorrect substitutions. This is most likely when variables are being declared. To help mitigate this, you can start searching for variable names at the bottom of the file and work up.
Short hands:
Force {} and () braces into each if/else/for/while/etc...
rewrite operations like "i+=..." as "i=i+..."
Functions:
In cases where function order doesn't matter, you can make sure functions are equivalent and then ignore them.
Operator precedence:
"3 + (2 * 4)" is usually equivalent to "2 * 4 + 3"
A way around this could be by determining the precedence of each operation and then matching it to an operation of the same precedence in the other set of code. Once a set of operations have been matched, you can replace them with a variable to represent them.
Ex.
(2+4) * 3 + (2+6) * 5 == someotherequation
//substitute most precedent: (2+4) and (2+6) for a and b
... a * 3 + b * 5
//substitute most precedent: (a*3) and (b*5) for c and d
... c + d
//substitute most precedent....
These are just a couple ways I could think of. If you do it this way, it'll end up being quite a big project... especially if you're working with multiple languages.

OrientDB having trouble with Unicode, Turkish, and enums

I am using a lib which has an enum type with consts like these;
Type.SHORT
Type.LONG
Type.FLOAT
Type.STRING
While I am debugging in Eclipse, I got an error:
No enum const class Type.STRİNG
As I am using a Turkish system, there is a problem on working i>İ but as this is an enum const, even though I put every attributes as UTF-8, nothing could get that STRING is what Eclipse should look for. But it still looks for STRİNG and it can't find and I can't use that. What must I do for that?
Project > Properties > Resouce > Text file encoding is UTF-8 now. Problem keeps.
EDIT: More information may give some clues which I can't get;
I am working on OrientDB. This is my first attempt, so I don't know if the problem could be on OrientDB packages. But I am using many other libs, I have never seen such a problem. There is a OType enum in this package, and I am only trying to connect to the database.
String url = "local:database";
ODatabaseObjectTx db = new ODatabaseObjectTx(url).
Person person = new Person("John");
db.save(person);
db.close();
There is no more code I use yet. Database created but then I get the java.lang.IllegalArgumentException:
Caused by: java.lang.IllegalArgumentException: No enum const class com.orientechnologies.orient.core.metadata.schema.OType.STRİNG
at java.lang.Enum.valueOf(Unknown Source)
at com.orientechnologies.orient.core.metadata.schema.OType.valueOf(OType.java:41)
at com.orientechnologies.orient.core.sql.OCommandExecutorSQLCreateProperty.parse(OCommandExecutorSQLCreateProperty.java:81)
at com.orientechnologies.orient.core.sql.OCommandExecutorSQLCreateProperty.parse(OCommandExecutorSQLCreateProperty.java:35)
at com.orientechnologies.orient.core.sql.OCommandExecutorSQLDelegate.parse(OCommandExecutorSQLDelegate.java:43)
at com.orientechnologies.orient.core.sql.OCommandExecutorSQLDelegate.parse(OCommandExecutorSQLDelegate.java:28)
at com.orientechnologies.orient.core.storage.OStorageEmbedded.command(OStorageEmbedded.java:63)
at com.orientechnologies.orient.core.command.OCommandRequestTextAbstract.execute(OCommandRequestTextAbstract.java:63)
at com.orientechnologies.orient.core.metadata.schema.OClassImpl.addProperty(OClassImpl.java:342)
at com.orientechnologies.orient.core.metadata.schema.OClassImpl.createProperty(OClassImpl.java:258)
at com.orientechnologies.orient.core.metadata.security.OSecurityShared.create(OSecurityShared.java:177)
at com.orientechnologies.orient.core.metadata.security.OSecurityProxy.create(OSecurityProxy.java:37)
at com.orientechnologies.orient.core.metadata.OMetadata.create(OMetadata.java:70)
at com.orientechnologies.orient.core.db.record.ODatabaseRecordAbstract.create(ODatabaseRecordAbstract.java:142)
... 4 more
Here is OType class: http://code.google.com/p/orient/source/browse/trunk/core/src/main/java/com/orientechnologies/orient/core/metadata/schema/OType.java
And other class; OCommandExecutorSQLCreateProperty:
http://code.google.com/p/orient/source/browse/trunk/core/src/main/java/com/orientechnologies/orient/core/sql/OCommandExecutorSQLCreateProperty.java
Line 81 says: type = OType.valueOf(word.toString());
Am I correct to assume you are running this program using a turkish locale? Then it seems the bug is in line 118 of OCommandExecutorSQLCreateProperty:
linkedType = OType.valueOf(linked.toUpperCase());
You would have to specify the Locale whose upper casing rules should be used, probably Locale.ENGLISH as the parameter to toUpperCase.
This problem is related to your database connection. Presumably, there's a string in OrientDB somewhere, and you are reading it, and then trying to use it to select a member of the enum.
I'm assuming in the code that you posted that the variable word comes from data in the database. If it comes from somewhere else, then the problem is the 'somewhere else'. If OrientDB, for some strange reason, returns 'STRİNG' as metadata to tell you the type of something, then that is indeed a defect in OrientDB.
If that string actually contains a İ, then no Eclipse setting will have any effect on the results. You will have to write code to normalize İ to I.
If you dump out the contents of 'word' as a sequence of hex values for the chars of the string, I think you'll see your İ staring right at you. You have to change what's in the DB to have a plain old I.
Unfortunately, it is related with regional setting, locale of your OS which is Turkish.
Two work around options :
1. Change your regional settings to English-US
2. Give encoding to the jvm as command line param for setting locale to English
-Duser.language=en -Duser.region=EN
I have created bug reports for xmlbeans, exist and apache cxf for the same issue. Enumeration toUpper is the point of the exception.
Some related links:
https://issues.apache.org/jira/browse/XMLSCHEMA-22
http://mail-archives.apache.org/mod_mbox/xmlbeans-user/201001.mbox/%3CSNT123-DS11993DD331D6CA7799C46CF6650#phx.gbl%3E
http://mail-archives.apache.org/mod_mbox/cxf-users/201203.mbox/%3CBLU0-SMTP115A668459D9A0DA11EA5FAF6460#phx.gbl%3E
https://vaadin.com/forum/-/message_boards/view_message/793105
http://comments.gmane.org/gmane.comp.apache.cxf.user/18316
One work-around is to type Type.ST and then press Ctrl-space. Eclipse should auto-complete the variable name without you having to figure out how to enter a dotless capital I on a Turkish keyboard. :)

Categories

Resources