We run code which does the standard for creating a temp directory:
import java.nio.file.Files;
And then:
tmp = Files.createTempDirectory("ourprefix-");
This, effectively, creates the directories under /tmp/ so that we get things like /tmp/ourprefix-1234 or similar.
Unfortunately, this base directory /tmp/ seems to be fixed and since on our build server lots of things tend to put their temp stuff there and because the partition the /tmp/ is on is rather small, this is a problem.
Is there a way to configure this facility from the outside (i. e. without changing the code)? I would have guessed that /tmp/ is a default and can be overridden by setting a special environment variable or (more Javaish) passing a special property to the compiler (e. g. -Djava.tmp.root=/path/to/my/larger/partition/tmp).
I tried using java.io.tmpdir but setting this did not have any effect; it seems to be the default in case nothing is given to createTempDirectory() but in our case the code passes a prefix.
Any idea how to achieve what I want without changing the source code?
EDIT
After some investigation I found that this works just fine:
import java.nio.file.Path;
import java.nio.file.Files;
import java.io.IOException;
public class TestTempDir {
public static void main(String[] args) throws IOException {
System.out.println(System.getProperty("java.io.tmpdir"));
Path path = Files.createTempDirectory("myprefix-");
System.out.println(path.toFile().getAbsolutePath());
}
}
Compile with javac TestTempDir.java, prepare with mkdir tmp and run with java -Djava.io.tmpdir=pwd/tmp TestTempDir this just works as expected:
/my/work/path/tmp
/my/work/path/tmp/myprefix-1525078348397347983
My issue rather seems to be one with Jenkins and its Maven plugin which does not pass the set properties along to the test cases :-/
if you pass the java.io.tmpdir property as a custom JVM property as you run the JVM, it should work.
Something like that :
java -Djava.io.tmpdir=myPath myClass
I tested and it works :
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class TestTempDir {
public static void main(String[] args) throws IOException {
System.out.println(System.getProperty("java.io.tmpdir"));
Path dir = Files.createTempDirectory("helloDir");
System.out.println(dir.toString());
}
}
$ java -Djava.io.tmpdir=D:\temp TestTempDir
D:\temp
D:\temp\helloDir5660384505531934395
Related
There are some cases that the software shall behave differently according to some environmental conditions, for example whether a file exists at some place or not.
In my case, I'm developing a library, and it is configured according to a configuration file in classpath, (and falls back to default behavior if the config file does not exists).
How shall I unit test this class?
I need to write tests for evaluating the class in following cases:
the file does not exists on classpath
the file with content A exist on classpath
the file with content B exist on classpath
But I don't know how to configure environment to justify all of them. And execute the test one after each other.
By the way I'm using Java, and I have both JUnit and TestNG on the test classpath.
Edit:
One of the problems is that the config file resides in classpath, so if the normal ClassLoader finds and loads it, it returns the same content as long as the same class loader is used.
And I believe using a custom ClassLoader for testing is so complicated, that it needs tests to validate the tests!
You can use a temporary file created by your test to mock out the path in your class.
ConfigurationTest.java:
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeThat;
import java.nio.file.Files;
import org.junit.Test;
public class ConfigurationTest {
private Configuration config = new Configuration();
#Test
public void testWithConfigFile() throws Exception {
config.configFile = Files.createTempFile("config_",".ini");
config.configFile.toFile().deleteOnExit();
assertFalse(config.isInDefaultMode());
}
#Test
public void testWithoutConfigFile() throws Exception {
assumeThat(Files.exists(config.configFile), is(false));
assertTrue(config.isInDefaultMode());
}
}
Configuration.java:
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class Configuration {
Path configFile = Paths.get("config.ini");
public boolean isInDefaultMode() {
return !Files.exists(configFile);
}
}
We tried to import a test rascal module and a module from the standard library using JavaToRascal.
The test module is stored in C:\Users\Klemens\workspace\RascalInterop\src\MyTest.rsc and contains:
module MyTest
Te java code containing the JavaToRascal invocation is as follows:
import java.io.PrintWriter;
import java.net.URISyntaxException;
import org.rascalmpl.interpreter.JavaToRascal;
import org.rascalmpl.interpreter.load.IRascalSearchPathContributor;
import org.rascalmpl.interpreter.load.StandardLibraryContributor;
import org.rascalmpl.interpreter.load.URIContributor;
import org.rascalmpl.uri.URIUtil;
public class RascalInterop {
public static void main(String[] args) throws URISyntaxException {
JavaToRascal j2r = new JavaToRascal(new PrintWriter(System.out), new PrintWriter(System.err));
IRascalSearchPathContributor modulePath = new URIContributor(URIUtil.createFileLocation("C:\\Users\\Klemens\\workspace\\RascalInterop\\src\\MyTest.rsc"));
j2r.getEvaluator().addRascalSearchPathContributor(modulePath);
try {
j2r.eval("import MyTest;").toString(); // Could not import module MyTest: can not find in search path
} catch (Exception e) {
System.out.println(e.getMessage());
}
try {
j2r.getEvaluator().addRascalSearchPathContributor(StandardLibraryContributor.getInstance());
j2r.eval("import IO;").toString(); // null pointer exception
} catch (Exception e) {
System.out.println(e.getClass());
}
}
}
The print in the first try block that tries to import our MyTest.rsc module results in:
Could not import module MyTest: can not find in search path
?[Advice](http://tutor.rascal-mpl.org/Errors/Static/ModuleImport/ModuleImport.html)
The second import attempting to import the IO module from the standard library results in:
class java.lang.NullPointerException
Any ideas how to use properly set the search path from a Java program?
We tried to use j2r.getEvaluator().addRascalSearchPathContributor in various ways but did not succeed in loading a MyTest.rsc module from the given directory.
Despite that these API will change in the near future (due to the compilation process and related changes), here's an answer. Two answers actually, one for Rascal files and one for Java code that it needs
For Rascal:
j2r.getEvaluator().addRascalSearchPathContributor
What you used is the correct way of doing things. So if it did not work, please provide more code so we can diagnose what goes wrong. So where is your module? Is it in a jar file or a binary folder? If its in a jar, you need some additional wiring I'm glad to explain.
The Rascal search path is distinguished from the Classpath for Java classes which are used by Rascal. So you have different API for that. We use classloaders to find Java files (such that it also works for situations like OSGI bundles in Eclipse):
Evaluator x = ctx.getEvaluator();
x.addClassLoader(getClass().getClassLoader());
This will make sure that the class loader used to load the current class is also used to load the class linked mentioned in the Rascal file. Of course you can also provide other class loaders. Note that if the libraries you depend on are loaded via OSGI, make sure you get a classloader from a class that is in a bundle that has access to these classes. The simple case is when everything is in the same jar file, then any classloader will do.
I think you should change the path to refer to the src directory instead of the source file:
new URIContributor(URIUtil.createFileLocation("C:\\Users\\Klemens\\workspace\\RascalInterop\\src"));
Also: probably you should use forward slashes without C:\, so /Users/.../src
AFAIK The null pointer exception is expected, evaluating import returns null, and you try to call toString().
I am trying to understand how javac deals with cyclic imports. After few attempts, I got the below code to be compiled:
package com.test.p1;
import com.test.p2.ClassP2;
public class ClassP1 {
public static void main(String[] args) {
System.out.println("ClassP1 loaded");
ClassP2.testP2();
}
}
And
package com.test.p2;
import com.test.p1.ClassP1;
public class ClassP2 {
public static void testP2() {
System.out.println("ClassP2 loaded");
}
}
When I compiled ClassP2.java first, I was expecting it to fail as ClassP1.java was not yet compiled and no class file was generated. Yet, it compiled ok, and generated ClassP2.class and ClassP1.class. Running ClassP1 worked fine as well.
Now my question is how did javac generate class file for ClassP1 when I only compiled ClassP2. And why does this not happen when cyclic reference is not there - i.e. when ClassP2 imports ClassP1, but ClassP1 does not import ClassP2 ?
I am still new to Java and trying to understand how compilation works.
There's nothing cyclic going on here. It sounds like you, along with a lot of other people, confuse import with class loading.
All the import statement does is allow you to use the short name to refer to a Java class in your code:
import java.sql.ResultSet;
public V find() {
ResultSet rs = null; // You can type ResultSet instead of java.sql.ResultSet
}
The import statement won't help you if the short name is ambiguous (e.g. java.util.Date and java.sql.Date in the same class).
The byte code for java.sql.ResultSet is not loaded into the JVM until your code needs it at runtime.
It is not a result of cyclic imports, it is a result of importing ClassP1 in ClassP2.java and javac being able to find the source for ClassP1 based on the arguments you passed to javac and the location from which you executed the command.
See the -sourcepath option in the docs for javac:
-sourcepath sourcepath
Specify the source code path to search for class or interface definitions. As with the user class path, source path entries are separated by semicolons (;) and can be directories, JAR archives, or ZIP archives. If packages are used, the local path name within the directory or archive must reflect the package name.
Note: Classes found through the class path may be subject to automatic recompilation if their sources are also found. See Searching For Types.
The Files class introduced in Java 7 has methods for handling links and symlinks but only as optional operations.
Is there any way of determining at runtime if a file system supports these operations before actually invoking the respective methods or do I need to call them and then catch the exception?
Classes like FileSystem or FileStore do not seem to contain anything in that regard (or I overlooked it).
I don't see any general approach that will work without relying on an UnsupportedOperationException or some other exception.
You could use a heuristic that assumes that only subclasses of BasicFileAttributesView support symbolic linking.
Note: The approach below will not work because FileAttributeViews and file attributes are not the same concept:
I did not get isSymbolicLink as one of the supported attributes with the following code on OS X 10.8.4:
package com.mlbam.internal;
import java.nio.file.Files;
import java.nio.file.FileStore;
import java.nio.file.FileSystems;
import java.nio.file.Paths;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MainClass {
private static final Logger LOG = LoggerFactory.getLogger(MainClass.class);
public static void main(String[] args) {
try {
System.out.println("FileStore.supportsFileAttributeView('isSymbolicLink'): "
+ Files.getFileStore(Paths.get("/")).supportsFileAttributeView("isSymbolicLink"));
// Got: FileStore.supportsFileAttributeView('isSymbolicLink'): false
System.out.println(FileSystems.getDefault().supportedFileAttributeViews());
// Got: [basic, owner, unix, posix]
} catch (Exception e) {}
}
}
Original Answer:
If you have an instance of FileStore, you can use FileStore.supportsFileAttributeView("isSymbolicLink")
Or, if you have an instance of FileSystem, you can check that resulting Set<String> from FileSystem.supportedFileAttributeViews() contains the String "isSymbolicLink".
You can get the FileStore associated with a Path using Files.getFileStore(Path)
One way of getting the FileSystem is via FileSystems.getDefault()
I am trying to imported a java class from an external lib in jyhon and it does not work. An example
package run;
import import.Imported;
Class Run()
{
public static void main(String[] args){
pi = new PythonInterpreter(null);
pi.execfile('script.py');
}
}
//this is an external libary
package import;
Class Imported()
{
//some stuff;
}
//py script
from import import Imported //this line throws an error Module not found
#do some stuff
The strangest thing is that it runs when it is compiled in Eclipse, but does not from command line.
Any help?
Sounds like your classpath is probably set incorrectly at runtime. The easiest solution is typically just to add the directory or jar file containing 'import' to sys.path.
(Also, naming your packages 'import' is just asking for trouble.)