Commit 2dee7899 authored by Petri Hintukainen's avatar Petri Hintukainen

Fix FileInputStream Java10+ compatibility

parent 49e142f8
/*
* This file is part of libbluray
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*/
package java.io;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
public final class FileDescriptor {
/* for files used by JVM */
private int fd;
private long handle;
private int useCount;
public FileDescriptor() {
fd = -1;
handle = -1;
useCount = 0;
}
private FileDescriptor(int fd) {
this();
this.fd = fd;
}
public static final FileDescriptor in = new FileDescriptor(0);
public static final FileDescriptor out = new FileDescriptor(1);
public static final FileDescriptor err = new FileDescriptor(2);
public boolean valid() {
return (fd != -1) || (handle != -1);
}
public native void sync() throws SyncFailedException;
private static native void initIDs();
static {
initIDs();
}
int incrementAndGetUseCount() {
synchronized (this) {
useCount = useCount + 1;
return useCount;
}
}
int decrementAndGetUseCount() {
synchronized (this) {
useCount = useCount - 1;
return useCount;
}
}
/* Java 8 */
private List parents = null;
private boolean closed = false;
synchronized void attach(Closeable c) {
if (parents == null) {
parents = new ArrayList();
}
parents.add(c);
}
synchronized void closeAll(Closeable releaser) throws IOException {
if (!closed) {
IOException ex = null;
closed = true;
for (Iterator it = parents.iterator(); it.hasNext(); ) {
Closeable c = (Closeable)it.next();
try {
c.close();
} catch (IOException ioe) {
if (ex != null)
ex = ioe;
}
}
releaser.close();
if (ex != null) {
throw ex;
}
}
}
}
......@@ -18,6 +18,7 @@
package java.io;
import java.lang.reflect.InvocationTargetException;
import org.videolan.BDJLoader;
import org.videolan.BDJXletContext;
......@@ -46,7 +47,7 @@ public class FileInputStream extends InputStream
}
fd = new FileDescriptor();
fd.incrementAndGetUseCount();
fdAttach();
if (file.isAbsolute()) {
String cachedName = BDJLoader.getCachedFile(name);
......@@ -82,9 +83,9 @@ public class FileInputStream extends InputStream
if (security != null) {
security.checkRead(fdObj);
}
fdObj.incrementAndGetUseCount();
fd = fdObj;
available = 1024;
fdAttach();
}
/* open()/open0() wrapper to select correct native method at runtime */
......@@ -98,6 +99,7 @@ public class FileInputStream extends InputStream
}
private native int readBytes(byte b[], int off, int len) throws IOException;
/* OpenJDK < 10 */
private native int close0();
/* OpenJDK 6, OpenJDK 7, PhoneME, ... */
private native void open(String name) throws FileNotFoundException;
......@@ -146,7 +148,7 @@ public class FileInputStream extends InputStream
close(true);
}
public void close(boolean force) throws IOException {
private void close(boolean force) throws IOException {
synchronized (closeLock) {
if (closed) {
return;
......@@ -156,14 +158,7 @@ public class FileInputStream extends InputStream
available = 0;
if (fd != null) {
int n = fd.decrementAndGetUseCount();
if (n > 0 && !force) {
return;
}
}
close0();
fdClose(force);
}
public final FileDescriptor getFD() throws IOException {
......@@ -199,4 +194,111 @@ public class FileInputStream extends InputStream
}
}
}
/*
* compat layer
*/
private boolean useFdCount = false;
private void fdAttach() {
/*
* Reflection fails at very early stage in JVM bootstrap.
* -> hide all errors in this function.
*/
try {
try {
fd.getClass().getDeclaredMethod("attach", new Class[] { Closeable.class })
.invoke(fd, new Object[] { (Object)this });
return;
} catch (NoSuchMethodException e) {
/* older RT libs */
}
try {
fd.getClass().getDeclaredMethod("incrementAndGetUseCount", new Class[0]).invoke((Object)fd, new Object[0]);
useFdCount = true;
return;
} catch (NoSuchMethodException e) {
getLogger().error("internal error in FileDescriptor usage");
}
} catch (Throwable t) {
if (logger != null)
logger.error("" + t);
}
}
private void closeImpl() throws IOException {
/* OpenJDK 10+ */
try {
fd.getClass().getDeclaredMethod("close", new Class[0])
.invoke(fd, new Object[0]);
return;
} catch (InvocationTargetException ite) {
Throwable t = ite.getTargetException();
getLogger().error("" + t);
if (t instanceof IOException) {
throw (IOException)t;
}
throw new IOException();
} catch (IllegalAccessException iae) {
getLogger().error("internal error in FileDescriptor usage: " + iae);
return;
} catch (NoSuchMethodException no_jdk10) {
/* JDK < 10 */
}
/* JDK < 10 */
try {
close0();
} catch (UnsatisfiedLinkError no_close0) {
getLogger().error("internal error in FileDescriptor usage: " + no_close0);
}
}
private void fdClose(boolean force) throws IOException {
try {
if (useFdCount) {
try {
Integer i = (Integer) fd.getClass().getDeclaredMethod("decrementAndGetUseCount", new Class[0]).invoke((Object)fd, new Object[0]);
if (i.intValue() > 0 && !force) {
return;
}
closeImpl();
} catch (NoSuchMethodException no_method) {
getLogger().error("internal error in FileDescriptor usage: " + no_method);
}
return;
}
try {
fd.getClass().getDeclaredMethod("closeAll", new Class[] { Closeable.class })
.invoke(fd, new Object[] { (Object)
new Closeable() {
public void close() throws IOException {
closeImpl();
}
}});
return;
} catch (NoSuchMethodException no_closeAll) {
getLogger().error("internal error in FileDescriptor usage: " + no_closeAll);
}
} catch (IllegalAccessException iae) {
getLogger().error("internal error in FileDescriptor usage: " + iae);
return;
} catch (InvocationTargetException ite) {
Throwable t = ite.getTargetException();
getLogger().error("" + t);
if (t instanceof IOException) {
throw (IOException)t;
}
throw new IOException();
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment