I'm trying to load the smartcard terminals using the javax.smartcardio API with the following code:
public CardTerminal getReadyCardTerminal() throws CardException {
TerminalFactory factory = TerminalFactory.getDefault();
CardTerminals terminals = factory.terminals();
List<CardTerminal> list = terminals.list(State.CARD_PRESENT);
while (list.isEmpty()) {
terminals.waitForChange(1000);
list = terminals.list(State.CARD_PRESENT);
}
CardTerminal cardTerminal = list.get(0);
return cardTerminal;
}
... and I always get the following exception:
java.lang.IllegalStateException: no terminals
at javax.smartcardio.TerminalFactory$NoneCardTerminals.waitForChange(TerminalFactory.java:145)
On Windows Vista/7 everything works fine, but I can't get it to work on Linux. I'm using Ubuntu 12.04 64 bits.
I installed the pcscd service using the following command:
sudo apt-get install libccid pcscd libpcsclite-dev libpcsclite1
sudo service pcscd start
And the pcsc_scan command prints this:
PC/SC device scanner
V 1.4.18 (c) 2001-2011, Ludovic Rousseau <ludovic.rousseau#free.fr>
Compiled with PC/SC lite version: 1.7.4
Using reader plug'n play mechanism
Scanning present readers...
0: OMNIKEY CardMan 3x21 00 00
Tue Sep 11 15:44:49 2012
Reader 0: OMNIKEY CardMan 3x21 00 00
Card state: Card inserted,
ATR: <some hexa codes>
...
So everything looks ok, but the smartcardio just doesn't work. I'm trying with both Oracle and OpenJDK 1.7.0_05, 32 and 64 bits.
The code runs ok with OpenJDK (but not with Oracle JDK, don't know really why) on a Ubuntu 32 bits environment. So I think it is a problem with the 64 bits bridge from Java to the PC/SC library.
Any ideas?
Thanks.
I think I found a workaround for this as I just had a similar problem. In a bugreport from ubuntu it says that the javax.smartcardio library searches for the PC/SC library in the wrong directory.
By specifying the path to the PC/SC library on my machine, like the bugreport mentions, I got it working.
The paths in the bugreport are wrong for me, I'm on 64 bit fedora, where the pc/sc library are installed at /usr/lib64/libpcsclite.so.1
So the workaround for me is to specify the library path to java like this:
java -Dsun.security.smartcardio.library=/usr/lib64/libpcsclite.so.1
Depending on your Linux distribution, the location of libpcsclite.so.1 actually might differ, it could also be at /lib/x86_64-linux-gnu/libpcsclite.so.1 (i.e. Kubuntu 15.04).
In that case, call it like this:
java -Dsun.security.smartcardio.library=/lib/x86_64-linux-gnu/libpcsclite.so.1
i'm using raspberry with debian arm version
find the location of libpcsclite first with:
$ ldd -r /usr/bin/pcsc_scan
and then use the libpcsclite location with:
java -Dsun.security.smartcardio.library=/usr/lib/arm-linux-gnueabihf/libpcsclite.so.1
You need to give the path to the libpcsclite.so.1 when calling your program as follows
java -Dsun.security.smartcardio.library=/path/to/libpcsclite.so.1
If you don't know the path to the library, use the following command
find /usr/lib -name libpcsclite.so.1
This usually shows you the path on your machine. I used it on both Ubuntu 10 (32bit) and Ubuntu 15(32bit and 64bit)
If you're lazy like me, what you can do is include this part of code in your program before you use the javax.smartcardio library
try {
String comm[] = { "find", "/usr", "/lib", "-name",
"libpcsclite.so.1" };
Process p = Runtime.getRuntime().exec(comm);
BufferedReader reader = new BufferedReader(
new InputStreamReader(p.getInputStream()));
while ((line = reader.readLine()) != null && !line.equals("")) {
if (line.contains("libpcsclite.so.1")) {
System.setProperty("sun.security.smartcardio.library",line);
break;
}
}
p.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
Now you can run your code from as usual without including the path to libpcsclite.so.1
For anyone else struggling with this on Ubuntu 14 with a 64 bit machine. I found the .so file is actually located in the following directory
/usr/lib/x86_64-linux-gnu/libpcsclite.so
So running my app with the setting as below worked for me
-Dsun.security.smartcardio.library=/usr/lib/x86_64-linux-gnu/libpcsclite.so
Addition to the solution with supplying the path as a parameter like this:
java -Dsun.security.smartcardio.library=/usr/lib64/libpcsclite.so.1
If you don't want to supply this every time you call the JVM, set it in the environment variables _JAVA_OPTIONS and/or JAVA_OPTS:
export _JAVA_OPTIONS="-Dsun.security.smartcardio.library=/usr/lib64/libpcsclite.so.1"
export JAVA_OPTS="-Dsun.security.smartcardio.library=/usr/lib64/libpcsclite.so.1"
Since this is a workaround for bug that affects the entire system, it makes sense IMHO to apply this workaround systemwide as well.
JAVA_OPTS has local scope and has to be evaluated by scripts running your code; _JAVA_OPTIONS is supposed to be evaluated automatically by the JRE.
Yet another approach (my favorite) is to make some symbolic links.
It has the advantage that it works system-wide (no jvm arguments, no environment variables).
For my (beloved) debian jessie amd64:
ln -s /usr/lib/x86_64-linux-gnu/libpcsclite.so libpcsclite.so
ln -s /usr/lib/x86_64-linux-gnu/libpcsclite.so.1 libpcsclite.so.1
ln -s /usr/lib/x86_64-linux-gnu/libpcsclite.so.1.0.0 libpcsclite.so.1.0.0
Note: This will probably require superuser access.
Complementing #AshanPerera answer, as sometimes searching each time can be slow, you can search it at the first time, and them store the location in a file, and read it from then on:
try {
String filename = "libpcsclite.location";
File propertyFile = new File(filename);
if(propertyFile.createNewFile())
{
String commandWithArguments[] = { "find", "/usr", "/lib", "-name","libpcsclite.so.1" };
Process searchProcess = Runtime.getRuntime().exec(commandWithArguments);
BufferedReader searchReader = new BufferedReader(new InputStreamReader(searchProcess.getInputStream()));
String propertyValue;
while ( (propertyValue = searchReader.readLine()) != null && !propertyValue.equals(""))
{
if (propertyValue.contains("libpcsclite.so.1")) {
BufferedWriter propertyWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(propertyFile)));
propertyWriter.write(propertyValue);
propertyWriter.close();
System.setProperty("sun.security.smartcardio.library",propertyValue);
break;
}
}
searchProcess.waitFor();
}
else
{
BufferedReader propertyReader = new BufferedReader(new InputStreamReader(new FileInputStream(propertyFile)));
String propertyValue = propertyReader.readLine();
System.setProperty("sun.security.smartcardio.library",propertyValue);
}
} catch (Exception e) {
e.printStackTrace();
}
Related
I am writing a program in Java that uses ffmpeg to "snip" a video into several pieces and the stitch them back together again. I have everything working relatively smoothly in Windows, but I cannot get ffmpeg to work in Mac, or in Linux for that matter. I'm focusing on mac right now though. I thought that it might be a permissions problem, but when I run it with sudo I get an error that says (after typing in the password:
sudo: ffmpeg: command not found
when I run it without sudo I get:
java.io.IOException: Cannot run program "ffmpeg": error=2, No such file or directory
I think that it might be because the ffmpeg package, on the Mac machine, was downloaded with homebrew, and ffmpeg is stored in /usr/local/Cellar/ffmpeg instead of the default folder, wherever it may be. That may not be the problem though, because I deleted ffmpeg and re-downloaded it with homebrew. It may have been in its defaulter folder in my first tests as well. It would be great to figure this out. Most of my family uses Mac (not me) and I really want to share my work with them. That is why I chose to code this in Java. Oh, and I did try using the directory to the binary in the command. Here's the code:
//snips out all the clips from the main video
public void snip() throws IOException, InterruptedException {
for(int i = 0; i < snippets.size(); i++) {
//ffmpeg -i 20sec.mp4 -ss 0:0:1 -to 0:0:5 -c copy foobar.mp4
String newFile = "foobar" + String.valueOf(i) + ".mp4";
//THIS WORKS
if(OS.isWindows()) {
ProcessBuilder processBuilder = new ProcessBuilder("ffmpeg", "-i", videoName, "-ss",
snippets.get(i).getStartTime(), "-to", snippets.get(i).getEndTime(), newFile);
Process process = processBuilder.inheritIO().start();
process.waitFor();
System.out.println("Win Snip " + i + "\n");
}
else if (OS.isMac()) {
//FFMPEG LOCATION: /usr/local/Cellar/ffmpeg
//THE ERROR: sudo: ffmpeg: command not found
//ERROR W/OUT SUDO: java.io.IOException: Cannot run program "ffmpeg": error=2, No such file or directory
ProcessBuilder processBuilder = new ProcessBuilder("sudo", "-S", "ffmpeg", "-f", videoName, "-ss",
snippets.get(i).getStartTime(), "-to", snippets.get(i).getEndTime(), newFile);
Process process = processBuilder.inheritIO().start();
process.waitFor();
System.out.println("Mac Snip " + i + "\n");
}
else if (OS.isUnix()) {
System.out.println("Your operating system is not supported");
//TODO
//need to figure out if deb/red hat/whatever are different
}
else if (OS.isSolaris()) {
System.out.println("Your operating system is not supported yet");
//TODO probably won't do
}
else {
System.out.println("Your operating system is not supported");
}
//add to the list of files to be concat later
filesToStitch.add(newFile);
filesToDelete.add(newFile);
}
//System.out.println(stitchFiles);
}
As Mac OS is UNIX-based, you need to put "./" before the executable name if the location isn't in the configured path (i.e. the $PATH environment variable). Changing "ffmpeg" to "./ffmpeg" should hopefully work (assuming that it is genuinely located in the working directory -- you can also change the working directory by calling directory() on your ProcessBuilder if necessary).
After listening to everyone telling me it was a problem with the filepath I decided to double check that I had the right directory. I didn't. I saw a "ffmpeg" file in the homebrew folder, but I found out that I could type:
type ffmpeg
into the terminal to find the filepath. It turns out it was actually under usr/local/bin/ffmpeg. All I had to do was add it to my code
ProcessBuilder processBuilder = new ProcessBuilder("usr/local/bin/ffmpeg", "-f", videoName, "-ss", snippets.get(i).getStartTime(), "-to", snippets.get(i).getEndTime(), newFile);
I feel like a complete moron.
Why do got this difference?
Path docDir
Paths.exists(docDir):true
docDir.toPath().exists():false
others attribute:
Files.isDirectory(docDir)=true
Files.isExecutable(docDir)=true
Files.isHidden(docDir)=false
Files.isReadable(docDir)=true
Files.isRegularFile(docDir)=false
Files.isSymbolicLink(docDir)=false
Files.isWritable(docDir)=true
Files.notExists(docDir)=false
This problem does not occur in single-byte character strings.
Linux version is
Linux version 2.6.32-431.el6.x86_64 (mockbuild#c6b8.bsys.dev.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) )
this application is service, and i using the springBoot library.
There is no problem using 'nio' for read/write, but using 'io.File' will result in 'FileNotFoundException'.
Is there anything I've done wrong?
If you mean
String fileName = "ใในใ.txt";
Path docDir = new File ("/tmp/" + fileName).toPath();
System.out.println(Files.exists(docDir));
System.out.println(docDir.toFile().exists());
then works OK for me # CentOS release 6.8 (Final)
Although I do remember something like this in a zip file
I have the following Java code. Purpose of this code is to establish a connection
to a remote MySQL database ProductionDb ( a data source defined in my /etc/odbc.ini file ).
import java.sql.*;
import java.util.*;
import java.io.*;
public class Test {
public static void main(String[] args) {
try {
Connection conn = null;
PreparedStatement s = null;
String driver = "sun.jdbc.odbc.JdbcOdbcDriver";
Class.forName(driver).newInstance();
conn = DriverManager.getConnection("jdbc:odbc:ProductionDb");
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
}
The /etc/odbc.ini file is:
$ cat /etc/odbc.ini
[ProductionDb]
Driver = /usr/lib/odbc/libmyodbc.so
Description = Production Database
Server = [ hidden ]
Port = 3306
User = [ hidden ]
Password = [ hidden ]
Database = ProductionDb
By the way - I am using Java 7 and Ubuntu :
$java -version
java version "1.7.0_09"
Java(TM) SE Runtime Environment (build 1.7.0_09-b05)
Java HotSpot(TM) 64-Bit Server VM (build 23.5-b02, mixed mode)
$lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 11.04
Release: 11.04
Codename: natty
When I try to run my program I get the following error:
$java Test
java: symbol lookup error: /usr/lib/jvm/java-7-oracle/jre/lib/amd64/libJdbcOdbc.so: undefined symbol: SQLAllocEnv
Does anyone know why I get this error ?
What is wrong here ?
P.S By the way I did run sudo apt-get install unixodbc-dev , sudo apt-get install libmyodbc and sudo apt-get install libmysql-java :-)
UPDATE:
I have also tried the idea suggested in one of the replies below ( by Benny Hill ) : to use the /etc/odbcinst.ini as well as /etc/odbc.ini. Still doesn't work and I get the same error message.
$ cat /etc/odbc.ini
[ProductionDb]
Driver = MySQL Driver
Description = Production Database
Server = [ hidden ]
Port = 3306
User = [ hidden ]
Password = [ hidden ]
Database = ProductionDb
$ cat /etc/odbcinst.ini
[MySQL Driver]
Driver = /usr/lib/odbc/libmyodbc.so
ADDITIONAL NOTE:
I can use this ODBC data source successfully from the R
programming language.
> library(odbc)
> con = odbcConnect("ProductionDb")
> con
RODBC Connection 1
Details:
case=nochange
DSN=ProductionDb
The error is the result of libJdbcOdbc.so looking for the function "SQLAllocEnv" in some other .so and not finding it. The way to debug this is to run the command ldd /usr/lib/jvm/java-7-oracle/jre/lib/amd64/libJdbcOdbc.so. That will show you a list of linked .so objects and where they are located.
Generally speaking they should be in /usr/lib however if you have compiled any software yourself you may find that some of these libs are in /usr/local/lib or some other location. If you have anything that shows up in /usr/local/lib it's possible this is what's causing your problem. To test, rename the library in /usr/local/lib to something else (sudo mv /usr/local/lib/mylib.so /usr/local/lib/mylib.so.SAVE).
Now run your program and see if you still get the same error. If that fixes your problem then great! If not, let us know if you get the same error message or if you get a new one.
I would expect your odbc.ini file to look like this:
[primary]
Description = primary
Driver = iSeries Access ODBC Driver
System = XXX.XXX.XXX.XXX
UserID = XXXXXXXXXX
Password = XXXXXXXXXX
Naming = 0
DefaultLibraries = QGPL
Database = XXXXXXXXXX
ConnectionType = 0
CommitMode = 2
ExtendedDynamic = 0
DefaultPkgLibrary = QGPL
DefaultPackage = A/DEFAULT(IBM),2,0,1,0,512
AllowDataCompression = 1
LibraryView = 0
AllowUnsupportedChar = 0
ForceTranslation = 0
Trace = 0
And your odbcinst.ini file to look like this:
[iSeries Access ODBC Driver]
Description = iSeries Access for Linux ODBC Driver
Driver = /usr/lib/libcwbodbc.so
Setup = /usr/lib/libcwbodbcs.so
NOTE1 = If using unixODBC 2.2.11 or later and you want the 32 and 64-bit ODBC drivers to share DSN's,
NOTE2 = the following Driver64/Setup64 keywords will provide that support.
Driver64 = /usr/lib/lib64/libcwbodbc.so
Setup64 = /usr/lib/lib64/libcwbodbcs.so
Threading = 2
DontDLClose = 1
UsageCount = 1
My example shows my setup for a remote iSeries but I'm sure you can see what you would need to change for MySQL.
Namely your odbc.ini "Driver = ..." line is wrong. It should be something like "Driver = mysql" and then you need to define [mysql] in your odbcinst.ini file.
Sounds like a missing or mismatched library. Try to debug the ldd processing.
First, check what
$ ldd /usr/lib/jvm/java-7-oracle/jre/lib/amd64/libJdbcOdbc.so
says, do all listed dependencies exist?
Then, try setting LD_DEBUG and and start your Java program again, to see the loader debug.
$ export LD_DEBUG=all
$ java Test
To fix this add the following to your startup script or profile:
export LD_PRELOAD=$LD_PRELOAD:/usr/lib/libodbc.so:/usr/lib/libodbcinst.so
Your path may vary a bit, for me the .so files where in /usr/lib64.
"There is a bug due to the fact that the libraries "libodbc.so" and "libodbcinst.so" libJdbcOdbc.so are not loaded from the library that implements the JDBC-ODBC bridge."
According to https://code.google.com/p/queryconnector/source/browse/wiki/HowToInstall.wiki?spec=svn122&r=121
I've used MySQL with JDBC before, and the easiest way I know to connect is using Connector/J which is the official MySQL driver. It will do the same as your ODBC driver, and doesn't require native stuff which may be causing your problem.
Get the driver from here: http://dev.mysql.com/downloads/connector/j/
Docs on above page.
Docs how to connect: http://dev.mysql.com/doc/refman/5.1/en/connector-j-usagenotes-connect-drivermanager.html#connector-j-examples-connection-drivermanager
Go to the directory:
/usr/lib/jvm/java-7-oracle/jre/lib/amd64/
And rename the file libJdbcOdbc.so to libJdbcOdbcXXX.so
This worked for me.
As a workaround and if SQLAllocEnv is defined in /usr/lib/odbc/libmyodbc.so you could try to force loading it before using JDBC
try {
System.load("/usr/lib/odbc/libmyodbc.so");
} catch (UnsatisfiedLinkError e) {
e.printStackTrace();
}
export LD_PRELOAD=$LD_PRELOAD:/usr/lib/libodbc.so:/usr/lib/libodbcinst.so
once I define this in .bash_profile, source it and it works fine for me.
I've use Adobe native process to run java program from my air app. Here the code and it works fine. But i should write absolute path to java runtime for that:
/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/java.
If user installed java runtime in diff folder, or have diff version then this code would not work. How i can detect where java were installed or maybe there is another right way to run java applications from air applications? If i run java library from terminal command line then i could just write "java -jar pdfbox-app-1.6.0.jar" etc. and it runs fine.
private function convertPdf2Txt():void{
var arg:Vector.<String> = new Vector.<String>;
arg.push("-jar");
arg.push(File.applicationDirectory.resolvePath("pdfbox-app-1.6.0.jar").nativePath);
arg.push("ExtractText");
arg.push("-force");
arg.push(File.applicationStorageDirectory.resolvePath("Data/1.pdf").nativePath);
arg.push(File.applicationStorageDirectory.resolvePath("Data/1.txt").nativePath);
var fjava:File = new File("/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/java");
if (fjava.exists==false){
Alert.show("Can't find Java Runtime in default folder.","Idea Rover",mx.controls.Alert.OK, null,null,imgInfo);
return;
}
var npInfo:NativeProcessStartupInfo;
npInfo = new NativeProcessStartupInfo();
npInfo.executable = fjava;
npInfo.arguments = arg;
var nativeProcess:NativeProcess;
nativeProcess = new NativeProcess();
nativeProcess.addEventListener(NativeProcessExitEvent.EXIT,onNativeProcessExit);
nativeProcess.start(npInfo);
}
Absolute path is:
Mac OS: /usr/bin/java
Win OS: (default)
64bit : C:\Program Files\Java
32bit : C:\Program Files (x86)\Java
rather than popping up an Alert, you could open a file selection dialog, using File.browseForOpen(). then, the File you want is contained in the event passed by the Event.SELECT handler. this flow seems standard for applications i've used that need to access other applications, but aren't sure where to find their executables.
var npInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
// setup npInfo, nativeProcess...
var fjava:File = new File("/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/java");
if (!fjava.exists) {
fjava.addEventListener(Event.SELECT, onFileSelected);
fjava.browseForOpen("Where is Java located?");
}
private function onFileSelected (evt:Event) :void {
npInfo.executable = evt.target;
nativeProcess.start(npInfo);
fjava.removeEventListener(Event.SELECT, onFileSelected);
}
of course, you can use the same logic to find the file java needs to launch as well.
You may be able to determine where the Java binaries are by looking at the JAVA_HOME environment variable. I'd like to do the same thing as you're doing, so I'll post more after I do more research.
Ok, I know that System.getProperty("os.name") will give me the name of the OS I'm running under, but that's not a lot of help. What I need to know is if the OS I'm running on is a 'Unix-like' OS, I don't care if it's HP-UX, AIX, Mac OS X or whatever.
From the list of possible os.name values it seems like a quick and dirty way of detecting a 'Unix-like' OS is checking if os.name does not contain "Windows". The false positives that will give me are OSes my code is very unlikely to encounter! Still, I'd love to know a better way if there is one.
Use the org.apache.commons.lang.SystemUtils utility class from Commons Lang, it has a nice IS_OS_UNIX constant. From the javadoc:
Is true if this is a POSIX compilant
system, as in any of AIX, HP-UX, Irix,
Linux, MacOSX, Solaris or SUN OS.
The field will return false if OS_NAME
is null.
And the test becomes:
if (SystemUtils.IS_OS_UNIX) {
...
}
Simple, effective, easy to read, no cryptic tricks.
I've used your scheme in production code on Windows XP, Vista, Win7, Mac OS 10.3 - 10.6 and a variety of Linux distros without an issue:
if (System.getProperty("os.name").startsWith("Windows")) {
// includes: Windows 2000, Windows 95, Windows 98, Windows NT, Windows Vista, Windows XP
} else {
// everything else
}
Essentially, detect Unix-like by not detecting Windows.
File.listRoots() will give you an array of the file system root directories.
If you are on a Unix-like system, then the array should contain a single entry "/" and on Windows systems you'll get something like ["C:", "D:", ...]
Edit: #chris_l: I totally forgot about mobile phones. Some digging turns up that Android returns a "/\0\0" - a slash followed by two null bytes (assumed to be a bug). Looks like we avoid false positives for the time being through luck and coincidence. Couldn't find good data on other phones, unfortunately.
It's probably not a good idea to run the same code on desktops and mobile phones regardless, but it is interesting to know. Looks like it comes down to needing to check for specific features instead of simply the system type.
Javadoc says: On UNIX systems the value of this
* field is '/'; on Microsoft Windows systems it is '\'.
System.out.println( File.separatorChar == '/' ? "Unix" : "Windows" );
System.getProperty("os.name"); is about the best you are going to get.
I agree with #Fuzzy in that I think the only way that Java intended you to be able to get that information was through the os.name property.
The only other things I can think of are:
Have a shell script or batch file wrapper to launch your Java app that passes in OS information using the -D argument to the JVM. Though given your description, this doesn't sound doable.
You could try to check for the existence of an OS-specific directory. For instance, you could assume the directory "/" will always exist on a Unix-like system, but not on Windows and do something like this:
if((new File("/")).exists())
{
System.out.println("I'm on a Unix system!");
}
Try to kick off a Unix-specific command line command like ls and check the return code. If it worked, you're on a Unix-like system, if not you're on Windows.
All of those solutions are really just hacks though and frankly I don't really feel all that great about any of them. You're unfortunately probably best off with your original thought. Fun, eh?
Use File.pathSeparator or File.separator. The first will return ";" in Windows and ":" in Unix. The second will return "\" in Windows and "/" in Unix.
You could try to execute the uname command - should be available on all unixoid systems.
package com.appspot.x19290;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class UnixCheck {
public static void main(String[] args) {
UnixCheck s = UnixCheck.S;
String isUnix = s.unix ? "is Unix" : "not Unix";
try {
System.out.println(isUnix + ", devnull: " + s.devnull.getPath());
} catch (NullPointerException e) {
System.out.println(isUnix + ", devnull: unknown");
}
}
public static final UnixCheck S = new UnixCheck();
public static final UnixCheck TEST = new UnixCheck(true);
public final boolean unix;
public final File devnull;
private UnixCheck() {
this(false);
}
private UnixCheck(boolean testing) {
String path;
path = testing ? "/<dev>/<no><such><null><device>" : "/dev/null";
File devnull = devnullOrNone(path);
if (devnull == null) {
this.unix = false;
path = testing ? "<no><such><null><device>" : "nul";
this.devnull = devnullOrNone(path);
} else {
this.unix = true;
this.devnull = devnull;
}
}
private static File devnullOrNone(String name) {
File file = new File(name);
if (file.isFile())
return null;
if (file.isDirectory())
return null;
try {
FileInputStream i = new FileInputStream(file);
try {
i.read();
} finally {
i.close();
}
} catch (IOException e) {
return null;
}
return file;
}
}