mirror of
https://github.com/corda/corda.git
synced 2025-01-13 16:30:25 +00:00
Integrate our deterministic OpenJDK fork with Avian (#117)
* Remove non-deterministic classes from Avian (wip). * Complete integration between Avian and our local OpenJDK fork. * Revert accidental Avian modification. * Implements a "blacklist filter" for Avian's system classloader. * Remove .DSA, .RSA, .SF and .MF files when creating a fat jar. * Revert more accidental Avian changes. * Fix breakage with dependencies, and retain Kryo instance. * Apply blacklisting per thread rather than globally. * Blacklist java.lang.ClassLoader and all java.lang.Thread* classes. * Add comment explaining class blacklisting. * Fix Avian when building without OpenJDK. * Configure ProGuard to keep more classes for deserialisation. * Retain explicit return type for secure random function. * Add sources of random numbers to the class blacklist. * Blacklist the threading classes more precisely. * Make SystemClassLoader.isForbidden() static. * Prevent ProGuard from removing SerializedLambda.readResolve(). * Remove Avian tests involving direct buffers.
This commit is contained in:
parent
6a631ec626
commit
4dbd404f64
@ -219,7 +219,7 @@ private val _newSecureRandom: () -> SecureRandom by lazy {
|
||||
* which should never happen and suggests an unusual JVM or non-standard Java library.
|
||||
*/
|
||||
@Throws(NoSuchAlgorithmException::class)
|
||||
fun newSecureRandom() = _newSecureRandom()
|
||||
fun newSecureRandom(): SecureRandom = _newSecureRandom()
|
||||
|
||||
/**
|
||||
* Returns a random positive non-zero long generated using a secure RNG. This function sacrifies a bit of entropy in order
|
||||
|
@ -1,7 +1,8 @@
|
||||
package net.corda.core.utilities
|
||||
|
||||
object SgxSupport {
|
||||
@JvmStatic
|
||||
val isInsideEnclave: Boolean by lazy {
|
||||
System.getProperty("os.name") == "Linux" && (System.getProperty("java.vm.name") == "Avian")
|
||||
(System.getProperty("os.name") == "Linux") && (System.getProperty("java.vm.name") == "Avian (Corda)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ all: jvm-enclave/standalone/build/standalone_sgx_verify linux-sgx-driver/isgx.ko
|
||||
|
||||
# The final binary
|
||||
jvm-enclave/standalone/build/standalone_sgx_verify: avian linux-sgx/build/linux/aesm_service
|
||||
JAVA_HOME=$(JAVA_HOME) $(MAKE) -C jvm-enclave
|
||||
JAVA_HOME=$(JAVA_HOME) JDK_IMAGE=$(JDK_IMAGE) $(MAKE) -C jvm-enclave
|
||||
|
||||
# Avian with SGX support
|
||||
AVIAN_EXTRA_CFLAGS="-I$(ROOT)/usr/include -I$(ROOT)/usr/include/x86_64-linux-gnu"
|
||||
|
@ -18,6 +18,9 @@ import java.util.Collections;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class SystemClassLoader extends ClassLoader {
|
||||
public static native ClassLoader appLoader();
|
||||
@ -25,6 +28,7 @@ public class SystemClassLoader extends ClassLoader {
|
||||
private native VMClass findVMClass(String name)
|
||||
throws ClassNotFoundException;
|
||||
|
||||
@Override
|
||||
protected Class findClass(String name) throws ClassNotFoundException {
|
||||
return getClass(findVMClass(name));
|
||||
}
|
||||
@ -35,11 +39,54 @@ public class SystemClassLoader extends ClassLoader {
|
||||
|
||||
private native VMClass findLoadedVMClass(String name);
|
||||
|
||||
private static native void startBlacklisting0();
|
||||
|
||||
public void startBlacklisting() {
|
||||
if (isForbidden("java/util/regex/Pattern$Test")) {
|
||||
throw new IllegalStateException("Impossible!");
|
||||
}
|
||||
startBlacklisting0();
|
||||
}
|
||||
|
||||
private static final Set<Pattern> BLACKLIST = Collections.unmodifiableSet(setOf(
|
||||
Pattern.compile("^java/lang/reflect/"),
|
||||
Pattern.compile("^java/lang/invoke/"),
|
||||
Pattern.compile("^java/io/File"),
|
||||
Pattern.compile("^java/net/"),
|
||||
Pattern.compile("^java/.*Random$"),
|
||||
Pattern.compile("^java/util/concurrent/"),
|
||||
Pattern.compile("^java/lang/ClassLoader$"),
|
||||
Pattern.compile("^java/lang/(Inheritable)?ThreadLocal$"),
|
||||
Pattern.compile("^java/lang/Thread$"),
|
||||
Pattern.compile("^com/sun/"),
|
||||
Pattern.compile("^sun/")
|
||||
));
|
||||
|
||||
private static <T> Set<T> setOf(T... items) {
|
||||
Set<T> set = new LinkedHashSet<T>();
|
||||
Collections.addAll(set, items);
|
||||
return set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoked via JNI, so uses the specification
|
||||
* rather than the class name.
|
||||
*/
|
||||
private static boolean isForbidden(String spec) {
|
||||
for (Pattern bad : BLACKLIST) {
|
||||
if (bad.matcher(spec).find()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected Class reallyFindLoadedClass(String name){
|
||||
VMClass c = findLoadedVMClass(name);
|
||||
return c == null ? null : getClass(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class loadClass(String name, boolean resolve)
|
||||
throws ClassNotFoundException
|
||||
{
|
||||
@ -83,6 +130,7 @@ public class SystemClassLoader extends ClassLoader {
|
||||
// appropriate for the Avian build, so we override it to ensure we
|
||||
// get the behavior we want. This implementation is the same as
|
||||
// that of Avian's java.lang.ClassLoader.getResource.
|
||||
@Override
|
||||
public URL getResource(String path) {
|
||||
URL url = null;
|
||||
ClassLoader parent = getParent();
|
||||
@ -99,6 +147,7 @@ public class SystemClassLoader extends ClassLoader {
|
||||
|
||||
// As above, we override this method to avoid inappropriate behavior
|
||||
// in OpenJDK's java.lang.ClassLoader.getResources.
|
||||
@Override
|
||||
public Enumeration<URL> getResources(String name) throws IOException {
|
||||
Collection<URL> urls = new ArrayList<URL>(5);
|
||||
|
||||
|
@ -1,148 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package avian.http;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.Socket;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLStreamHandler;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Handler extends URLStreamHandler
|
||||
{
|
||||
public URLConnection openConnection(URL url) throws IOException
|
||||
{
|
||||
return new HttpURLConnection(url);
|
||||
}
|
||||
|
||||
class HttpURLConnection extends URLConnection
|
||||
{
|
||||
private static final String HKEY_CONTENT_LENGTH = "content-length";
|
||||
|
||||
Socket socket;
|
||||
private BufferedWriter writer;
|
||||
private InputStream bin;
|
||||
private Map<String, List<String>> header = new HashMap<String, List<String>>();
|
||||
private int status;
|
||||
|
||||
protected HttpURLConnection(URL url)
|
||||
{
|
||||
super(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() throws IOException
|
||||
{
|
||||
if(socket == null)
|
||||
{
|
||||
URLConnection con = null;
|
||||
String host = url.getHost();
|
||||
int port =url.getPort();
|
||||
if(port < 0) port = 80;
|
||||
socket = new Socket(host, port);
|
||||
OutputStream out = socket.getOutputStream();
|
||||
writer = new BufferedWriter(new OutputStreamWriter(out));
|
||||
writer.write("GET " + url.getPath() + " HTTP/1.1");
|
||||
writer.write("\r\nHost: " + host);
|
||||
writer.write("\r\n\r\n");
|
||||
writer.flush();
|
||||
bin = new BufferedInputStream(socket.getInputStream());
|
||||
readHeader();
|
||||
// System.out.println("Status: " + status);
|
||||
// System.out.println("Headers: " + header);
|
||||
}
|
||||
}
|
||||
|
||||
private void readHeader() throws IOException
|
||||
{
|
||||
byte[] buf = new byte[8192];
|
||||
int b = 0;
|
||||
int index = 0;
|
||||
while(b >= 0)
|
||||
{
|
||||
if(index >= 4 && buf[index-4] == '\r' && buf[index-3] == '\n' && buf[index-2] == '\r' && buf[index-1] == '\n')
|
||||
{
|
||||
break;
|
||||
}
|
||||
b = bin.read();
|
||||
buf[index] = (byte) b;
|
||||
index++;
|
||||
if(index >= buf.length)
|
||||
{
|
||||
throw new IOException("Header exceeded maximum size of 8k.");
|
||||
}
|
||||
}
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(buf, 0, index)));
|
||||
String line = reader.readLine();
|
||||
int x = line.indexOf(' ');
|
||||
status = Integer.parseInt(line.substring(x + 1 , line.indexOf(' ', x+1)));
|
||||
while(line != null)
|
||||
{
|
||||
int i = line.indexOf(':');
|
||||
if(i > 0)
|
||||
{
|
||||
String key = line.substring(0, i).toLowerCase();
|
||||
String value = line.substring(i + 1).trim();
|
||||
|
||||
List<String> valueList = new ArrayList<String>();
|
||||
valueList.add(value);
|
||||
header.put(key, Collections.unmodifiableList(valueList));
|
||||
}
|
||||
line = reader.readLine();
|
||||
}
|
||||
reader.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException
|
||||
{
|
||||
connect();
|
||||
return bin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getOutputStream() throws IOException
|
||||
{
|
||||
throw new UnsupportedOperationException("Can' write to HTTP Connection");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentLength()
|
||||
{
|
||||
return getHeaderFieldInt(HKEY_CONTENT_LENGTH, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getContentLengthLong()
|
||||
{
|
||||
return getHeaderFieldLong(HKEY_CONTENT_LENGTH, -1l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String,List<String>> getHeaderFields()
|
||||
{
|
||||
return Collections.unmodifiableMap(header);
|
||||
}
|
||||
}
|
||||
}
|
@ -347,65 +347,6 @@ extern "C" JNIEXPORT jlong JNICALL
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_io_File_mkdir(JNIEnv* e, jclass, jstring path)
|
||||
{
|
||||
string_t chars = getChars(e, path);
|
||||
if (chars) {
|
||||
if (not exists(chars)) {
|
||||
int r = ::MKDIR(chars, 0777);
|
||||
if (r != 0) {
|
||||
throwNewErrno(e, "java/io/IOException");
|
||||
}
|
||||
}
|
||||
releaseChars(e, path, chars);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_java_io_File_createNewFile(JNIEnv* e, jclass, jstring path)
|
||||
{
|
||||
bool result = false;
|
||||
string_t chars = getChars(e, path);
|
||||
if (chars) {
|
||||
if (not exists(chars)) {
|
||||
int fd = OPEN(chars, O_CREAT | O_WRONLY | O_EXCL, 0666);
|
||||
if (fd == -1) {
|
||||
if (errno != EEXIST) {
|
||||
throwNewErrno(e, "java/io/IOException");
|
||||
}
|
||||
} else {
|
||||
result = true;
|
||||
doClose(e, fd);
|
||||
}
|
||||
}
|
||||
releaseChars(e, path, chars);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_io_File_delete(JNIEnv* e, jclass, jstring path)
|
||||
{
|
||||
string_t chars = getChars(e, path);
|
||||
int r;
|
||||
if (chars) {
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
if (GetFileAttributes(chars) & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
r = !RemoveDirectory(chars);
|
||||
} else {
|
||||
r = REMOVE(chars);
|
||||
}
|
||||
#else
|
||||
r = REMOVE(chars);
|
||||
#endif
|
||||
if (r != 0) {
|
||||
throwNewErrno(e, "java/io/IOException");
|
||||
}
|
||||
releaseChars(e, path, chars);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_java_io_File_canRead(JNIEnv* e, jclass, jstring path)
|
||||
{
|
||||
@ -497,27 +438,6 @@ extern "C" JNIEXPORT jboolean JNICALL
|
||||
|
||||
#endif
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_java_io_File_rename(JNIEnv* e, jclass, jstring old, jstring new_)
|
||||
{
|
||||
string_t oldChars = getChars(e, old);
|
||||
string_t newChars = getChars(e, new_);
|
||||
if (oldChars) {
|
||||
bool v;
|
||||
if (newChars) {
|
||||
v = RENAME(oldChars, newChars) == 0;
|
||||
|
||||
releaseChars(e, new_, newChars);
|
||||
} else {
|
||||
v = false;
|
||||
}
|
||||
releaseChars(e, old, oldChars);
|
||||
return v;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_java_io_File_isDirectory(JNIEnv* e, jclass, jstring path)
|
||||
{
|
||||
|
@ -376,103 +376,6 @@ void copyAndEscape(char** dest, const char* src, size_t length)
|
||||
*dest = destp;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_lang_Runtime_exec(JNIEnv* e,
|
||||
jclass,
|
||||
jobjectArray command,
|
||||
jlongArray process)
|
||||
{
|
||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
int size = 0;
|
||||
for (int i = 0; i < e->GetArrayLength(command); ++i) {
|
||||
jstring element = (jstring)e->GetObjectArrayElement(command, i);
|
||||
if (element) {
|
||||
// worst case, assuming every character is '"', and we escape all of them
|
||||
size += 2 * e->GetStringUTFLength(element) + 3;
|
||||
} else {
|
||||
throwNew(e,
|
||||
"java/lang/NullPointerException",
|
||||
strdup("null string array element"));
|
||||
}
|
||||
}
|
||||
|
||||
RUNTIME_ARRAY(char, line, size);
|
||||
char* linep = RUNTIME_ARRAY_BODY(line);
|
||||
for (int i = 0; i < e->GetArrayLength(command); ++i) {
|
||||
if (i)
|
||||
*(linep++) = _T(' ');
|
||||
jstring element = (jstring)e->GetObjectArrayElement(command, i);
|
||||
const char* s = e->GetStringUTFChars(element, 0);
|
||||
|
||||
copyAndEscape(&linep, s, e->GetStringUTFLength(element));
|
||||
|
||||
e->ReleaseStringUTFChars(element, s);
|
||||
}
|
||||
*(linep++) = _T('\0');
|
||||
|
||||
HANDLE in[] = {0, 0};
|
||||
HANDLE out[] = {0, 0};
|
||||
HANDLE err[] = {0, 0};
|
||||
|
||||
makePipe(e, in);
|
||||
SetHandleInformation(in[0], HANDLE_FLAG_INHERIT, 0);
|
||||
jlong inDescriptor = static_cast<jlong>(descriptor(e, in[0]));
|
||||
if (e->ExceptionCheck())
|
||||
return;
|
||||
e->SetLongArrayRegion(process, 2, 1, &inDescriptor);
|
||||
makePipe(e, out);
|
||||
SetHandleInformation(out[1], HANDLE_FLAG_INHERIT, 0);
|
||||
jlong outDescriptor = static_cast<jlong>(descriptor(e, out[1]));
|
||||
if (e->ExceptionCheck())
|
||||
return;
|
||||
e->SetLongArrayRegion(process, 3, 1, &outDescriptor);
|
||||
makePipe(e, err);
|
||||
SetHandleInformation(err[0], HANDLE_FLAG_INHERIT, 0);
|
||||
jlong errDescriptor = static_cast<jlong>(descriptor(e, err[0]));
|
||||
if (e->ExceptionCheck())
|
||||
return;
|
||||
e->SetLongArrayRegion(process, 4, 1, &errDescriptor);
|
||||
|
||||
PROCESS_INFORMATION pi;
|
||||
ZeroMemory(&pi, sizeof(pi));
|
||||
|
||||
STARTUPINFO si;
|
||||
ZeroMemory(&si, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
si.dwFlags = STARTF_USESTDHANDLES;
|
||||
si.hStdOutput = in[1];
|
||||
si.hStdInput = out[0];
|
||||
si.hStdError = err[1];
|
||||
|
||||
BOOL success = CreateProcess(0,
|
||||
(LPSTR)RUNTIME_ARRAY_BODY(line),
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT,
|
||||
0,
|
||||
0,
|
||||
&si,
|
||||
&pi);
|
||||
|
||||
CloseHandle(in[1]);
|
||||
CloseHandle(out[0]);
|
||||
CloseHandle(err[1]);
|
||||
|
||||
if (not success) {
|
||||
throwNew(e, "java/io/IOException", getErrorStr(GetLastError()));
|
||||
return;
|
||||
}
|
||||
|
||||
jlong pid = reinterpret_cast<jlong>(pi.hProcess);
|
||||
e->SetLongArrayRegion(process, 0, 1, &pid);
|
||||
jlong tid = reinterpret_cast<jlong>(pi.hThread);
|
||||
e->SetLongArrayRegion(process, 1, 1, &tid);
|
||||
#else
|
||||
throwNew(e, "java/io/Exception", strdup("Not supported on WinRT/WinPhone8"));
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid, jlong tid)
|
||||
{
|
||||
@ -1003,60 +906,6 @@ extern "C" JNIEXPORT jobjectArray JNICALL
|
||||
return array;
|
||||
}
|
||||
|
||||
// System.getEnvironment() implementation
|
||||
// TODO: For Win32, replace usage of deprecated _environ and add Unicode
|
||||
// support (neither of which is likely to be of great importance).
|
||||
#ifdef AVIAN_IOS
|
||||
namespace {
|
||||
const char* environ[] = {0};
|
||||
}
|
||||
#elif defined __APPLE__
|
||||
#include <crt_externs.h>
|
||||
#define environ (*_NSGetEnviron())
|
||||
#elif defined(WINAPI_FAMILY) \
|
||||
&& !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
// WinRT/WP8 does not provide alternative for environment variables
|
||||
char* environ[] = {0};
|
||||
#else
|
||||
extern char** environ;
|
||||
#endif
|
||||
extern "C" JNIEXPORT jobjectArray JNICALL
|
||||
Java_java_lang_System_getEnvironment(JNIEnv* env, jclass)
|
||||
{
|
||||
int length;
|
||||
for (length = 0; environ[length] != 0; ++length)
|
||||
;
|
||||
|
||||
jobjectArray stringArray = env->NewObjectArray(
|
||||
length, env->FindClass("java/lang/String"), env->NewStringUTF(""));
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
jobject varString = env->NewStringUTF(environ[i]);
|
||||
env->SetObjectArrayElement(stringArray, i, varString);
|
||||
}
|
||||
|
||||
return stringArray;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_java_lang_System_currentTimeMillis(JNIEnv*, jclass)
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
// We used to use _ftime here, but that only gives us 1-second
|
||||
// resolution on Windows 7. _ftime_s might work better, but MinGW
|
||||
// doesn't have it as of this writing. So we use this mess instead:
|
||||
FILETIME time;
|
||||
GetSystemTimeAsFileTime(&time);
|
||||
return (((static_cast<jlong>(time.dwHighDateTime) << 32) | time.dwLowDateTime)
|
||||
/ 10000) - 11644473600000LL;
|
||||
#else
|
||||
timeval tv = {0, 0};
|
||||
gettimeofday(&tv, 0);
|
||||
return (static_cast<jlong>(tv.tv_sec) * 1000)
|
||||
+ (static_cast<jlong>(tv.tv_usec) / 1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jstring JNICALL
|
||||
Java_java_lang_System_doMapLibraryName(JNIEnv* e, jclass, jstring name)
|
||||
{
|
||||
|
@ -1,145 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#ifndef SGX
|
||||
|
||||
#include "jni.h"
|
||||
#include "avian/machine.h"
|
||||
#include "sockets.h"
|
||||
#include "jni-util.h"
|
||||
|
||||
using namespace avian::classpath::sockets;
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL Java_java_net_Socket_init(JNIEnv* e, jclass)
|
||||
{
|
||||
init(e);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT SOCKET JNICALL
|
||||
Java_java_net_Socket_create(JNIEnv* e, jclass)
|
||||
{
|
||||
return create(e);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL Java_java_net_Socket_connect(JNIEnv* e,
|
||||
jclass,
|
||||
jlong sock,
|
||||
jlong addr,
|
||||
jshort port)
|
||||
{
|
||||
connect(e, static_cast<SOCKET>(sock), addr, port);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL Java_java_net_Socket_bind(JNIEnv* e,
|
||||
jclass,
|
||||
jlong sock,
|
||||
jlong addr,
|
||||
jshort port)
|
||||
{
|
||||
bind(e, static_cast<SOCKET>(sock), addr, port);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_net_Socket_abort(JNIEnv* e, jclass, jlong sock)
|
||||
{
|
||||
abort(e, static_cast<SOCKET>(sock));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_net_Socket_close(JNIEnv* e, jclass, jlong sock)
|
||||
{
|
||||
close(e, static_cast<SOCKET>(sock));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_net_Socket_closeOutput(JNIEnv* e, jclass, jlong sock)
|
||||
{
|
||||
close_output(e, static_cast<SOCKET>(sock));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_net_Socket_closeInput(JNIEnv* e, jclass, jlong sock)
|
||||
{
|
||||
close_input(e, static_cast<SOCKET>(sock));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_java_net_Socket_send(vm::Thread* t, vm::object, uintptr_t* arguments)
|
||||
{ /* SOCKET s, object buffer_obj, int start_pos, int count */
|
||||
SOCKET& s = *(reinterpret_cast<SOCKET*>(&arguments[0]));
|
||||
vm::GcByteArray* buffer_obj = vm::cast<vm::GcByteArray>(
|
||||
t, reinterpret_cast<vm::object>(arguments[2]));
|
||||
int32_t& start_pos = *(reinterpret_cast<int32_t*>(&arguments[3]));
|
||||
int32_t& count = *(reinterpret_cast<int32_t*>(&arguments[4]));
|
||||
char* buffer = reinterpret_cast<char*>(&buffer_obj->body()[start_pos]);
|
||||
avian::classpath::sockets::send((JNIEnv*)t, s, buffer, count);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_java_net_Socket_recv(vm::Thread* t, vm::object, uintptr_t* arguments)
|
||||
{ /* SOCKET s, object buffer_obj, int start_pos, int count */
|
||||
SOCKET& s = *(reinterpret_cast<SOCKET*>(&arguments[0]));
|
||||
vm::GcByteArray* buffer_obj = vm::cast<vm::GcByteArray>(
|
||||
t, reinterpret_cast<vm::object>(arguments[2]));
|
||||
int32_t& start_pos = *(reinterpret_cast<int32_t*>(&arguments[3]));
|
||||
int32_t& count = *(reinterpret_cast<int32_t*>(&arguments[4]));
|
||||
char* buffer = reinterpret_cast<char*>(&buffer_obj->body()[start_pos]);
|
||||
return avian::classpath::sockets::recv((JNIEnv*)t, s, buffer, count);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_net_InetAddress_ipv4AddressForName(JNIEnv* e,
|
||||
jclass,
|
||||
jstring name)
|
||||
{
|
||||
if(!name) {
|
||||
throwNew(e, "java/lang/NullPointerException", 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* chars = e->GetStringUTFChars(name, 0);
|
||||
if (chars) {
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
hostent* host = gethostbyname(chars);
|
||||
e->ReleaseStringUTFChars(name, chars);
|
||||
if (host) {
|
||||
return ntohl(reinterpret_cast<in_addr*>(host->h_addr_list[0])->s_addr);
|
||||
} else {
|
||||
throwNew(e, "java/net/UnknownHostException", 0);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
addrinfo hints;
|
||||
memset(&hints, 0, sizeof(addrinfo));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
addrinfo* result;
|
||||
int r = getaddrinfo(chars, 0, &hints, &result);
|
||||
e->ReleaseStringUTFChars(name, chars);
|
||||
|
||||
if (r != 0) {
|
||||
throwNew(e, "java/net/UnknownHostException", 0);
|
||||
return 0;
|
||||
} else {
|
||||
int address = ntohl(
|
||||
reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr);
|
||||
|
||||
freeaddrinfo(result);
|
||||
return address;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
throwNew(e, "java/lang/OutOfMemoryError", 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !SGX
|
@ -85,18 +85,6 @@ inline jbyteArray errorString(JNIEnv* e, int n)
|
||||
#endif
|
||||
}
|
||||
|
||||
inline jbyteArray socketErrorString(JNIEnv* e, int n)
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
const unsigned size = 64;
|
||||
char buffer[size];
|
||||
snprintf(buffer, size, "wsa code: %d", n);
|
||||
return charsToArray(e, buffer);
|
||||
#else
|
||||
return errorString(e, n);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline jbyteArray errorString(JNIEnv* e)
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
@ -132,37 +120,6 @@ void throwIOException(JNIEnv* e)
|
||||
throwIOException(e, errorString(e));
|
||||
}
|
||||
|
||||
void throwSocketException(JNIEnv* e, const char* s)
|
||||
{
|
||||
throwNew(e, "java/net/SocketException", s);
|
||||
}
|
||||
|
||||
void throwSocketException(JNIEnv* e, jbyteArray a)
|
||||
{
|
||||
size_t length = e->GetArrayLength(a);
|
||||
uint8_t* buf = static_cast<uint8_t*>(allocate(e, length));
|
||||
if (buf) {
|
||||
e->GetByteArrayRegion(a, 0, length, reinterpret_cast<jbyte*>(buf));
|
||||
throwSocketException(e, reinterpret_cast<const char*>(buf));
|
||||
free(buf);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void throwSocketException(JNIEnv* e)
|
||||
{
|
||||
throwSocketException(e, errorString(e));
|
||||
}
|
||||
|
||||
void init(sockaddr_in* address, jint host, jint port)
|
||||
{
|
||||
memset(address, 0, sizeof(sockaddr_in));
|
||||
address->sin_family = AF_INET;
|
||||
address->sin_port = htons(port);
|
||||
address->sin_addr.s_addr = htonl(host);
|
||||
}
|
||||
|
||||
inline bool einProgress(int error)
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
@ -172,26 +129,6 @@ inline bool einProgress(int error)
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool einProgress()
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
return WSAGetLastError() == WSAEINPROGRESS
|
||||
or WSAGetLastError() == WSAEWOULDBLOCK;
|
||||
#else
|
||||
return errno == EINPROGRESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool eagain()
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
return WSAGetLastError() == WSAEINPROGRESS
|
||||
or WSAGetLastError() == WSAEWOULDBLOCK;
|
||||
#else
|
||||
return errno == EAGAIN;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool setBlocking(JNIEnv* e, int d, bool blocking)
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
@ -214,609 +151,32 @@ bool setBlocking(JNIEnv* e, int d, bool blocking)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool setTcpNoDelay(JNIEnv* e, int d, bool on)
|
||||
{
|
||||
int flag = on;
|
||||
int r = setsockopt(
|
||||
d, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&flag), sizeof(int));
|
||||
if (r < 0) {
|
||||
throwSocketException(e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void doBind(JNIEnv* e, int s, sockaddr_in* address)
|
||||
{
|
||||
{
|
||||
int opt = 1;
|
||||
int r = ::setsockopt(s,
|
||||
SOL_SOCKET,
|
||||
SO_REUSEADDR,
|
||||
reinterpret_cast<char*>(&opt),
|
||||
sizeof(int));
|
||||
if (r != 0) {
|
||||
throwIOException(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SO_NOSIGPIPE
|
||||
{
|
||||
int opt = 1;
|
||||
int r = ::setsockopt(s,
|
||||
SOL_SOCKET,
|
||||
SO_NOSIGPIPE,
|
||||
reinterpret_cast<char*>(&opt),
|
||||
sizeof(int));
|
||||
if (r != 0) {
|
||||
throwIOException(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
int r
|
||||
= ::bind(s, reinterpret_cast<sockaddr*>(address), sizeof(sockaddr_in));
|
||||
if (r != 0) {
|
||||
throwIOException(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void doListen(JNIEnv* e, int s)
|
||||
{
|
||||
int r = ::listen(s, 100);
|
||||
if (r != 0) {
|
||||
throwIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
void doFinishConnect(JNIEnv* e, int socket)
|
||||
{
|
||||
int error;
|
||||
socklen_t size = sizeof(int);
|
||||
int r = getsockopt(
|
||||
socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&error), &size);
|
||||
|
||||
if (r != 0 or size != sizeof(int)) {
|
||||
throwIOException(e);
|
||||
} else if (error and not einProgress(error)) {
|
||||
throwIOException(e, socketErrorString(e, error));
|
||||
}
|
||||
}
|
||||
|
||||
bool doConnect(JNIEnv* e, int s, sockaddr_in* address)
|
||||
{
|
||||
int r
|
||||
= ::connect(s, reinterpret_cast<sockaddr*>(address), sizeof(sockaddr_in));
|
||||
if (r == 0) {
|
||||
return true;
|
||||
} else if (not einProgress()) {
|
||||
throwIOException(e);
|
||||
return false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int doAccept(JNIEnv* e, int s)
|
||||
{
|
||||
sockaddr address;
|
||||
socklen_t length = sizeof(address);
|
||||
int r = ::accept(s, &address, &length);
|
||||
if (r >= 0) {
|
||||
return r;
|
||||
} else if (errno != EINTR) {
|
||||
throwIOException(e);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int doRead(int fd, void* buffer, size_t count)
|
||||
inline bool einProgress()
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
return recv(fd, static_cast<char*>(buffer), count, 0);
|
||||
return WSAGetLastError() == WSAEINPROGRESS
|
||||
or WSAGetLastError() == WSAEWOULDBLOCK;
|
||||
#else
|
||||
return read(fd, buffer, count);
|
||||
return errno == EINPROGRESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
int doRecv(int fd, void* buffer, size_t count, int32_t* host, int32_t* port)
|
||||
{
|
||||
sockaddr address;
|
||||
socklen_t length = sizeof(address);
|
||||
int r = recvfrom(fd, static_cast<char*>(buffer), count, 0, &address, &length);
|
||||
|
||||
if (r > 0) {
|
||||
sockaddr_in a;
|
||||
memcpy(&a, &address, length);
|
||||
*host = ntohl(a.sin_addr.s_addr);
|
||||
*port = ntohs(a.sin_port);
|
||||
} else {
|
||||
*host = 0;
|
||||
*port = 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int doWrite(int fd, const void* buffer, size_t count)
|
||||
inline bool eagain()
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
return send(fd, static_cast<const char*>(buffer), count, 0);
|
||||
return WSAGetLastError() == WSAEINPROGRESS
|
||||
or WSAGetLastError() == WSAEWOULDBLOCK;
|
||||
#else
|
||||
return write(fd, buffer, count);
|
||||
return errno == EAGAIN;
|
||||
#endif
|
||||
}
|
||||
|
||||
int doSend(int fd, sockaddr_in* address, const void* buffer, size_t count)
|
||||
{
|
||||
return sendto(fd,
|
||||
static_cast<const char*>(buffer),
|
||||
count,
|
||||
0,
|
||||
reinterpret_cast<sockaddr*>(address),
|
||||
sizeof(sockaddr_in));
|
||||
}
|
||||
|
||||
int makeSocket(JNIEnv* e, int type = SOCK_STREAM, int protocol = IPPROTO_TCP)
|
||||
{
|
||||
int s = ::socket(AF_INET, type, protocol);
|
||||
if (s < 0) {
|
||||
throwIOException(e);
|
||||
return s;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace <anonymous>
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_nio_channels_ServerSocketChannel_natDoAccept(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket)
|
||||
{
|
||||
return ::doAccept(e, socket);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_ServerSocketChannel_natDoListen(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket,
|
||||
jint host,
|
||||
jint port)
|
||||
{
|
||||
sockaddr_in address;
|
||||
init(&address, host, port);
|
||||
|
||||
::doBind(e, socket, &address);
|
||||
if (e->ExceptionCheck())
|
||||
return;
|
||||
|
||||
::doListen(e, socket);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_SocketChannel_bind(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket,
|
||||
jint host,
|
||||
jint port)
|
||||
{
|
||||
sockaddr_in address;
|
||||
init(&address, host, port);
|
||||
|
||||
::doBind(e, socket, &address);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_DatagramChannel_bind(JNIEnv* e,
|
||||
jclass c,
|
||||
jint socket,
|
||||
jint host,
|
||||
jint port)
|
||||
{
|
||||
Java_java_nio_channels_SocketChannel_bind(e, c, socket, host, port);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_SocketChannel_configureBlocking(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket,
|
||||
jboolean blocking)
|
||||
{
|
||||
setBlocking(e, socket, blocking);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_DatagramChannel_configureBlocking(JNIEnv* e,
|
||||
jclass c,
|
||||
jint socket,
|
||||
jboolean blocking)
|
||||
{
|
||||
return Java_java_nio_channels_SocketChannel_configureBlocking(
|
||||
e, c, socket, blocking);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_SocketChannel_natSetTcpNoDelay(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket,
|
||||
jboolean on)
|
||||
{
|
||||
setTcpNoDelay(e, socket, on);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_java_nio_channels_SocketChannel_natDoConnect(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket,
|
||||
jint host,
|
||||
jint port)
|
||||
{
|
||||
sockaddr_in address;
|
||||
init(&address, host, port);
|
||||
|
||||
return ::doConnect(e, socket, &address);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_nio_channels_SocketChannel_makeSocket(JNIEnv* e, jclass)
|
||||
{
|
||||
return makeSocket(e);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_nio_channels_DatagramChannel_makeSocket(JNIEnv* e, jclass)
|
||||
{
|
||||
return makeSocket(e, SOCK_DGRAM, IPPROTO_UDP);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_java_nio_channels_DatagramChannel_connect(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket,
|
||||
jint host,
|
||||
jint port)
|
||||
{
|
||||
sockaddr_in address;
|
||||
init(&address, host, port);
|
||||
|
||||
return ::doConnect(e, socket, &address);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_SocketChannel_natFinishConnect(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket)
|
||||
{
|
||||
doFinishConnect(e, socket);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_nio_channels_SocketChannel_natRead(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket,
|
||||
jbyteArray buffer,
|
||||
jint offset,
|
||||
jint length,
|
||||
jboolean blocking)
|
||||
{
|
||||
int r;
|
||||
if (blocking) {
|
||||
uint8_t* buf = static_cast<uint8_t*>(allocate(e, length));
|
||||
if (buf) {
|
||||
r = ::doRead(socket, buf, length);
|
||||
if (r > 0) {
|
||||
e->SetByteArrayRegion(buffer, offset, r, reinterpret_cast<jbyte*>(buf));
|
||||
}
|
||||
free(buf);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
jboolean isCopy;
|
||||
uint8_t* buf
|
||||
= static_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, &isCopy));
|
||||
|
||||
r = ::doRead(socket, buf + offset, length);
|
||||
|
||||
e->ReleasePrimitiveArrayCritical(buffer, buf, 0);
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
if (eagain()) {
|
||||
return 0;
|
||||
} else {
|
||||
throwIOException(e);
|
||||
}
|
||||
} else if (r == 0) {
|
||||
return -1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket,
|
||||
jbyteArray buffer,
|
||||
jint offset,
|
||||
jint length,
|
||||
jboolean blocking,
|
||||
jintArray address)
|
||||
{
|
||||
int r;
|
||||
int32_t host;
|
||||
int32_t port;
|
||||
if (blocking) {
|
||||
uint8_t* buf = static_cast<uint8_t*>(allocate(e, length));
|
||||
if (buf) {
|
||||
r = ::doRecv(socket, buf, length, &host, &port);
|
||||
if (r > 0) {
|
||||
e->SetByteArrayRegion(buffer, offset, r, reinterpret_cast<jbyte*>(buf));
|
||||
}
|
||||
free(buf);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
jboolean isCopy;
|
||||
uint8_t* buf
|
||||
= static_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, &isCopy));
|
||||
|
||||
r = ::doRecv(socket, buf + offset, length, &host, &port);
|
||||
|
||||
e->ReleasePrimitiveArrayCritical(buffer, buf, 0);
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
if (eagain()) {
|
||||
return 0;
|
||||
} else {
|
||||
throwIOException(e);
|
||||
}
|
||||
} else if (r == 0) {
|
||||
return -1;
|
||||
} else {
|
||||
jint jhost = host;
|
||||
e->SetIntArrayRegion(address, 0, 1, &jhost);
|
||||
jint jport = port;
|
||||
e->SetIntArrayRegion(address, 1, 1, &jport);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_nio_channels_SocketChannel_natWrite(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket,
|
||||
jbyteArray buffer,
|
||||
jint offset,
|
||||
jint length,
|
||||
jboolean blocking)
|
||||
{
|
||||
int r;
|
||||
if (blocking) {
|
||||
uint8_t* buf = static_cast<uint8_t*>(allocate(e, length));
|
||||
if (buf) {
|
||||
e->GetByteArrayRegion(
|
||||
buffer, offset, length, reinterpret_cast<jbyte*>(buf));
|
||||
r = ::doWrite(socket, buf, length);
|
||||
free(buf);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
jboolean isCopy;
|
||||
uint8_t* buf
|
||||
= static_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, &isCopy));
|
||||
|
||||
r = ::doWrite(socket, buf + offset, length);
|
||||
|
||||
e->ReleasePrimitiveArrayCritical(buffer, buf, 0);
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
if (eagain()) {
|
||||
return 0;
|
||||
} else {
|
||||
throwIOException(e);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_nio_channels_DatagramChannel_write(JNIEnv* e,
|
||||
jclass c,
|
||||
jint socket,
|
||||
jbyteArray buffer,
|
||||
jint offset,
|
||||
jint length,
|
||||
jboolean blocking)
|
||||
{
|
||||
return Java_java_nio_channels_SocketChannel_natWrite(
|
||||
e, c, socket, buffer, offset, length, blocking);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_nio_channels_DatagramChannel_send(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket,
|
||||
jint host,
|
||||
jint port,
|
||||
jbyteArray buffer,
|
||||
jint offset,
|
||||
jint length,
|
||||
jboolean blocking)
|
||||
{
|
||||
sockaddr_in address;
|
||||
init(&address, host, port);
|
||||
|
||||
int r;
|
||||
if (blocking) {
|
||||
uint8_t* buf = static_cast<uint8_t*>(allocate(e, length));
|
||||
if (buf) {
|
||||
e->GetByteArrayRegion(
|
||||
buffer, offset, length, reinterpret_cast<jbyte*>(buf));
|
||||
r = ::doSend(socket, &address, buf, length);
|
||||
free(buf);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
jboolean isCopy;
|
||||
uint8_t* buf
|
||||
= static_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, &isCopy));
|
||||
|
||||
r = ::doSend(socket, &address, buf + offset, length);
|
||||
|
||||
e->ReleasePrimitiveArrayCritical(buffer, buf, 0);
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
if (eagain()) {
|
||||
return 0;
|
||||
} else {
|
||||
throwIOException(e);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_SocketChannel_natThrowWriteError(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket)
|
||||
{
|
||||
int error;
|
||||
socklen_t size = sizeof(int);
|
||||
int r = getsockopt(
|
||||
socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&error), &size);
|
||||
if (r != 0 or size != sizeof(int)) {
|
||||
throwIOException(e);
|
||||
} else if (error != 0) {
|
||||
throwIOException(e, socketErrorString(e, error));
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_SocketChannel_natCloseSocket(JNIEnv*,
|
||||
jclass,
|
||||
jint socket)
|
||||
{
|
||||
doClose(socket);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_DatagramChannel_close(JNIEnv*, jclass, jint socket)
|
||||
{
|
||||
doClose(socket);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class Pipe {
|
||||
public:
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
// The Windows socket API only accepts socket file descriptors, not
|
||||
// pipe descriptors or others. Thus, to implement
|
||||
// Selector.wakeup(), we make a socket connection via the loopback
|
||||
// interface and use it as a pipe.
|
||||
Pipe(JNIEnv* e) : connected_(false), listener_(-1), reader_(-1), writer_(-1)
|
||||
{
|
||||
sockaddr_in address;
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_port = 0;
|
||||
address.sin_addr.s_addr = inet_addr("127.0.0.1"); // INADDR_LOOPBACK;
|
||||
|
||||
listener_ = makeSocket(e);
|
||||
if (e->ExceptionCheck())
|
||||
return;
|
||||
|
||||
setBlocking(e, listener_, false);
|
||||
|
||||
::doBind(e, listener_, &address);
|
||||
if (e->ExceptionCheck())
|
||||
return;
|
||||
|
||||
::doListen(e, listener_);
|
||||
if (e->ExceptionCheck())
|
||||
return;
|
||||
|
||||
socklen_t length = sizeof(sockaddr_in);
|
||||
int r = getsockname(
|
||||
listener_, reinterpret_cast<sockaddr*>(&address), &length);
|
||||
if (r) {
|
||||
throwIOException(e);
|
||||
return;
|
||||
}
|
||||
|
||||
writer_ = makeSocket(e);
|
||||
if (e->ExceptionCheck())
|
||||
return;
|
||||
|
||||
setBlocking(e, writer_, true);
|
||||
connected_ = ::doConnect(e, writer_, &address);
|
||||
}
|
||||
|
||||
void dispose()
|
||||
{
|
||||
if (listener_ >= 0)
|
||||
::doClose(listener_);
|
||||
if (reader_ >= 0)
|
||||
::doClose(reader_);
|
||||
if (writer_ >= 0)
|
||||
::doClose(writer_);
|
||||
}
|
||||
|
||||
bool connected()
|
||||
{
|
||||
return connected_;
|
||||
}
|
||||
|
||||
void setConnected(bool v)
|
||||
{
|
||||
connected_ = v;
|
||||
}
|
||||
|
||||
int listener()
|
||||
{
|
||||
return listener_;
|
||||
}
|
||||
|
||||
void setListener(int v)
|
||||
{
|
||||
listener_ = v;
|
||||
}
|
||||
|
||||
int reader()
|
||||
{
|
||||
return reader_;
|
||||
}
|
||||
|
||||
void setReader(int v)
|
||||
{
|
||||
reader_ = v;
|
||||
}
|
||||
|
||||
int writer()
|
||||
{
|
||||
return writer_;
|
||||
}
|
||||
|
||||
private:
|
||||
bool connected_;
|
||||
int listener_;
|
||||
int reader_;
|
||||
int writer_;
|
||||
#else
|
||||
Pipe(JNIEnv* e)
|
||||
{
|
||||
if (::pipe(pipe) != 0) {
|
||||
@ -856,236 +216,10 @@ class Pipe {
|
||||
private:
|
||||
int pipe[2];
|
||||
bool open_;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct SelectorState {
|
||||
fd_set read;
|
||||
fd_set write;
|
||||
fd_set except;
|
||||
Pipe control;
|
||||
SelectorState(JNIEnv* e) : control(e)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_java_nio_channels_SocketSelector_natInit(JNIEnv* e, jclass)
|
||||
{
|
||||
void* mem = malloc(sizeof(SelectorState));
|
||||
if (mem) {
|
||||
SelectorState* s = new (mem) SelectorState(e);
|
||||
if (e->ExceptionCheck())
|
||||
return 0;
|
||||
|
||||
if (s) {
|
||||
FD_ZERO(&(s->read));
|
||||
FD_ZERO(&(s->write));
|
||||
FD_ZERO(&(s->except));
|
||||
return reinterpret_cast<jlong>(s);
|
||||
}
|
||||
}
|
||||
throwNew(e, "java/lang/OutOfMemoryError", 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_SocketSelector_natWakeup(JNIEnv* e,
|
||||
jclass,
|
||||
jlong state)
|
||||
{
|
||||
SelectorState* s = reinterpret_cast<SelectorState*>(state);
|
||||
if (s->control.connected()) {
|
||||
const char c = 1;
|
||||
int r = ::doWrite(s->control.writer(), &c, 1);
|
||||
if (r != 1) {
|
||||
throwIOException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_SocketSelector_natClose(JNIEnv*, jclass, jlong state)
|
||||
{
|
||||
SelectorState* s = reinterpret_cast<SelectorState*>(state);
|
||||
s->control.dispose();
|
||||
free(s);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_nio_channels_SocketSelector_natSelectClearAll(JNIEnv*,
|
||||
jclass,
|
||||
jint socket,
|
||||
jlong state)
|
||||
{
|
||||
SelectorState* s = reinterpret_cast<SelectorState*>(state);
|
||||
FD_CLR(static_cast<unsigned>(socket), &(s->read));
|
||||
FD_CLR(static_cast<unsigned>(socket), &(s->write));
|
||||
FD_CLR(static_cast<unsigned>(socket), &(s->except));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_nio_channels_SocketSelector_natSelectUpdateInterestSet(
|
||||
JNIEnv*,
|
||||
jclass,
|
||||
jint socket,
|
||||
jint interest,
|
||||
jlong state,
|
||||
jint max)
|
||||
{
|
||||
SelectorState* s = reinterpret_cast<SelectorState*>(state);
|
||||
if (interest & (java_nio_channels_SelectionKey_OP_READ
|
||||
| java_nio_channels_SelectionKey_OP_ACCEPT)) {
|
||||
FD_SET(static_cast<unsigned>(socket), &(s->read));
|
||||
if (max < socket)
|
||||
max = socket;
|
||||
} else {
|
||||
FD_CLR(static_cast<unsigned>(socket), &(s->read));
|
||||
}
|
||||
|
||||
if (interest & (java_nio_channels_SelectionKey_OP_WRITE
|
||||
| java_nio_channels_SelectionKey_OP_CONNECT)) {
|
||||
FD_SET(static_cast<unsigned>(socket), &(s->write));
|
||||
FD_SET(static_cast<unsigned>(socket), &(s->except));
|
||||
if (max < socket)
|
||||
max = socket;
|
||||
} else {
|
||||
FD_CLR(static_cast<unsigned>(socket), &(s->write));
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv* e,
|
||||
jclass,
|
||||
jlong state,
|
||||
jint max,
|
||||
jlong interval)
|
||||
{
|
||||
SelectorState* s = reinterpret_cast<SelectorState*>(state);
|
||||
if (s->control.reader() >= 0) {
|
||||
int socket = s->control.reader();
|
||||
FD_SET(static_cast<unsigned>(socket), &(s->read));
|
||||
if (max < socket)
|
||||
max = socket;
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
if (s->control.listener() >= 0) {
|
||||
int socket = s->control.listener();
|
||||
FD_SET(static_cast<unsigned>(socket), &(s->read));
|
||||
if (max < socket)
|
||||
max = socket;
|
||||
}
|
||||
|
||||
if (not s->control.connected()) {
|
||||
int socket = s->control.writer();
|
||||
FD_SET(static_cast<unsigned>(socket), &(s->write));
|
||||
FD_SET(static_cast<unsigned>(socket), &(s->except));
|
||||
if (max < socket)
|
||||
max = socket;
|
||||
}
|
||||
#endif
|
||||
|
||||
timeval time;
|
||||
if (interval > 0) {
|
||||
time.tv_sec = interval / 1000;
|
||||
time.tv_usec = (interval % 1000) * 1000;
|
||||
} else if (interval < 0) {
|
||||
time.tv_sec = 0;
|
||||
time.tv_usec = 0;
|
||||
} else {
|
||||
time.tv_sec = 24 * 60 * 60 * 1000;
|
||||
time.tv_usec = 0;
|
||||
}
|
||||
int r = ::select(max + 1, &(s->read), &(s->write), &(s->except), &time);
|
||||
|
||||
if (r < 0) {
|
||||
if (errno != EINTR) {
|
||||
throwIOException(e);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
if (FD_ISSET(s->control.writer(), &(s->write))
|
||||
or FD_ISSET(s->control.writer(), &(s->except))) {
|
||||
int socket = s->control.writer();
|
||||
FD_CLR(static_cast<unsigned>(socket), &(s->write));
|
||||
FD_CLR(static_cast<unsigned>(socket), &(s->except));
|
||||
|
||||
int error;
|
||||
socklen_t size = sizeof(int);
|
||||
int r = getsockopt(
|
||||
socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&error), &size);
|
||||
if (r != 0 or size != sizeof(int)) {
|
||||
throwIOException(e);
|
||||
} else if (error != 0) {
|
||||
throwIOException(e, socketErrorString(e, error));
|
||||
}
|
||||
s->control.setConnected(true);
|
||||
}
|
||||
|
||||
if (s->control.listener() >= 0
|
||||
and FD_ISSET(s->control.listener(), &(s->read))) {
|
||||
FD_CLR(static_cast<unsigned>(s->control.listener()), &(s->read));
|
||||
|
||||
s->control.setReader(::doAccept(e, s->control.listener()));
|
||||
s->control.setListener(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (s->control.reader() >= 0 and FD_ISSET(s->control.reader(), &(s->read))) {
|
||||
FD_CLR(static_cast<unsigned>(s->control.reader()), &(s->read));
|
||||
|
||||
char c;
|
||||
int r = 1;
|
||||
while (r == 1) {
|
||||
r = ::doRead(s->control.reader(), &c, 1);
|
||||
}
|
||||
if (r < 0 and not eagain()) {
|
||||
throwIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_nio_channels_SocketSelector_natUpdateReadySet(JNIEnv*,
|
||||
jclass,
|
||||
jint socket,
|
||||
jint interest,
|
||||
jlong state)
|
||||
{
|
||||
SelectorState* s = reinterpret_cast<SelectorState*>(state);
|
||||
jint ready = 0;
|
||||
|
||||
if (FD_ISSET(socket, &(s->read))) {
|
||||
if (interest & java_nio_channels_SelectionKey_OP_READ) {
|
||||
ready |= java_nio_channels_SelectionKey_OP_READ;
|
||||
}
|
||||
|
||||
if (interest & java_nio_channels_SelectionKey_OP_ACCEPT) {
|
||||
ready |= java_nio_channels_SelectionKey_OP_ACCEPT;
|
||||
}
|
||||
}
|
||||
|
||||
if (FD_ISSET(socket, &(s->write)) or FD_ISSET(socket, &(s->except))) {
|
||||
if (interest & java_nio_channels_SelectionKey_OP_WRITE) {
|
||||
ready |= java_nio_channels_SelectionKey_OP_WRITE;
|
||||
}
|
||||
|
||||
if (interest & java_nio_channels_SelectionKey_OP_CONNECT) {
|
||||
ready |= java_nio_channels_SelectionKey_OP_CONNECT;
|
||||
}
|
||||
}
|
||||
|
||||
return ready;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_java_nio_ByteOrder_isNativeBigEndian(JNIEnv*, jclass)
|
||||
{
|
||||
@ -1099,4 +233,4 @@ extern "C" JNIEXPORT jboolean JNICALL
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
#endif // !SGX
|
||||
#endif // !SGX
|
||||
|
@ -47,43 +47,6 @@ public class File implements Serializable {
|
||||
this(parent.getPath() + FileSeparator + child);
|
||||
}
|
||||
|
||||
public static File createTempFile(String prefix, String suffix)
|
||||
throws IOException
|
||||
{
|
||||
return createTempFile(prefix, suffix, null);
|
||||
}
|
||||
|
||||
public static File createTempFile(String prefix, String suffix,
|
||||
File directory)
|
||||
throws IOException
|
||||
{
|
||||
if(directory == null) {
|
||||
directory = new File(System.getProperty("java.io.tmpdir"));
|
||||
}
|
||||
if(suffix == null) {
|
||||
suffix = ".tmp";
|
||||
}
|
||||
File ret;
|
||||
long state = System.currentTimeMillis();
|
||||
|
||||
do {
|
||||
ret = generateFile(directory, prefix, state, suffix);
|
||||
state *= 7;
|
||||
state += 3;
|
||||
} while(ret == null);
|
||||
ret.createNewFile();
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static File generateFile(File directory, String prefix, long state, String suffix) {
|
||||
File ret = new File(directory, prefix + state + suffix);
|
||||
if(ret.exists()) {
|
||||
return null;
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
private static String stripSeparators(String p) {
|
||||
while (p.length() > 1 && p.endsWith(FileSeparator)) {
|
||||
p = p.substring(0, p.length() - 1);
|
||||
@ -104,12 +67,6 @@ public class File implements Serializable {
|
||||
("\\".equals(FileSeparator) ? path.replace('/', '\\') : path);
|
||||
}
|
||||
|
||||
public static native boolean rename(String old, String new_);
|
||||
|
||||
public boolean renameTo(File newName) {
|
||||
return rename(path, newName.path);
|
||||
}
|
||||
|
||||
private static native boolean isDirectory(String path);
|
||||
|
||||
public boolean isDirectory() {
|
||||
@ -144,16 +101,6 @@ public class File implements Serializable {
|
||||
return canExecute(path);
|
||||
}
|
||||
|
||||
private static native boolean setExecutable(String path, boolean executable, boolean ownerOnly);
|
||||
|
||||
public boolean setExecutable(boolean executable) {
|
||||
return setExecutable(executable, true);
|
||||
}
|
||||
|
||||
public boolean setExecutable(boolean executable, boolean ownerOnly) {
|
||||
return setExecutable(path, executable, ownerOnly);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
int index = path.lastIndexOf(FileSeparator);
|
||||
if (index >= 0) {
|
||||
@ -219,46 +166,6 @@ public class File implements Serializable {
|
||||
return exists(path);
|
||||
}
|
||||
|
||||
private static native void mkdir(String path) throws IOException;
|
||||
|
||||
public boolean mkdir() {
|
||||
try {
|
||||
mkdir(path);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static native boolean createNewFile(String path) throws IOException;
|
||||
|
||||
public boolean createNewFile() throws IOException {
|
||||
return createNewFile(path);
|
||||
}
|
||||
|
||||
public static native void delete(String path) throws IOException;
|
||||
|
||||
public boolean delete() {
|
||||
try {
|
||||
delete(path);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean mkdirs() {
|
||||
File parent = getParentFile();
|
||||
if (parent != null) {
|
||||
if (!parent.exists()) {
|
||||
if (!parent.mkdirs()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return mkdir();
|
||||
}
|
||||
|
||||
public File[] listFiles() {
|
||||
return listFiles(null);
|
||||
}
|
||||
|
@ -1,443 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.io;
|
||||
|
||||
import static java.io.ObjectOutputStream.STREAM_MAGIC;
|
||||
import static java.io.ObjectOutputStream.STREAM_VERSION;
|
||||
import static java.io.ObjectOutputStream.TC_NULL;
|
||||
import static java.io.ObjectOutputStream.TC_REFERENCE;
|
||||
import static java.io.ObjectOutputStream.TC_CLASSDESC;
|
||||
import static java.io.ObjectOutputStream.TC_OBJECT;
|
||||
import static java.io.ObjectOutputStream.TC_STRING;
|
||||
import static java.io.ObjectOutputStream.TC_ARRAY;
|
||||
import static java.io.ObjectOutputStream.TC_CLASS;
|
||||
import static java.io.ObjectOutputStream.TC_BLOCKDATA;
|
||||
import static java.io.ObjectOutputStream.TC_ENDBLOCKDATA;
|
||||
import static java.io.ObjectOutputStream.TC_RESET;
|
||||
import static java.io.ObjectOutputStream.TC_BLOCKDATALONG;
|
||||
import static java.io.ObjectOutputStream.TC_EXCEPTION;
|
||||
import static java.io.ObjectOutputStream.TC_LONGSTRING;
|
||||
import static java.io.ObjectOutputStream.TC_PROXYCLASSDESC;
|
||||
import static java.io.ObjectOutputStream.TC_ENUM;
|
||||
import static java.io.ObjectOutputStream.SC_WRITE_METHOD;
|
||||
import static java.io.ObjectOutputStream.SC_BLOCK_DATA;
|
||||
import static java.io.ObjectOutputStream.SC_SERIALIZABLE;
|
||||
import static java.io.ObjectOutputStream.SC_EXTERNALIZABLE;
|
||||
import static java.io.ObjectOutputStream.SC_ENUM;
|
||||
import static java.io.ObjectOutputStream.getReadOrWriteMethod;
|
||||
|
||||
import avian.VMClass;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
public class ObjectInputStream extends InputStream implements DataInput {
|
||||
private final static int HANDLE_OFFSET = 0x7e0000;
|
||||
|
||||
private final InputStream in;
|
||||
private final ArrayList references;
|
||||
|
||||
public ObjectInputStream(InputStream in) throws IOException {
|
||||
this.in = in;
|
||||
short signature = (short)rawShort();
|
||||
if (signature != STREAM_MAGIC) {
|
||||
throw new IOException("Unrecognized signature: 0x"
|
||||
+ Integer.toHexString(signature));
|
||||
}
|
||||
int version = rawShort();
|
||||
if (version != STREAM_VERSION) {
|
||||
throw new IOException("Unsupported version: " + version);
|
||||
}
|
||||
references = new ArrayList();
|
||||
}
|
||||
|
||||
public int read() throws IOException {
|
||||
return in.read();
|
||||
}
|
||||
|
||||
private int rawByte() throws IOException {
|
||||
int c = read();
|
||||
if (c < 0) {
|
||||
throw new EOFException();
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private int rawShort() throws IOException {
|
||||
return (rawByte() << 8) | rawByte();
|
||||
}
|
||||
|
||||
private int rawInt() throws IOException {
|
||||
return (rawShort() << 16) | rawShort();
|
||||
}
|
||||
|
||||
private long rawLong() throws IOException {
|
||||
return ((rawInt() & 0xffffffffl) << 32) | rawInt();
|
||||
}
|
||||
|
||||
private String rawString() throws IOException {
|
||||
int length = rawShort();
|
||||
byte[] array = new byte[length];
|
||||
readFully(array);
|
||||
return new String(array);
|
||||
}
|
||||
|
||||
public int read(byte[] b, int offset, int length) throws IOException {
|
||||
return in.read(b, offset, length);
|
||||
}
|
||||
|
||||
public void readFully(byte[] b) throws IOException {
|
||||
readFully(b, 0, b.length);
|
||||
}
|
||||
|
||||
public void readFully(byte[] b, int offset, int length) throws IOException {
|
||||
while (length > 0) {
|
||||
int count = read(b, offset, length);
|
||||
if (count < 0) {
|
||||
throw new EOFException("Reached EOF " + length + " bytes too early");
|
||||
}
|
||||
offset += count;
|
||||
length -= count;
|
||||
}
|
||||
}
|
||||
|
||||
public String readLine() throws IOException {
|
||||
int c = read();
|
||||
if (c < 0) {
|
||||
return null;
|
||||
} else if (c == '\n') {
|
||||
return "";
|
||||
}
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (;;) {
|
||||
builder.append((char)c);
|
||||
c = read();
|
||||
if (c < 0 || c == '\n') {
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
in.close();
|
||||
}
|
||||
|
||||
private int remainingBlockData;
|
||||
|
||||
private int rawBlockDataByte() throws IOException {
|
||||
while (remainingBlockData <= 0) {
|
||||
int b = rawByte();
|
||||
if (b == TC_BLOCKDATA) {
|
||||
remainingBlockData = rawByte();
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unknown token: 0x"
|
||||
+ Integer.toHexString(b));
|
||||
}
|
||||
}
|
||||
--remainingBlockData;
|
||||
return rawByte();
|
||||
}
|
||||
|
||||
private int rawBlockDataShort() throws IOException {
|
||||
return (rawBlockDataByte() << 8) | rawBlockDataByte();
|
||||
}
|
||||
|
||||
private int rawBlockDataInt() throws IOException {
|
||||
return (rawBlockDataShort() << 16) | rawBlockDataShort();
|
||||
}
|
||||
|
||||
private long rawBlockDataLong() throws IOException {
|
||||
return ((rawBlockDataInt() & 0xffffffffl) << 32) | rawBlockDataInt();
|
||||
}
|
||||
|
||||
public boolean readBoolean() throws IOException {
|
||||
return rawBlockDataByte() != 0;
|
||||
}
|
||||
|
||||
public byte readByte() throws IOException {
|
||||
return (byte)rawBlockDataByte();
|
||||
}
|
||||
|
||||
public char readChar() throws IOException {
|
||||
return (char)rawBlockDataShort();
|
||||
}
|
||||
|
||||
public short readShort() throws IOException {
|
||||
return (short)rawBlockDataShort();
|
||||
}
|
||||
|
||||
public int readInt() throws IOException {
|
||||
return rawBlockDataInt();
|
||||
}
|
||||
|
||||
public long readLong() throws IOException {
|
||||
return rawBlockDataLong();
|
||||
}
|
||||
|
||||
public float readFloat() throws IOException {
|
||||
return Float.intBitsToFloat(rawBlockDataInt());
|
||||
}
|
||||
|
||||
public double readDouble() throws IOException {
|
||||
return Double.longBitsToDouble(rawBlockDataLong());
|
||||
}
|
||||
|
||||
public int readUnsignedByte() throws IOException {
|
||||
return rawBlockDataByte();
|
||||
}
|
||||
|
||||
public int readUnsignedShort() throws IOException {
|
||||
return rawBlockDataShort();
|
||||
}
|
||||
|
||||
public String readUTF() throws IOException {
|
||||
int length = rawBlockDataShort();
|
||||
if (remainingBlockData < length) {
|
||||
throw new IOException("Short block data: "
|
||||
+ remainingBlockData + " < " + length);
|
||||
}
|
||||
byte[] bytes = new byte[length];
|
||||
readFully(bytes);
|
||||
remainingBlockData -= length;
|
||||
return new String(bytes, "UTF-8");
|
||||
}
|
||||
|
||||
public int skipBytes(int count) throws IOException {
|
||||
int i = 0;
|
||||
while (i < count) {
|
||||
if (read() < 0) {
|
||||
return i;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private static Class charToPrimitiveType(int c) {
|
||||
if (c == 'B') {
|
||||
return Byte.TYPE;
|
||||
} else if (c == 'C') {
|
||||
return Character.TYPE;
|
||||
} else if (c == 'D') {
|
||||
return Double.TYPE;
|
||||
} else if (c == 'F') {
|
||||
return Float.TYPE;
|
||||
} else if (c == 'I') {
|
||||
return Integer.TYPE;
|
||||
} else if (c == 'J') {
|
||||
return Long.TYPE;
|
||||
} else if (c == 'S') {
|
||||
return Short.TYPE;
|
||||
} else if (c == 'Z') {
|
||||
return Boolean.TYPE;
|
||||
}
|
||||
throw new RuntimeException("Unhandled char: " + (char)c);
|
||||
}
|
||||
|
||||
private void expectToken(int token) throws IOException {
|
||||
int c = rawByte();
|
||||
if (c != token) {
|
||||
throw new UnsupportedOperationException("Unexpected token: 0x"
|
||||
+ Integer.toHexString(c));
|
||||
}
|
||||
}
|
||||
|
||||
private void field(Field field, Object o)
|
||||
throws IOException, IllegalArgumentException, IllegalAccessException,
|
||||
ClassNotFoundException
|
||||
{
|
||||
Class type = field.getType();
|
||||
if (!type.isPrimitive()) {
|
||||
field.set(o, readObject());
|
||||
} else {
|
||||
if (type == Byte.TYPE) {
|
||||
field.setByte(o, (byte)rawByte());
|
||||
} else if (type == Character.TYPE) {
|
||||
field.setChar(o, (char)rawShort());
|
||||
} else if (type == Double.TYPE) {
|
||||
field.setDouble(o, Double.longBitsToDouble(rawLong()));
|
||||
} else if (type == Float.TYPE) {
|
||||
field.setFloat(o, Float.intBitsToFloat(rawInt()));
|
||||
} else if (type == Integer.TYPE) {
|
||||
field.setInt(o, rawInt());
|
||||
} else if (type == Long.TYPE) {
|
||||
field.setLong(o, rawLong());
|
||||
} else if (type == Short.TYPE) {
|
||||
field.setShort(o, (short)rawShort());
|
||||
} else if (type == Boolean.TYPE) {
|
||||
field.setBoolean(o, rawByte() != 0);
|
||||
} else {
|
||||
throw new IOException("Unhandled type: " + type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Object readObject() throws IOException, ClassNotFoundException {
|
||||
int c = rawByte();
|
||||
if (c == TC_NULL) {
|
||||
return null;
|
||||
}
|
||||
if (c == TC_STRING) {
|
||||
int length = rawShort();
|
||||
byte[] bytes = new byte[length];
|
||||
readFully(bytes);
|
||||
String s = new String(bytes, "UTF-8");
|
||||
references.add(s);
|
||||
return s;
|
||||
}
|
||||
if (c == TC_REFERENCE) {
|
||||
int handle = rawInt();
|
||||
return references.get(handle - HANDLE_OFFSET);
|
||||
}
|
||||
if (c != TC_OBJECT) {
|
||||
throw new IOException("Unexpected token: 0x"
|
||||
+ Integer.toHexString(c));
|
||||
}
|
||||
|
||||
// class desc
|
||||
c = rawByte();
|
||||
ClassDesc classDesc;
|
||||
if (c == TC_REFERENCE) {
|
||||
int handle = rawInt() - HANDLE_OFFSET;
|
||||
classDesc = (ClassDesc)references.get(handle);
|
||||
} else if (c == TC_CLASSDESC) {
|
||||
classDesc = classDesc();
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unexpected token: 0x"
|
||||
+ Integer.toHexString(c));
|
||||
}
|
||||
|
||||
try {
|
||||
Object o = makeInstance(classDesc.clazz.vmClass);
|
||||
references.add(o);
|
||||
|
||||
do {
|
||||
Object o1 = classDesc.clazz.cast(o);
|
||||
boolean customized = (classDesc.flags & SC_WRITE_METHOD) != 0;
|
||||
Method readMethod = customized ?
|
||||
getReadOrWriteMethod(o, "readObject") : null;
|
||||
if (readMethod == null) {
|
||||
if (customized) {
|
||||
throw new IOException("Could not find required readObject method "
|
||||
+ "in " + classDesc.clazz);
|
||||
}
|
||||
defaultReadObject(o, classDesc.fields);
|
||||
} else {
|
||||
current = o1;
|
||||
currentFields = classDesc.fields;
|
||||
readMethod.invoke(o, this);
|
||||
current = null;
|
||||
currentFields = null;
|
||||
expectToken(TC_ENDBLOCKDATA);
|
||||
}
|
||||
} while ((classDesc = classDesc.superClassDesc) != null);
|
||||
|
||||
return o;
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ClassDesc {
|
||||
Class clazz;
|
||||
int flags;
|
||||
Field[] fields;
|
||||
ClassDesc superClassDesc;
|
||||
}
|
||||
|
||||
private ClassDesc classDesc() throws ClassNotFoundException, IOException {
|
||||
ClassDesc result = new ClassDesc();
|
||||
String className = rawString();
|
||||
ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
||||
result.clazz = loader.loadClass(className);
|
||||
long serialVersionUID = rawLong();
|
||||
try {
|
||||
Field field = result.clazz.getField("serialVersionUID");
|
||||
long expected = field.getLong(null);
|
||||
if (expected != serialVersionUID) {
|
||||
throw new IOException("Incompatible serial version UID: 0x"
|
||||
+ Long.toHexString(serialVersionUID) + " != 0x"
|
||||
+ Long.toHexString(expected));
|
||||
}
|
||||
} catch (Exception ignored) { }
|
||||
references.add(result);
|
||||
|
||||
result.flags = rawByte();
|
||||
if ((result.flags & ~(SC_SERIALIZABLE | SC_WRITE_METHOD)) != 0) {
|
||||
throw new UnsupportedOperationException("Cannot handle flags: 0x"
|
||||
+ Integer.toHexString(result.flags));
|
||||
}
|
||||
|
||||
int fieldCount = rawShort();
|
||||
result.fields = new Field[fieldCount];
|
||||
for (int i = 0; i < result.fields.length; i++) {
|
||||
int typeChar = rawByte();
|
||||
String fieldName = rawString();
|
||||
try {
|
||||
result.fields[i] = result.clazz.getDeclaredField(fieldName);
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
Class type;
|
||||
if (typeChar == '[' || typeChar == 'L') {
|
||||
String typeName = (String)readObject();
|
||||
if (typeName.startsWith("L") && typeName.endsWith(";")) {
|
||||
typeName = typeName.substring(1, typeName.length() - 1)
|
||||
.replace('/', '.');
|
||||
}
|
||||
type = loader.loadClass(typeName);
|
||||
} else {
|
||||
type = charToPrimitiveType(typeChar);
|
||||
}
|
||||
if (result.fields[i].getType() != type) {
|
||||
throw new IOException("Unexpected type of field " + fieldName
|
||||
+ ": expected " + result.fields[i].getType() + " but got " + type);
|
||||
}
|
||||
}
|
||||
expectToken(TC_ENDBLOCKDATA);
|
||||
int c = rawByte();
|
||||
if (c == TC_CLASSDESC) {
|
||||
result.superClassDesc = classDesc();
|
||||
} else if (c != TC_NULL) {
|
||||
throw new UnsupportedOperationException("Unexpected token: 0x"
|
||||
+ Integer.toHexString(c));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Object current;
|
||||
private Field[] currentFields;
|
||||
|
||||
public void defaultReadObject() throws IOException {
|
||||
defaultReadObject(current, currentFields);
|
||||
}
|
||||
|
||||
private void defaultReadObject(Object o, Field[] fields) throws IOException {
|
||||
try {
|
||||
for (Field field : fields) {
|
||||
field(field, o);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static native Object makeInstance(VMClass c);
|
||||
}
|
@ -1,337 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.io;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
public class ObjectOutputStream extends OutputStream implements DataOutput {
|
||||
final static short STREAM_MAGIC = (short)0xaced;
|
||||
final static short STREAM_VERSION = 5;
|
||||
final static byte TC_NULL = (byte)0x70;
|
||||
final static byte TC_REFERENCE = (byte)0x71;
|
||||
final static byte TC_CLASSDESC = (byte)0x72;
|
||||
final static byte TC_OBJECT = (byte)0x73;
|
||||
final static byte TC_STRING = (byte)0x74;
|
||||
final static byte TC_ARRAY = (byte)0x75;
|
||||
final static byte TC_CLASS = (byte)0x76;
|
||||
final static byte TC_BLOCKDATA = (byte)0x77;
|
||||
final static byte TC_ENDBLOCKDATA = (byte)0x78;
|
||||
final static byte TC_RESET = (byte)0x79;
|
||||
final static byte TC_BLOCKDATALONG = (byte)0x7a;
|
||||
final static byte TC_EXCEPTION = (byte)0x7b;
|
||||
final static byte TC_LONGSTRING = (byte)0x7c;
|
||||
final static byte TC_PROXYCLASSDESC = (byte)0x7d;
|
||||
final static byte TC_ENUM = (byte)0x7e;
|
||||
final static byte SC_WRITE_METHOD = 0x01; //if SC_SERIALIZABLE
|
||||
final static byte SC_BLOCK_DATA = 0x08; //if SC_EXTERNALIZABLE
|
||||
final static byte SC_SERIALIZABLE = 0x02;
|
||||
final static byte SC_EXTERNALIZABLE = 0x04;
|
||||
final static byte SC_ENUM = 0x10;
|
||||
|
||||
private final OutputStream out;
|
||||
|
||||
public ObjectOutputStream(OutputStream out) throws IOException {
|
||||
this.out = out;
|
||||
rawShort(STREAM_MAGIC);
|
||||
rawShort(STREAM_VERSION);
|
||||
}
|
||||
|
||||
public void write(int c) throws IOException {
|
||||
out.write(c);
|
||||
}
|
||||
|
||||
public void write(byte[] b, int offset, int length) throws IOException {
|
||||
out.write(b, offset, length);
|
||||
}
|
||||
|
||||
public void flush() throws IOException {
|
||||
out.flush();
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
out.close();
|
||||
}
|
||||
|
||||
private void rawByte(int v) throws IOException {
|
||||
out.write((byte)(v & 0xff));
|
||||
}
|
||||
|
||||
private void rawShort(int v) throws IOException {
|
||||
rawByte(v >> 8);
|
||||
rawByte(v);
|
||||
}
|
||||
|
||||
private void rawInt(int v) throws IOException {
|
||||
rawShort(v >> 16);
|
||||
rawShort(v);
|
||||
}
|
||||
|
||||
private void rawLong(long v) throws IOException {
|
||||
rawInt((int)(v >> 32));
|
||||
rawInt((int)(v & 0xffffffffl));
|
||||
}
|
||||
|
||||
private void blockData(int... bytes) throws IOException {
|
||||
blockData(bytes, null, null);
|
||||
}
|
||||
|
||||
private void blockData(int[] bytes, byte[] bytes2, char[] chars) throws IOException {
|
||||
int count = (bytes == null ? 0 : bytes.length)
|
||||
+ (bytes2 == null ? 0 : bytes2.length)
|
||||
+ (chars == null ? 0 : chars.length * 2);
|
||||
if (count < 0x100) {
|
||||
rawByte(TC_BLOCKDATA);
|
||||
rawByte(count);
|
||||
} else {
|
||||
rawByte(TC_BLOCKDATALONG);
|
||||
rawInt(count);
|
||||
}
|
||||
if (bytes != null) {
|
||||
for (int b : bytes) {
|
||||
rawByte(b);
|
||||
}
|
||||
}
|
||||
if (bytes2 != null) {
|
||||
for (byte b : bytes2) {
|
||||
rawByte(b & 0xff);
|
||||
}
|
||||
}
|
||||
if (chars != null) {
|
||||
for (char c : chars) {
|
||||
rawShort((short)c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void writeBoolean(boolean v) throws IOException {
|
||||
blockData(v ? 1 : 0);
|
||||
}
|
||||
|
||||
public void writeByte(int v) throws IOException {
|
||||
blockData(v);
|
||||
}
|
||||
|
||||
public void writeShort(int v) throws IOException {
|
||||
blockData(v >> 8, v);
|
||||
}
|
||||
|
||||
public void writeChar(int v) throws IOException {
|
||||
blockData(v >> 8, v);
|
||||
}
|
||||
|
||||
public void writeInt(int v) throws IOException {
|
||||
blockData(v >> 24, v >> 16, v >> 8, v);
|
||||
}
|
||||
|
||||
public void writeLong(long v) throws IOException {
|
||||
int u = (int)(v >> 32), l = (int)(v & 0xffffffff);
|
||||
blockData(u >> 24, u >> 16, u >> 8, u, l >> 24, l >> 16, l >> 8, l);
|
||||
}
|
||||
|
||||
public void writeFloat(float v) throws IOException {
|
||||
writeInt(Float.floatToIntBits(v));
|
||||
}
|
||||
|
||||
public void writeDouble(double v) throws IOException {
|
||||
writeLong(Double.doubleToLongBits(v));
|
||||
}
|
||||
|
||||
public void writeBytes(String s) throws IOException {
|
||||
blockData(null, s.getBytes(), null);
|
||||
}
|
||||
|
||||
public void writeChars(String s) throws IOException {
|
||||
blockData(null, null, s.toCharArray());
|
||||
}
|
||||
|
||||
public void writeUTF(String s) throws IOException {
|
||||
byte[] bytes = s.getBytes();
|
||||
int length = bytes.length;
|
||||
blockData(new int[] { length >> 8, length }, bytes, null);
|
||||
}
|
||||
|
||||
private int classHandle;
|
||||
|
||||
private void string(String s) throws IOException {
|
||||
int length = s.length();
|
||||
rawShort(length);
|
||||
for (byte b : s.getBytes()) {
|
||||
rawByte(b);
|
||||
}
|
||||
}
|
||||
|
||||
private static char primitiveTypeChar(Class type) {
|
||||
if (type == Byte.TYPE) {
|
||||
return 'B';
|
||||
} else if (type == Character.TYPE) {
|
||||
return 'C';
|
||||
} else if (type == Double.TYPE) {
|
||||
return 'D';
|
||||
} else if (type == Float.TYPE) {
|
||||
return 'F';
|
||||
} else if (type == Integer.TYPE) {
|
||||
return 'I';
|
||||
} else if (type == Long.TYPE) {
|
||||
return 'J';
|
||||
} else if (type == Short.TYPE) {
|
||||
return 'S';
|
||||
} else if (type == Boolean.TYPE) {
|
||||
return 'Z';
|
||||
}
|
||||
throw new RuntimeException("Unhandled primitive type: " + type);
|
||||
}
|
||||
|
||||
private void classDesc(Class clazz, int scFlags) throws IOException {
|
||||
rawByte(TC_CLASSDESC);
|
||||
|
||||
// class name
|
||||
string(clazz.getName());
|
||||
|
||||
// serial version UID
|
||||
long serialVersionUID = 1l;
|
||||
try {
|
||||
Field field = clazz.getField("serialVersionUID");
|
||||
serialVersionUID = field.getLong(null);
|
||||
} catch (Exception ignored) {}
|
||||
rawLong(serialVersionUID);
|
||||
|
||||
// handle
|
||||
rawByte(SC_SERIALIZABLE | scFlags);
|
||||
|
||||
Field[] fields = getFields(clazz);
|
||||
rawShort(fields.length);
|
||||
for (Field field : fields) {
|
||||
Class fieldType = field.getType();
|
||||
if (fieldType.isPrimitive()) {
|
||||
rawByte(primitiveTypeChar(fieldType));
|
||||
string(field.getName());
|
||||
} else {
|
||||
rawByte(fieldType.isArray() ? '[' : 'L');
|
||||
string(field.getName());
|
||||
rawByte(TC_STRING);
|
||||
string("L" + fieldType.getName().replace('.', '/') + ";");
|
||||
}
|
||||
}
|
||||
rawByte(TC_ENDBLOCKDATA); // TODO: write annotation
|
||||
rawByte(TC_NULL); // super class desc
|
||||
}
|
||||
|
||||
private void field(Object o, Field field) throws IOException {
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
Class type = field.getType();
|
||||
if (!type.isPrimitive()) {
|
||||
writeObject(field.get(o));
|
||||
} else if (type == Byte.TYPE) {
|
||||
rawByte(field.getByte(o));
|
||||
} else if (type == Character.TYPE) {
|
||||
char c = field.getChar(o);
|
||||
rawShort((short)c);
|
||||
} else if (type == Double.TYPE) {
|
||||
double d = field.getDouble(o);
|
||||
rawLong(Double.doubleToLongBits(d));
|
||||
} else if (type == Float.TYPE) {
|
||||
float f = field.getFloat(o);
|
||||
rawInt(Float.floatToIntBits(f));
|
||||
} else if (type == Integer.TYPE) {
|
||||
int i = field.getInt(o);
|
||||
rawInt(i);
|
||||
} else if (type == Long.TYPE) {
|
||||
long l = field.getLong(o);
|
||||
rawLong(l);
|
||||
} else if (type == Short.TYPE) {
|
||||
short s = field.getShort(o);
|
||||
rawShort(s);
|
||||
} else if (type == Boolean.TYPE) {
|
||||
boolean b = field.getBoolean(o);
|
||||
rawByte(b ? 1 : 0);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Field '" + field.getName()
|
||||
+ "' has unsupported type: " + type);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Field[] getFields(Class clazz) {
|
||||
ArrayList<Field> list = new ArrayList<Field>();
|
||||
Field[] fields = clazz.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
if (0 == (field.getModifiers() &
|
||||
(Modifier.STATIC | Modifier.TRANSIENT))) {
|
||||
list.add(field);
|
||||
}
|
||||
}
|
||||
return list.toArray(new Field[list.size()]);
|
||||
}
|
||||
|
||||
public void writeObject(Object o) throws IOException {
|
||||
if (o == null) {
|
||||
rawByte(TC_NULL);
|
||||
return;
|
||||
}
|
||||
if (o instanceof String) {
|
||||
byte[] bytes = ((String)o).getBytes("UTF-8");
|
||||
rawByte(TC_STRING);
|
||||
rawShort(bytes.length);
|
||||
write(bytes);
|
||||
return;
|
||||
}
|
||||
rawByte(TC_OBJECT);
|
||||
Method writeObject = getReadOrWriteMethod(o, "writeObject");
|
||||
if (writeObject == null) {
|
||||
classDesc(o.getClass(), 0);
|
||||
defaultWriteObject(o);
|
||||
} else try {
|
||||
classDesc(o.getClass(), SC_WRITE_METHOD);
|
||||
current = o;
|
||||
writeObject.invoke(o, this);
|
||||
current = null;
|
||||
rawByte(TC_ENDBLOCKDATA);
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
static Method getReadOrWriteMethod(Object o, String methodName) {
|
||||
try {
|
||||
Method method = o.getClass().getDeclaredMethod(methodName,
|
||||
new Class[] { methodName.startsWith("write") ?
|
||||
ObjectOutputStream.class : ObjectInputStream.class });
|
||||
method.setAccessible(true);
|
||||
int modifiers = method.getModifiers();
|
||||
if ((modifiers & Modifier.STATIC) == 0 ||
|
||||
(modifiers & Modifier.PRIVATE) != 0) {
|
||||
return method;
|
||||
}
|
||||
} catch (NoSuchMethodException ignored) { }
|
||||
return null;
|
||||
}
|
||||
|
||||
private Object current;
|
||||
|
||||
public void defaultWriteObject() throws IOException {
|
||||
defaultWriteObject(current);
|
||||
}
|
||||
|
||||
private void defaultWriteObject(Object o) throws IOException {
|
||||
for (Field field : getFields(o.getClass())) {
|
||||
field(o, field);
|
||||
}
|
||||
}
|
||||
}
|
@ -12,7 +12,6 @@ package java.io;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
public class RandomAccessFile implements DataInput, Closeable {
|
||||
|
||||
@ -229,54 +228,4 @@ public class RandomAccessFile implements DataInput, Closeable {
|
||||
}
|
||||
|
||||
private static native void close(long peer);
|
||||
|
||||
public FileChannel getChannel() {
|
||||
return new FileChannel() {
|
||||
public void close() {
|
||||
if (peer != 0) RandomAccessFile.close(peer);
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return peer != 0;
|
||||
}
|
||||
|
||||
public int read(ByteBuffer dst, long position) throws IOException {
|
||||
if (!dst.hasArray()) throw new IOException("Cannot handle " + dst.getClass());
|
||||
// TODO: this needs to be synchronized on the Buffer, no?
|
||||
byte[] array = dst.array();
|
||||
return readBytes(peer, position, array, dst.position(), dst.remaining());
|
||||
}
|
||||
|
||||
public int read(ByteBuffer dst) throws IOException {
|
||||
int count = read(dst, position);
|
||||
if (count > 0) position += count;
|
||||
return count;
|
||||
}
|
||||
|
||||
public int write(ByteBuffer src, long position) throws IOException {
|
||||
if (!src.hasArray()) throw new IOException("Cannot handle " + src.getClass());
|
||||
byte[] array = src.array();
|
||||
return writeBytes(peer, position, array, src.position(), src.remaining());
|
||||
}
|
||||
|
||||
public int write(ByteBuffer src) throws IOException {
|
||||
int count = write(src, position);
|
||||
if (count > 0) position += count;
|
||||
return count;
|
||||
}
|
||||
|
||||
public long position() throws IOException {
|
||||
return getFilePointer();
|
||||
}
|
||||
|
||||
public FileChannel position(long position) throws IOException {
|
||||
seek(position);
|
||||
return this;
|
||||
}
|
||||
|
||||
public long size() throws IOException {
|
||||
return length();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -16,10 +16,6 @@ public final class Math {
|
||||
public static final double E = 2.718281828459045;
|
||||
public static final double PI = 3.141592653589793;
|
||||
|
||||
private static class Static {
|
||||
public static final Random random = new Random();
|
||||
}
|
||||
|
||||
private Math() { }
|
||||
|
||||
public static double max(double a, double b) {
|
||||
@ -86,10 +82,6 @@ public final class Math {
|
||||
return f > 0 ? +1.0f : f < 0 ? -1.0f : 0;
|
||||
}
|
||||
|
||||
public static double random() {
|
||||
return Static.random.nextDouble();
|
||||
}
|
||||
|
||||
public static native double floor(double v);
|
||||
|
||||
public static native double ceil(double v);
|
||||
|
@ -22,10 +22,6 @@ import java.util.Hashtable;
|
||||
import java.util.Properties;
|
||||
|
||||
public abstract class System {
|
||||
private static class NanoTime {
|
||||
public static final long BaseInMillis = currentTimeMillis();
|
||||
}
|
||||
|
||||
private static class Static {
|
||||
public static Properties properties = makeProperties();
|
||||
}
|
||||
@ -91,14 +87,8 @@ public abstract class System {
|
||||
|
||||
private static native String[] getVMProperties();
|
||||
|
||||
public static native long currentTimeMillis();
|
||||
|
||||
public static native int identityHashCode(Object o);
|
||||
|
||||
public static long nanoTime() {
|
||||
return (currentTimeMillis() - NanoTime.BaseInMillis) * 1000000;
|
||||
}
|
||||
|
||||
public static String mapLibraryName(String name) {
|
||||
if (name != null) {
|
||||
return doMapLibraryName(name);
|
||||
|
@ -25,7 +25,6 @@ public class Thread implements Runnable {
|
||||
private byte priority;
|
||||
private final Runnable task;
|
||||
private Map<ThreadLocal, Object> locals;
|
||||
private Object sleepLock;
|
||||
private ClassLoader classLoader;
|
||||
private UncaughtExceptionHandler exceptionHandler;
|
||||
private String name;
|
||||
@ -158,30 +157,6 @@ public class Thread implements Runnable {
|
||||
return interrupted;
|
||||
}
|
||||
|
||||
public static void sleep(long milliseconds) throws InterruptedException {
|
||||
if (milliseconds <= 0) {
|
||||
milliseconds = 1;
|
||||
}
|
||||
|
||||
Thread t = currentThread();
|
||||
if (t.sleepLock == null) {
|
||||
t.sleepLock = new Object();
|
||||
}
|
||||
synchronized (t.sleepLock) {
|
||||
t.sleepLock.wait(milliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
public static void sleep(long milliseconds, int nanoseconds)
|
||||
throws InterruptedException
|
||||
{
|
||||
if (nanoseconds > 0) {
|
||||
++ milliseconds;
|
||||
}
|
||||
|
||||
sleep(milliseconds);
|
||||
}
|
||||
|
||||
public StackTraceElement[] getStackTrace() {
|
||||
long p = peer;
|
||||
if (p == 0) {
|
||||
@ -269,27 +244,6 @@ public class Thread implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void join(long milliseconds) throws InterruptedException
|
||||
{
|
||||
long then = System.currentTimeMillis();
|
||||
long remaining = milliseconds;
|
||||
while (remaining > 0 && getState() != State.TERMINATED) {
|
||||
wait(remaining);
|
||||
|
||||
remaining = milliseconds - (System.currentTimeMillis() - then);
|
||||
}
|
||||
}
|
||||
|
||||
public void join(long milliseconds, int nanoseconds)
|
||||
throws InterruptedException
|
||||
{
|
||||
if (nanoseconds > 0) {
|
||||
++ milliseconds;
|
||||
}
|
||||
|
||||
join(milliseconds);
|
||||
}
|
||||
|
||||
public ThreadGroup getThreadGroup() {
|
||||
return group;
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.net;
|
||||
|
||||
public class BindException extends SocketException {
|
||||
public BindException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public BindException() {
|
||||
this(null);
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.net;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public abstract class DatagramSocket {
|
||||
public abstract SocketAddress getRemoteSocketAddress();
|
||||
|
||||
public abstract void bind(SocketAddress address) throws SocketException;
|
||||
}
|
@ -13,66 +13,20 @@ package java.net;
|
||||
import java.io.IOException;
|
||||
|
||||
public class InetAddress {
|
||||
private final String name;
|
||||
private final int ip;
|
||||
|
||||
private InetAddress(String name) throws UnknownHostException {
|
||||
this.name = name;
|
||||
this.ip = ipv4AddressForName(name);
|
||||
}
|
||||
|
||||
public String getHostName() {
|
||||
return name;
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getHostAddress() {
|
||||
try {
|
||||
return new InetAddress(name).toString();
|
||||
} catch (UnknownHostException e) {
|
||||
return null; // Strange case
|
||||
}
|
||||
}
|
||||
|
||||
public static InetAddress getByName(String name) throws UnknownHostException {
|
||||
try {
|
||||
Socket.init();
|
||||
return new InetAddress(name);
|
||||
} catch (IOException e) {
|
||||
UnknownHostException uhe = new UnknownHostException(name);
|
||||
uhe.initCause(e);
|
||||
throw uhe;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public byte[] getAddress() {
|
||||
byte[] res = new byte[4];
|
||||
res[0] = (byte) ( ip >>> 24);
|
||||
res[1] = (byte) ((ip >>> 16) & 0xFF);
|
||||
res[2] = (byte) ((ip >>> 8 ) & 0xFF);
|
||||
res[3] = (byte) ((ip ) & 0xFF);
|
||||
return res;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
byte[] addr = getAddress();
|
||||
return (int)((addr[0] + 256) % 256) + "." +
|
||||
(int)((addr[1] + 256) % 256) + "." +
|
||||
(int)((addr[2] + 256) % 256) + "." +
|
||||
(int)((addr[3] + 256) % 256);
|
||||
}
|
||||
|
||||
public int getRawAddress() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
static native int ipv4AddressForName(String name) throws UnknownHostException;
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof InetAddress && ((InetAddress) o).ip == ip;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ip;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -1,65 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.net;
|
||||
|
||||
public class InetSocketAddress extends SocketAddress {
|
||||
private final String host;
|
||||
private final InetAddress address;
|
||||
private final int port;
|
||||
|
||||
public InetSocketAddress(String host, int port) {
|
||||
InetAddress address;
|
||||
try {
|
||||
address = InetAddress.getByName(host);
|
||||
host = address.getHostName();
|
||||
} catch (UnknownHostException e) {
|
||||
address = null;
|
||||
}
|
||||
this.host = host;
|
||||
this.address = address;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public InetSocketAddress(InetAddress address, int port) {
|
||||
this.host = address.getHostName();
|
||||
this.address = address;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public InetAddress getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public String getHostName() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof InetSocketAddress) {
|
||||
InetSocketAddress a = (InetSocketAddress) o;
|
||||
return a.address.equals(address) && a.port == port;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return port ^ address.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getHostName() + ":" + port;
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.net;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public abstract class ServerSocket {
|
||||
public abstract void bind(SocketAddress address) throws IOException;
|
||||
}
|
@ -1,201 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.net;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class Socket implements Closeable, AutoCloseable {
|
||||
|
||||
private static final int SD_RECEIVE = 0x00;
|
||||
private static final int SD_SEND = 0x01;
|
||||
private static final int SD_BOTH = 0x02;
|
||||
|
||||
private static final int BUFFER_SIZE = 65535;
|
||||
|
||||
/**
|
||||
* This method is called from all routines that depend on winsock in windows,
|
||||
* so it has public visibility
|
||||
* @throws IOException
|
||||
*/
|
||||
public static native void init() throws IOException;
|
||||
|
||||
/**
|
||||
* Creates the native socket object
|
||||
* @return Handle to the native object
|
||||
* @throws IOException
|
||||
*/
|
||||
private static native /* SOCKET */long create() throws IOException;
|
||||
|
||||
/**
|
||||
* Connects the native socket object to an address:port
|
||||
* @param sock Native socket handler
|
||||
* @param addr Address to connect to
|
||||
* @param port Port to connect to
|
||||
* @throws IOException
|
||||
*/
|
||||
private static native void connect(/* SOCKET */long sock, long addr, short port) throws IOException;
|
||||
private static native void bind(/* SOCKET */long sock, long addr, short port) throws IOException;
|
||||
|
||||
private static native void send(/* SOCKET */long sock, byte[] buffer, int start_pos, int count) throws IOException;
|
||||
private static native int recv(/* SOCKET */long sock, byte[] buffer, int start_pos, int count) throws IOException;
|
||||
|
||||
private static native void abort(/* SOCKET */long sock);
|
||||
private static native void close(/* SOCKET */long sock);
|
||||
private static native void closeOutput(/* SOCKET */long sock);
|
||||
private static native void closeInput(/* SOCKET */long sock);
|
||||
|
||||
private class SocketInputStream extends InputStream {
|
||||
|
||||
private boolean closed = false;
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (!closed) {
|
||||
closeInput(sock);
|
||||
closed = true;
|
||||
}
|
||||
super.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
close();
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
byte[] buffer = new byte[1];
|
||||
int size = recv(sock, buffer, 0, 1);
|
||||
if (size == 0) {
|
||||
return -1;
|
||||
}
|
||||
return buffer[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] buffer) throws IOException {
|
||||
if(buffer.length == 0) return 0; //spec says return 0 if buffer length is zero.
|
||||
int fullSize = buffer.length;
|
||||
int size;
|
||||
size = recv(sock, buffer, 0, Math.min(fullSize, Socket.BUFFER_SIZE));
|
||||
fullSize -= size;
|
||||
//removed loop, because otherwise interactive protocols will not work.
|
||||
if(size < 0) throw new IOException("Error while reading stream"); //as the manpage of recv says, a value below zero indicates an error.
|
||||
if(size == 0) return -1; // if the stream is closed (size == 0), then return -1 to indicate end of stream.
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
private class SocketOutputStream extends OutputStream {
|
||||
|
||||
private boolean closed = false;
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (!closed) {
|
||||
closeOutput(sock);
|
||||
closed = true;
|
||||
}
|
||||
super.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
close();
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int c) throws IOException {
|
||||
byte[] res = new byte[1];
|
||||
res[0] = (byte)c;
|
||||
send(sock, res, 0, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] buffer) throws IOException {
|
||||
int fullSize = buffer.length;
|
||||
int index = 0;
|
||||
int size;
|
||||
do {
|
||||
size = Math.min(fullSize, Socket.BUFFER_SIZE);
|
||||
send(sock, buffer, index, size);
|
||||
fullSize -= size;
|
||||
index += size;
|
||||
} while (fullSize != 0 && size != 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private long sock;
|
||||
private SocketInputStream inputStream;
|
||||
private SocketOutputStream outputStream;
|
||||
|
||||
public Socket() throws IOException {
|
||||
Socket.init();
|
||||
sock = create();
|
||||
inputStream = new SocketInputStream();
|
||||
outputStream = new SocketOutputStream();
|
||||
}
|
||||
|
||||
public SocketInputStream getInputStream() {
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
public SocketOutputStream getOutputStream() {
|
||||
return outputStream;
|
||||
}
|
||||
|
||||
public Socket(InetAddress address, int port) throws IOException {
|
||||
this();
|
||||
connect(sock, address.getRawAddress(), (short)port);
|
||||
}
|
||||
|
||||
public Socket(String host, int port) throws UnknownHostException, IOException {
|
||||
this(InetAddress.getByName(host), port);
|
||||
}
|
||||
|
||||
public void bind(SocketAddress bindpoint) throws IOException {
|
||||
if (bindpoint instanceof InetSocketAddress) {
|
||||
InetSocketAddress inetBindpoint = (InetSocketAddress)bindpoint;
|
||||
bind(sock, inetBindpoint.getAddress().getRawAddress(), (short) inetBindpoint.getPort());
|
||||
}
|
||||
}
|
||||
|
||||
public void setTcpNoDelay(boolean on) throws SocketException {}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
close(sock);
|
||||
}
|
||||
|
||||
public void shutdownInput() throws IOException {
|
||||
inputStream.close();
|
||||
}
|
||||
|
||||
public void shutdownOutput() throws IOException {
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
public SocketAddress getRemoteSocketAddress() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
close();
|
||||
super.finalize();
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.net;
|
||||
|
||||
public abstract class SocketAddress { }
|
@ -81,9 +81,7 @@ public final class URL {
|
||||
private static URLStreamHandler findHandler(String protocol)
|
||||
throws MalformedURLException
|
||||
{
|
||||
if ("http".equals(protocol) || "https".equals(protocol)) {
|
||||
return new avian.http.Handler();
|
||||
} else if ("avianvmresource".equals(protocol)) {
|
||||
if ("avianvmresource".equals(protocol)) {
|
||||
return new avian.avianvmresource.Handler();
|
||||
} else if ("file".equals(protocol)) {
|
||||
return new avian.file.Handler();
|
||||
|
@ -1,13 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.nio.channels;
|
||||
|
||||
public class ClosedSelectorException extends IllegalStateException { }
|
@ -1,239 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.nio.channels;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ProtocolFamily;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.StandardProtocolFamily;
|
||||
|
||||
// TODO: This class is both divergent from the Java standard and incomplete.
|
||||
public class DatagramChannel extends SelectableChannel
|
||||
implements ReadableByteChannel, WritableByteChannel
|
||||
{
|
||||
public static final int InvalidSocket = -1;
|
||||
|
||||
private int socket = makeSocket();
|
||||
private boolean blocking = true;
|
||||
private boolean connected = false;
|
||||
|
||||
public SelectableChannel configureBlocking(boolean v) throws IOException {
|
||||
blocking = v;
|
||||
configureBlocking();
|
||||
return this;
|
||||
}
|
||||
|
||||
private void configureBlocking() throws IOException {
|
||||
if (socket != InvalidSocket) {
|
||||
configureBlocking(socket, blocking);
|
||||
}
|
||||
}
|
||||
|
||||
int socketFD() {
|
||||
return socket;
|
||||
}
|
||||
|
||||
void handleReadyOps(int ops) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
public static DatagramChannel open(ProtocolFamily family)
|
||||
throws IOException
|
||||
{
|
||||
if (family.equals(StandardProtocolFamily.INET)) {
|
||||
Socket.init();
|
||||
|
||||
return new DatagramChannel();
|
||||
} else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
public static DatagramChannel open()
|
||||
throws IOException
|
||||
{
|
||||
return open(StandardProtocolFamily.INET);
|
||||
}
|
||||
|
||||
public DatagramSocket socket() {
|
||||
return new Handle();
|
||||
}
|
||||
|
||||
public DatagramChannel bind(SocketAddress address) throws IOException {
|
||||
InetSocketAddress inetAddress;
|
||||
try {
|
||||
inetAddress = (InetSocketAddress) address;
|
||||
} catch (ClassCastException e) {
|
||||
throw new UnsupportedAddressTypeException();
|
||||
}
|
||||
|
||||
if (inetAddress == null) {
|
||||
bind(socket, 0, 0);
|
||||
} else {
|
||||
bind(socket, inetAddress.getAddress().getRawAddress(),
|
||||
inetAddress.getPort());
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public DatagramChannel connect(SocketAddress address) throws IOException {
|
||||
InetSocketAddress inetAddress;
|
||||
try {
|
||||
inetAddress = (InetSocketAddress) address;
|
||||
} catch (ClassCastException e) {
|
||||
throw new UnsupportedAddressTypeException();
|
||||
}
|
||||
|
||||
connected = connect(socket, inetAddress.getAddress().getRawAddress(),
|
||||
inetAddress.getPort());
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public int write(ByteBuffer b) throws IOException {
|
||||
if (b.remaining() == 0) return 0;
|
||||
|
||||
byte[] array = b.array();
|
||||
if (array == null) throw new NullPointerException();
|
||||
|
||||
int c = write
|
||||
(socket, array, b.arrayOffset() + b.position(), b.remaining(), blocking);
|
||||
|
||||
if (c > 0) {
|
||||
b.position(b.position() + c);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
public int read(ByteBuffer b) throws IOException {
|
||||
int p = b.position();
|
||||
receive(b);
|
||||
return b.position() - p;
|
||||
}
|
||||
|
||||
public SocketAddress receive(ByteBuffer b) throws IOException {
|
||||
if (b.remaining() == 0) return null;
|
||||
|
||||
byte[] array = b.array();
|
||||
if (array == null) throw new NullPointerException();
|
||||
|
||||
int[] address = new int[2];
|
||||
|
||||
int c = receive
|
||||
(socket, array, b.arrayOffset() + b.position(), b.remaining(), blocking,
|
||||
address);
|
||||
|
||||
if (c > 0) {
|
||||
b.position(b.position() + c);
|
||||
|
||||
return new InetSocketAddress(ipv4ToString(address[0]), address[1]);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public int send(ByteBuffer b, SocketAddress address) throws IOException {
|
||||
if (b.remaining() == 0) return 0;
|
||||
|
||||
InetSocketAddress inetAddress;
|
||||
try {
|
||||
inetAddress = (InetSocketAddress) address;
|
||||
} catch (ClassCastException e) {
|
||||
throw new UnsupportedAddressTypeException();
|
||||
}
|
||||
|
||||
byte[] array = b.array();
|
||||
if (array == null) throw new NullPointerException();
|
||||
|
||||
int c = send
|
||||
(socket, inetAddress.getAddress().getRawAddress(),
|
||||
inetAddress.getPort(), array, b.arrayOffset() + b.position(),
|
||||
b.remaining(), blocking);
|
||||
|
||||
if (c > 0) {
|
||||
b.position(b.position() + c);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
private static String ipv4ToString(int address) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( address >> 24 ).append('.')
|
||||
.append((address >> 16) & 0xFF).append('.')
|
||||
.append((address >> 8) & 0xFF).append('.')
|
||||
.append( address & 0xFF);
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public class Handle extends DatagramSocket {
|
||||
public SocketAddress getRemoteSocketAddress() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void bind(SocketAddress address) throws SocketException {
|
||||
try {
|
||||
DatagramChannel.this.bind(address);
|
||||
} catch (SocketException e) {
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
SocketException se = new SocketException();
|
||||
se.initCause(e);
|
||||
throw se;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isConnected() { return connected; }
|
||||
|
||||
/** TODO: This is probably incomplete. */
|
||||
public DatagramChannel disconnect() throws IOException {
|
||||
connect(socket, 0, 0);
|
||||
connected = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
if (isOpen()) {
|
||||
super.close();
|
||||
close(socket);
|
||||
}
|
||||
}
|
||||
|
||||
private static native int makeSocket();
|
||||
private static native void configureBlocking(int socket, boolean blocking)
|
||||
throws IOException;
|
||||
private static native void bind(int socket, int host, int port)
|
||||
throws IOException;
|
||||
private static native boolean connect(int socket, int host, int port)
|
||||
throws IOException;
|
||||
private static native int write(int socket, byte[] array, int offset,
|
||||
int length, boolean blocking)
|
||||
throws IOException;
|
||||
private static native int send(int socket, int host, int port,
|
||||
byte[] array, int offset,
|
||||
int length, boolean blocking)
|
||||
throws IOException;
|
||||
private static native int receive(int socket, byte[] array, int offset,
|
||||
int length, boolean blocking,
|
||||
int[] address)
|
||||
throws IOException;
|
||||
private static native void close(int socket);
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.nio.channels;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public abstract class FileChannel implements Channel {
|
||||
|
||||
public static enum MapMode {
|
||||
PRIVATE, READ_ONLY, READ_WRITE
|
||||
};
|
||||
|
||||
public abstract int read(ByteBuffer dst) throws IOException;
|
||||
|
||||
public abstract int read(ByteBuffer dst, long position) throws IOException;
|
||||
|
||||
public abstract int write(ByteBuffer dst) throws IOException;
|
||||
|
||||
public abstract int write(ByteBuffer dst, long position) throws IOException;
|
||||
|
||||
public abstract long position() throws IOException;
|
||||
|
||||
public abstract FileChannel position(long position) throws IOException;
|
||||
|
||||
public abstract long size() throws IOException;
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.nio.channels;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public abstract class SelectableChannel implements Channel {
|
||||
private SelectionKey key;
|
||||
private boolean open = true;
|
||||
|
||||
abstract int socketFD();
|
||||
|
||||
abstract void handleReadyOps(int ops);
|
||||
|
||||
public abstract SelectableChannel configureBlocking(boolean v)
|
||||
throws IOException;
|
||||
|
||||
public SelectionKey register(Selector selector, int interestOps,
|
||||
Object attachment)
|
||||
{
|
||||
key = new SelectionKey(this, selector, interestOps, attachment);
|
||||
selector.add(key);
|
||||
return key;
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return open;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
open = false;
|
||||
key = null;
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.nio.channels;
|
||||
|
||||
public class SelectionKey {
|
||||
public static final int OP_READ = 1 << 0;
|
||||
public static final int OP_WRITE = 1 << 2;
|
||||
public static final int OP_CONNECT = 1 << 3;
|
||||
public static final int OP_ACCEPT = 1 << 4;
|
||||
|
||||
private final SelectableChannel channel;
|
||||
private final Selector selector;
|
||||
private int interestOps;
|
||||
private int readyOps;
|
||||
private final Object attachment;
|
||||
|
||||
public SelectionKey(SelectableChannel channel, Selector selector,
|
||||
int interestOps, Object attachment)
|
||||
{
|
||||
this.channel = channel;
|
||||
this.selector = selector;
|
||||
this.interestOps = interestOps;
|
||||
this.attachment = attachment;
|
||||
this.readyOps = 0;
|
||||
}
|
||||
|
||||
public int interestOps() {
|
||||
return interestOps;
|
||||
}
|
||||
|
||||
public SelectionKey interestOps(int v) {
|
||||
this.interestOps = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int readyOps() {
|
||||
return readyOps;
|
||||
}
|
||||
|
||||
public void readyOps(int v) {
|
||||
this.readyOps = v;
|
||||
}
|
||||
|
||||
public boolean isReadable() {
|
||||
return (readyOps & OP_READ) != 0;
|
||||
}
|
||||
|
||||
public boolean isWritable() {
|
||||
return (readyOps & OP_WRITE) != 0;
|
||||
}
|
||||
|
||||
public boolean isConnectable() {
|
||||
return (readyOps & OP_CONNECT) != 0;
|
||||
}
|
||||
|
||||
public boolean isAcceptable() {
|
||||
return (readyOps & OP_ACCEPT) != 0;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return channel.isOpen() && selector.isOpen();
|
||||
}
|
||||
|
||||
public SelectableChannel channel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public Selector selector() {
|
||||
return selector;
|
||||
}
|
||||
|
||||
public Object attachment() {
|
||||
return attachment;
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.nio.channels;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
|
||||
public abstract class Selector {
|
||||
protected final Set<SelectionKey> keys = new HashSet();
|
||||
protected final Set<SelectionKey> selectedKeys = new HashSet();
|
||||
|
||||
public static Selector open() throws IOException {
|
||||
return new SocketSelector();
|
||||
}
|
||||
|
||||
public void add(SelectionKey key) {
|
||||
keys.add(key);
|
||||
}
|
||||
|
||||
public void remove(SelectionKey key) {
|
||||
keys.remove(key);
|
||||
}
|
||||
|
||||
public Set<SelectionKey> keys() {
|
||||
return keys;
|
||||
}
|
||||
|
||||
public Set<SelectionKey> selectedKeys() {
|
||||
return selectedKeys;
|
||||
}
|
||||
|
||||
public abstract boolean isOpen();
|
||||
|
||||
public abstract Selector wakeup();
|
||||
|
||||
public abstract int selectNow() throws IOException;
|
||||
|
||||
public abstract int select(long interval) throws IOException;
|
||||
|
||||
public abstract int select() throws IOException;
|
||||
|
||||
public abstract void close();
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.nio.channels;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
public class ServerSocketChannel extends SelectableChannel {
|
||||
private final SocketChannel channel;
|
||||
|
||||
private ServerSocketChannel() throws IOException {
|
||||
channel = new SocketChannel();
|
||||
}
|
||||
|
||||
public static ServerSocketChannel open() throws IOException {
|
||||
Socket.init();
|
||||
|
||||
return new ServerSocketChannel();
|
||||
}
|
||||
|
||||
public int socketFD() {
|
||||
return channel.socketFD();
|
||||
}
|
||||
|
||||
public void handleReadyOps(int ops) {
|
||||
channel.handleReadyOps(ops);
|
||||
}
|
||||
|
||||
public SelectableChannel configureBlocking(boolean v) throws IOException {
|
||||
return channel.configureBlocking(v);
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
channel.close();
|
||||
}
|
||||
|
||||
public SocketChannel accept() throws IOException {
|
||||
SocketChannel c = new SocketChannel();
|
||||
c.socket = doAccept();
|
||||
c.connected = true;
|
||||
return c;
|
||||
}
|
||||
|
||||
public ServerSocket socket() {
|
||||
return new Handle();
|
||||
}
|
||||
|
||||
private int doAccept() throws IOException {
|
||||
while (true) {
|
||||
int s = natDoAccept(channel.socket);
|
||||
if (s != -1) {
|
||||
return s;
|
||||
}
|
||||
// todo: throw ClosedByInterruptException if this thread was
|
||||
// interrupted during the accept call
|
||||
}
|
||||
}
|
||||
|
||||
private void doListen(int socket, int host, int port) throws IOException {
|
||||
Socket.init();
|
||||
|
||||
natDoListen(socket, host, port);
|
||||
}
|
||||
|
||||
public class Handle extends ServerSocket {
|
||||
public void bind(SocketAddress address)
|
||||
throws IOException
|
||||
{
|
||||
InetSocketAddress a;
|
||||
try {
|
||||
a = (InetSocketAddress) address;
|
||||
} catch (ClassCastException e) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
doListen(channel.socket, a.getAddress().getRawAddress(), a.getPort());
|
||||
}
|
||||
}
|
||||
|
||||
private static native int natDoAccept(int socket) throws IOException;
|
||||
private static native void natDoListen(int socket, int host, int port) throws IOException;
|
||||
}
|
@ -1,214 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.nio.channels;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class SocketChannel extends SelectableChannel
|
||||
implements ReadableByteChannel, GatheringByteChannel
|
||||
{
|
||||
public static final int InvalidSocket = -1;
|
||||
|
||||
int socket = makeSocket();
|
||||
boolean connected = false;
|
||||
boolean readyToConnect = false;
|
||||
boolean blocking = true;
|
||||
|
||||
public static SocketChannel open() throws IOException {
|
||||
Socket.init();
|
||||
|
||||
return new SocketChannel();
|
||||
}
|
||||
|
||||
public SelectableChannel configureBlocking(boolean v) throws IOException {
|
||||
blocking = v;
|
||||
if (socket != InvalidSocket) {
|
||||
configureBlocking(socket, v);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isBlocking() {
|
||||
return blocking;
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return connected;
|
||||
}
|
||||
|
||||
public Socket socket() {
|
||||
try {
|
||||
return new Handle();
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean connect(SocketAddress address) throws IOException {
|
||||
InetSocketAddress a;
|
||||
try {
|
||||
a = (InetSocketAddress) address;
|
||||
} catch (ClassCastException e) {
|
||||
throw new UnsupportedAddressTypeException();
|
||||
}
|
||||
doConnect(socket, a.getAddress().getRawAddress(), a.getPort());
|
||||
configureBlocking(blocking);
|
||||
return connected;
|
||||
}
|
||||
|
||||
public boolean finishConnect() throws IOException {
|
||||
if (! connected) {
|
||||
while (! readyToConnect) {
|
||||
Selector selector = Selector.open();
|
||||
SelectionKey key = register(selector, SelectionKey.OP_CONNECT, null);
|
||||
|
||||
if (blocking) {
|
||||
selector.select();
|
||||
} else {
|
||||
selector.selectNow();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
natFinishConnect(socket);
|
||||
|
||||
connected = readyToConnect;
|
||||
}
|
||||
|
||||
return connected;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
if (isOpen()) {
|
||||
super.close();
|
||||
closeSocket();
|
||||
}
|
||||
}
|
||||
|
||||
private void doConnect(int socket, int host, int port)
|
||||
throws IOException
|
||||
{
|
||||
connected = natDoConnect(socket, host, port);
|
||||
}
|
||||
|
||||
public int read(ByteBuffer b) throws IOException {
|
||||
if (! isOpen()) return -1;
|
||||
if (b.remaining() == 0) return 0;
|
||||
|
||||
byte[] array = b.array();
|
||||
if (array == null) throw new NullPointerException();
|
||||
|
||||
int r = natRead(socket, array, b.arrayOffset() + b.position(), b.remaining(), blocking);
|
||||
if (r > 0) {
|
||||
b.position(b.position() + r);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
public int write(ByteBuffer b) throws IOException {
|
||||
if (! connected) {
|
||||
natThrowWriteError(socket);
|
||||
}
|
||||
if (b.remaining() == 0) return 0;
|
||||
|
||||
byte[] array = b.array();
|
||||
if (array == null) throw new NullPointerException();
|
||||
|
||||
int w = natWrite(socket, array, b.arrayOffset() + b.position(), b.remaining(), blocking);
|
||||
if (w > 0) {
|
||||
b.position(b.position() + w);
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
public long write(ByteBuffer[] srcs) throws IOException {
|
||||
return write(srcs, 0, srcs.length);
|
||||
}
|
||||
|
||||
public long write(ByteBuffer[] srcs, int offset, int length)
|
||||
throws IOException
|
||||
{
|
||||
long total = 0;
|
||||
for (int i = offset; i < offset + length; ++i) {
|
||||
total += write(srcs[i]);
|
||||
if (srcs[i].hasRemaining()) {
|
||||
return total;
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
private void closeSocket() {
|
||||
natCloseSocket(socket);
|
||||
}
|
||||
|
||||
int socketFD() {
|
||||
return socket;
|
||||
}
|
||||
|
||||
void handleReadyOps(int ops) {
|
||||
if ((ops & SelectionKey.OP_CONNECT) != 0) {
|
||||
readyToConnect = true;
|
||||
}
|
||||
}
|
||||
|
||||
public class Handle extends Socket {
|
||||
public Handle() throws IOException {
|
||||
super();
|
||||
}
|
||||
|
||||
public void setTcpNoDelay(boolean on) throws SocketException {
|
||||
natSetTcpNoDelay(socket, on);
|
||||
}
|
||||
|
||||
public void bind(SocketAddress address)
|
||||
throws IOException
|
||||
{
|
||||
InetSocketAddress a;
|
||||
try {
|
||||
a = (InetSocketAddress) address;
|
||||
} catch (ClassCastException e) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
if (a == null) {
|
||||
SocketChannel.bind(socket, 0, 0);
|
||||
} else {
|
||||
SocketChannel.bind
|
||||
(socket, a.getAddress().getRawAddress(), a.getPort());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static native int makeSocket();
|
||||
private static native void configureBlocking(int socket, boolean blocking)
|
||||
throws IOException;
|
||||
|
||||
private static native void natSetTcpNoDelay(int socket, boolean on)
|
||||
throws SocketException;
|
||||
private static native void bind(int socket, int host, int port)
|
||||
throws IOException;
|
||||
private static native boolean natDoConnect(int socket, int host, int port)
|
||||
throws IOException;
|
||||
private static native void natFinishConnect(int socket)
|
||||
throws IOException;
|
||||
private static native int natRead(int socket, byte[] buffer, int offset, int length, boolean blocking)
|
||||
throws IOException;
|
||||
private static native int natWrite(int socket, byte[] buffer, int offset, int length, boolean blocking)
|
||||
throws IOException;
|
||||
private static native void natThrowWriteError(int socket) throws IOException;
|
||||
private static native void natCloseSocket(int socket);
|
||||
}
|
@ -1,133 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.nio.channels;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.net.Socket;
|
||||
|
||||
class SocketSelector extends Selector {
|
||||
protected volatile long state;
|
||||
protected final Object lock = new Object();
|
||||
protected boolean woken = false;
|
||||
|
||||
public SocketSelector() throws IOException {
|
||||
Socket.init();
|
||||
|
||||
state = natInit();
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return state != 0;
|
||||
}
|
||||
|
||||
public Selector wakeup() {
|
||||
synchronized (lock) {
|
||||
if (isOpen() && (! woken)) {
|
||||
woken = true;
|
||||
|
||||
natWakeup(state);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private boolean clearWoken() {
|
||||
synchronized (lock) {
|
||||
if (woken) {
|
||||
woken = false;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized int selectNow() throws IOException {
|
||||
return doSelect(-1);
|
||||
}
|
||||
|
||||
public synchronized int select() throws IOException {
|
||||
return doSelect(0);
|
||||
}
|
||||
|
||||
public synchronized int select(long interval) throws IOException {
|
||||
if (interval < 0) throw new IllegalArgumentException();
|
||||
|
||||
return doSelect(interval);
|
||||
}
|
||||
|
||||
public int doSelect(long interval) throws IOException {
|
||||
if (! isOpen()) {
|
||||
throw new ClosedSelectorException();
|
||||
}
|
||||
|
||||
selectedKeys.clear();
|
||||
|
||||
if (clearWoken()) interval = -1;
|
||||
|
||||
int max=0;
|
||||
for (Iterator<SelectionKey> it = keys.iterator();
|
||||
it.hasNext();)
|
||||
{
|
||||
SelectionKey key = it.next();
|
||||
SelectableChannel c = key.channel();
|
||||
int socket = c.socketFD();
|
||||
if (c.isOpen()) {
|
||||
key.readyOps(0);
|
||||
max = natSelectUpdateInterestSet
|
||||
(socket, key.interestOps(), state, max);
|
||||
} else {
|
||||
natSelectClearAll(socket, state);
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
int r = natDoSocketSelect(state, max, interval);
|
||||
|
||||
if (r > 0) {
|
||||
for (SelectionKey key : keys) {
|
||||
SelectableChannel c = key.channel();
|
||||
int socket = c.socketFD();
|
||||
int ready = natUpdateReadySet(socket, key.interestOps(), state);
|
||||
key.readyOps(ready);
|
||||
if (ready != 0) {
|
||||
c.handleReadyOps(ready);
|
||||
selectedKeys.add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
clearWoken();
|
||||
|
||||
return selectedKeys.size();
|
||||
}
|
||||
|
||||
public synchronized void close() {
|
||||
synchronized (lock) {
|
||||
if (isOpen()) {
|
||||
natClose(state);
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static native long natInit();
|
||||
private static native void natWakeup(long state);
|
||||
private static native void natClose(long state);
|
||||
private static native void natSelectClearAll(int socket, long state);
|
||||
private static native int natSelectUpdateInterestSet(int socket,
|
||||
int interest,
|
||||
long state,
|
||||
int max);
|
||||
private static native int natDoSocketSelect(long state, int max, long interval)
|
||||
throws IOException;
|
||||
private static native int natUpdateReadySet(int socket, int interest, long state);
|
||||
}
|
@ -11,8 +11,6 @@
|
||||
package java.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
public class ArrayList<T> extends AbstractList<T> implements java.io.Serializable, RandomAccess {
|
||||
private static final int MinimumCapacity = 16;
|
||||
@ -187,23 +185,4 @@ public class ArrayList<T> extends AbstractList<T> implements java.io.Serializabl
|
||||
public String toString() {
|
||||
return avian.Data.toString(this);
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
out.defaultWriteObject();
|
||||
out.writeInt(array.length);
|
||||
for (T o : this) {
|
||||
out.writeObject(o);
|
||||
}
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in)
|
||||
throws ClassNotFoundException, IOException
|
||||
{
|
||||
in.defaultReadObject();
|
||||
int capacity = in.readInt();
|
||||
grow(capacity);
|
||||
for (int i = 0; i < size; i++) {
|
||||
array[i] = in.readObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ public abstract class Calendar {
|
||||
protected Calendar() { }
|
||||
|
||||
public static Calendar getInstance() {
|
||||
return new MyCalendar(System.currentTimeMillis());
|
||||
return new MyCalendar(0);
|
||||
}
|
||||
|
||||
public int get(int field) {
|
||||
|
@ -31,10 +31,6 @@ public class Collections {
|
||||
}
|
||||
}
|
||||
|
||||
public static void shuffle(List list) {
|
||||
shuffle(list, new Random());
|
||||
}
|
||||
|
||||
public static void sort(List list) {
|
||||
sort(list, new Comparator() {
|
||||
public int compare(Object a, Object b) {
|
||||
@ -200,6 +196,14 @@ public class Collections {
|
||||
return new ReverseComparator<T>(cmp);
|
||||
}
|
||||
|
||||
public static <T> boolean addAll(Collection<? super T> collection, T... items) {
|
||||
boolean modified = false;
|
||||
for (T item : items) {
|
||||
modified |= collection.add(item);
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
static class IteratorEnumeration<T> implements Enumeration<T> {
|
||||
private final Iterator<T> it;
|
||||
|
||||
|
@ -13,10 +13,6 @@ package java.util;
|
||||
public class Date {
|
||||
public final long when;
|
||||
|
||||
public Date() {
|
||||
when = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public Date(long when) {
|
||||
this.when = when;
|
||||
}
|
||||
|
@ -23,16 +23,6 @@ public class Random {
|
||||
setSeed(seed);
|
||||
}
|
||||
|
||||
public Random() {
|
||||
synchronized (Random.class) {
|
||||
setSeed(nextSeed ^ System.currentTimeMillis());
|
||||
nextSeed *= 123456789987654321L;
|
||||
if (nextSeed == 0) {
|
||||
nextSeed = InitialSeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setSeed(long seed) {
|
||||
this.seed = (seed ^ Mask) & ((1L << 48) - 1);
|
||||
}
|
||||
|
@ -11,8 +11,6 @@
|
||||
package java.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
public class TreeMap<K,V> implements NavigableMap<K,V> {
|
||||
private final Comparator<K> comparator;
|
||||
@ -279,26 +277,4 @@ public class TreeMap<K,V> implements NavigableMap<K,V> {
|
||||
return new avian.Data.ValueIterator(set.iterator());
|
||||
}
|
||||
}
|
||||
|
||||
public final static long serialVersionUID = 0x0cc1f63e2d256ae6l;
|
||||
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
out.defaultWriteObject();
|
||||
out.writeInt(size());
|
||||
for (Entry<K, V> entry : entrySet()) {
|
||||
out.writeObject(entry.getKey());
|
||||
out.writeObject(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in) throws IOException {
|
||||
in.defaultReadObject();
|
||||
initializeSet();
|
||||
int size = in.readInt();
|
||||
for (int i = 0; i < size; i++) try {
|
||||
put((K) in.readObject(), (V) in.readObject());
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,19 +17,6 @@ public class UUID {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public static UUID randomUUID() {
|
||||
byte[] array = new byte[16];
|
||||
|
||||
new Random().nextBytes(array);
|
||||
|
||||
array[6] &= 0x0f;
|
||||
array[6] |= 0x40;
|
||||
array[8] &= 0x3f;
|
||||
array[8] |= 0x80;
|
||||
|
||||
return new UUID(array);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
toHex(sb, data, 0, 4); sb.append('-');
|
||||
|
@ -1,73 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
public class ExecutorCompletionService<T> implements CompletionService<T> {
|
||||
private final Executor executor;
|
||||
private final BlockingQueue<Future<T>> completionQueue;
|
||||
|
||||
public ExecutorCompletionService(Executor executor) {
|
||||
this(executor, new LinkedBlockingQueue<Future<T>>());
|
||||
}
|
||||
|
||||
public ExecutorCompletionService(Executor executor, BlockingQueue<Future<T>> completionQueue) {
|
||||
this.executor = executor;
|
||||
this.completionQueue = completionQueue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<T> submit(Callable<T> task) {
|
||||
ECSFuture f = new ECSFuture(task);
|
||||
|
||||
executor.execute(f);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<T> submit(Runnable task, T result) {
|
||||
ECSFuture f = new ECSFuture(task, result);
|
||||
|
||||
executor.execute(f);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<T> take() throws InterruptedException {
|
||||
return completionQueue.take();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<T> poll() {
|
||||
return completionQueue.poll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<T> poll(long timeout, TimeUnit unit) throws InterruptedException {
|
||||
return completionQueue.poll(timeout, unit);
|
||||
}
|
||||
|
||||
private class ECSFuture extends FutureTask<T> implements Future<T> {
|
||||
private ECSFuture(Runnable r, T result) {
|
||||
super(r, result);
|
||||
}
|
||||
|
||||
private ECSFuture(Callable<T> callable) {
|
||||
super(callable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
completionQueue.add(this);
|
||||
}
|
||||
}
|
||||
}
|
@ -64,11 +64,7 @@ public class FutureTask<T> implements RunnableFuture<T> {
|
||||
* and thus thread is in interrupted status, the exception should
|
||||
* throw immediately on the sleep call.
|
||||
*/
|
||||
try {
|
||||
Thread.sleep(Long.MAX_VALUE);
|
||||
} catch (InterruptedException e) {
|
||||
// expected
|
||||
}
|
||||
throw new UnsupportedOperationException("Blocking not supported.");
|
||||
}
|
||||
|
||||
Thread.interrupted(); // reset interrupted status if set
|
||||
@ -127,43 +123,13 @@ public class FutureTask<T> implements RunnableFuture<T> {
|
||||
|
||||
@Override
|
||||
public T get() throws InterruptedException, ExecutionException {
|
||||
try {
|
||||
return get(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
|
||||
} catch (TimeoutException e) {
|
||||
// not possible
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
throw new UnsupportedOperationException("System clock unavailable");
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(long timeout, TimeUnit unit) throws InterruptedException,
|
||||
ExecutionException,
|
||||
TimeoutException {
|
||||
long timeoutInMillis = unit.toMillis(timeout);
|
||||
long startTime = 0;
|
||||
if (timeoutInMillis < Long.MAX_VALUE) {
|
||||
startTime = System.currentTimeMillis();
|
||||
}
|
||||
long remainingTime;
|
||||
synchronized (notifyLock) {
|
||||
remainingTime = timeoutInMillis;
|
||||
while (! isDone() && remainingTime > 0) {
|
||||
notifyLock.wait(remainingTime);
|
||||
|
||||
if (timeoutInMillis < Long.MAX_VALUE) {
|
||||
remainingTime = timeoutInMillis - (System.currentTimeMillis() - startTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (remainingTime <= 0) {
|
||||
throw new TimeoutException();
|
||||
} else if (currentState.get() == State.Canceled) {
|
||||
throw new CancellationException();
|
||||
} else if (failure != null) {
|
||||
throw new ExecutionException(failure);
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
throw new UnsupportedOperationException("System clock unavailable");
|
||||
}
|
||||
}
|
||||
|
@ -1,302 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
import java.util.AbstractQueue;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class LinkedBlockingQueue<T> extends AbstractQueue<T>
|
||||
implements BlockingQueue<T> {
|
||||
private final Object collectionLock;
|
||||
private final LinkedList<T> storage;
|
||||
private final int capacity;
|
||||
|
||||
public LinkedBlockingQueue() {
|
||||
this(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
public LinkedBlockingQueue(int capacity) {
|
||||
collectionLock = new Object();
|
||||
this.capacity = capacity;
|
||||
storage = new LinkedList<T>();
|
||||
}
|
||||
|
||||
// should be synchronized on collectionLock before calling
|
||||
private void handleRemove() {
|
||||
collectionLock.notifyAll();
|
||||
}
|
||||
|
||||
// should be synchronized on collectionLock before calling
|
||||
private void handleAdd() {
|
||||
collectionLock.notifyAll();
|
||||
}
|
||||
|
||||
// should be synchronized on collectionLock before calling
|
||||
private void blockTillNotFull() throws InterruptedException {
|
||||
blockTillNotFull(Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
// should be synchronized on collectionLock before calling
|
||||
private void blockTillNotFull(long maxWaitInMillis) throws InterruptedException {
|
||||
if (capacity > storage.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
long startTime = 0;
|
||||
if (maxWaitInMillis != Long.MAX_VALUE) {
|
||||
startTime = System.currentTimeMillis();
|
||||
}
|
||||
long remainingWait = maxWaitInMillis;
|
||||
while (remainingWait > 0) {
|
||||
collectionLock.wait(remainingWait);
|
||||
|
||||
if (capacity > storage.size()) {
|
||||
return;
|
||||
} else if (maxWaitInMillis != Long.MAX_VALUE) {
|
||||
remainingWait = maxWaitInMillis - (System.currentTimeMillis() - startTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// should be synchronized on collectionLock before calling
|
||||
private void blockTillNotEmpty() throws InterruptedException {
|
||||
blockTillNotEmpty(Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
// should be synchronized on collectionLock before calling
|
||||
private void blockTillNotEmpty(long maxWaitInMillis) throws InterruptedException {
|
||||
if (! storage.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
long startTime = 0;
|
||||
if (maxWaitInMillis != Long.MAX_VALUE) {
|
||||
startTime = System.currentTimeMillis();
|
||||
}
|
||||
long remainingWait = maxWaitInMillis;
|
||||
while (remainingWait > 0) {
|
||||
collectionLock.wait(remainingWait);
|
||||
|
||||
if (! storage.isEmpty()) {
|
||||
return;
|
||||
} else if (maxWaitInMillis != Long.MAX_VALUE) {
|
||||
remainingWait = maxWaitInMillis - (System.currentTimeMillis() - startTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean offer(T element) {
|
||||
synchronized (collectionLock) {
|
||||
if (capacity > storage.size()) {
|
||||
storage.addLast(element);
|
||||
|
||||
handleAdd();
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean offer(T e, long timeout, TimeUnit unit) throws InterruptedException {
|
||||
long timeoutInMillis = unit.toMillis(timeout);
|
||||
synchronized (collectionLock) {
|
||||
// block till we can add or have reached timeout
|
||||
blockTillNotFull(timeoutInMillis);
|
||||
|
||||
return offer(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(T e) throws InterruptedException {
|
||||
synchronized (collectionLock) {
|
||||
// block till we have space
|
||||
blockTillNotFull();
|
||||
|
||||
storage.add(e);
|
||||
handleAdd();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends T> c) {
|
||||
synchronized (collectionLock) {
|
||||
if (storage.size() + c.size() > capacity) {
|
||||
throw new IllegalStateException("Not enough space");
|
||||
}
|
||||
|
||||
if (c.isEmpty()) {
|
||||
return false;
|
||||
} else {
|
||||
storage.addAll(c);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T peek() {
|
||||
synchronized (collectionLock) {
|
||||
if (storage.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return storage.getFirst();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// should be synchronized on collectionLock before calling
|
||||
private T removeFirst() {
|
||||
T result = storage.removeFirst();
|
||||
handleRemove();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T poll() {
|
||||
synchronized (collectionLock) {
|
||||
if (storage.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return removeFirst();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T poll(long timeout, TimeUnit unit) throws InterruptedException {
|
||||
long timeoutInMillis = unit.toMillis(timeout);
|
||||
synchronized (collectionLock) {
|
||||
// block till we available or timeout
|
||||
blockTillNotEmpty(timeoutInMillis);
|
||||
|
||||
return poll();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T take() throws InterruptedException {
|
||||
synchronized (collectionLock) {
|
||||
// block till we available
|
||||
blockTillNotEmpty();
|
||||
|
||||
return removeFirst();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int drainTo(Collection<? super T> c) {
|
||||
return drainTo(c, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int drainTo(Collection<? super T> c, int maxElements) {
|
||||
int remainingElements = maxElements;
|
||||
synchronized (collectionLock) {
|
||||
while (remainingElements > 0 && ! storage.isEmpty()) {
|
||||
c.add(storage.removeFirst());
|
||||
remainingElements--;
|
||||
}
|
||||
|
||||
if (remainingElements != maxElements) {
|
||||
handleRemove();
|
||||
}
|
||||
|
||||
return maxElements - remainingElements;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int remainingCapacity() {
|
||||
synchronized (collectionLock) {
|
||||
return capacity - storage.size();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
synchronized (collectionLock) {
|
||||
return storage.size();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object element) {
|
||||
synchronized (collectionLock) {
|
||||
return storage.contains(element);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
synchronized (collectionLock) {
|
||||
return storage.containsAll(c);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object element) {
|
||||
synchronized (collectionLock) {
|
||||
if (storage.remove(element)) {
|
||||
handleRemove();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
synchronized (collectionLock) {
|
||||
if (storage.removeAll(c)) {
|
||||
handleRemove();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
synchronized (collectionLock) {
|
||||
storage.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
synchronized (collectionLock) {
|
||||
return storage.toArray();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S> S[] toArray(S[] array) {
|
||||
synchronized (collectionLock) {
|
||||
return storage.toArray(array);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
throw new UnsupportedOperationException("Not implemented yet");
|
||||
}
|
||||
}
|
@ -397,20 +397,4 @@ public enum TimeUnit {
|
||||
obj.wait(ms, ns);
|
||||
}
|
||||
}
|
||||
|
||||
public void timedJoin(Thread thread, long timeout) throws InterruptedException {
|
||||
if (timeout > 0) {
|
||||
long ms = toMillis(timeout);
|
||||
int ns = excessNanos(timeout, ms);
|
||||
thread.join(ms, ns);
|
||||
}
|
||||
}
|
||||
|
||||
public void sleep(long timeout) throws InterruptedException {
|
||||
if (timeout > 0) {
|
||||
long ms = toMillis(timeout);
|
||||
int ns = excessNanos(timeout, ms);
|
||||
Thread.sleep(ms, ns);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,6 @@ public class ZipEntry {
|
||||
|
||||
public ZipEntry(String name) {
|
||||
this.name = name;
|
||||
setTime(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
//Method to return name of the file
|
||||
|
@ -1,205 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
/*
|
||||
* This file implements a simple cross-platform JNI sockets API
|
||||
* It is used from different classes of the default Avian classpath
|
||||
*/
|
||||
|
||||
#ifndef SGX
|
||||
|
||||
#include "sockets.h"
|
||||
|
||||
namespace avian {
|
||||
namespace classpath {
|
||||
namespace sockets {
|
||||
|
||||
int last_socket_error()
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
int error = WSAGetLastError();
|
||||
#else
|
||||
int error = errno;
|
||||
#endif
|
||||
return error;
|
||||
}
|
||||
|
||||
void init(JNIEnv* ONLY_ON_WINDOWS(e))
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
static bool wsaInitialized = false;
|
||||
if (not wsaInitialized) {
|
||||
WSADATA data;
|
||||
int r = WSAStartup(MAKEWORD(2, 2), &data);
|
||||
if (r or LOBYTE(data.wVersion) != 2 or HIBYTE(data.wVersion) != 2) {
|
||||
throwNew(e, "java/io/IOException", "WSAStartup failed");
|
||||
} else {
|
||||
wsaInitialized = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SOCKET create(JNIEnv* e)
|
||||
{
|
||||
SOCKET sock;
|
||||
if (INVALID_SOCKET == (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))) {
|
||||
char buf[255];
|
||||
sprintf(
|
||||
buf, "Can't create a socket. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return 0; // This doesn't matter cause we have risen an exception
|
||||
}
|
||||
return sock;
|
||||
}
|
||||
|
||||
void connect(JNIEnv* e, SOCKET sock, long addr, short port)
|
||||
{
|
||||
sockaddr_in adr;
|
||||
adr.sin_family = AF_INET;
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
adr.sin_addr.S_un.S_addr = htonl(addr);
|
||||
#else
|
||||
adr.sin_addr.s_addr = htonl(addr);
|
||||
#endif
|
||||
adr.sin_port = htons(port);
|
||||
|
||||
if (SOCKET_ERROR == ::connect(sock, (sockaddr*)&adr, sizeof(adr))) {
|
||||
char buf[255];
|
||||
sprintf(
|
||||
buf, "Can't connect a socket. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void bind(JNIEnv* e, SOCKET sock, long addr, short port)
|
||||
{
|
||||
sockaddr_in adr;
|
||||
adr.sin_family = AF_INET;
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
adr.sin_addr.S_un.S_addr = htonl(addr);
|
||||
#else
|
||||
adr.sin_addr.s_addr = htonl(addr);
|
||||
#endif
|
||||
adr.sin_port = htons(port);
|
||||
|
||||
if (SOCKET_ERROR == ::bind(sock, (sockaddr*)&adr, sizeof(adr))) {
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't bind a socket. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SOCKET accept(JNIEnv* e, SOCKET sock, long* client_addr, short* client_port)
|
||||
{
|
||||
sockaddr_in adr;
|
||||
SOCKET client_socket = ::accept(sock, (sockaddr*)&adr, NULL);
|
||||
if (INVALID_SOCKET == client_socket) {
|
||||
char buf[255];
|
||||
sprintf(buf,
|
||||
"Can't accept the incoming connection. System error: %d",
|
||||
last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
if (client_addr != NULL) {
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
*client_addr = ntohl(adr.sin_addr.S_un.S_addr);
|
||||
#else
|
||||
*client_addr = ntohl(adr.sin_addr.s_addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (client_port != NULL) {
|
||||
*client_port = ntohs(adr.sin_port);
|
||||
}
|
||||
|
||||
return client_socket;
|
||||
}
|
||||
|
||||
void send(JNIEnv* e, SOCKET sock, const char* buff_ptr, int buff_size)
|
||||
{
|
||||
if (SOCKET_ERROR == ::send(sock, buff_ptr, buff_size, 0)) {
|
||||
char buf[255];
|
||||
sprintf(buf,
|
||||
"Can't send data through the socket. System error: %d",
|
||||
last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int recv(JNIEnv* e, SOCKET sock, char* buff_ptr, int buff_size)
|
||||
{
|
||||
int length = ::recv(sock, buff_ptr, buff_size, 0);
|
||||
if (SOCKET_ERROR == length) {
|
||||
char buf[255];
|
||||
sprintf(buf,
|
||||
"Can't receive data through the socket. System error: %d",
|
||||
last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return 0; // This doesn't matter cause we have risen an exception
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
void abort(JNIEnv* e, SOCKET sock)
|
||||
{
|
||||
if (SOCKET_ERROR == ::closesocket(sock)) {
|
||||
char buf[255];
|
||||
sprintf(
|
||||
buf, "Can't close the socket. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
}
|
||||
}
|
||||
|
||||
void close(JNIEnv* e, SOCKET sock)
|
||||
{
|
||||
if (SOCKET_ERROR == ::shutdown(sock, SD_BOTH)) {
|
||||
int errcode = last_socket_error();
|
||||
if (errcode != ENOTCONN) {
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't shutdown the socket. System error: %d", errcode);
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void close_input(JNIEnv* e, SOCKET sock)
|
||||
{
|
||||
if (SOCKET_ERROR == ::shutdown(sock, SD_RECEIVE)) {
|
||||
int errcode = last_socket_error();
|
||||
if (errcode != ENOTCONN) {
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't shutdown the socket. System error: %d", errcode);
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void close_output(JNIEnv* e, SOCKET sock)
|
||||
{
|
||||
if (SOCKET_ERROR == ::shutdown(sock, SD_SEND)) {
|
||||
int errcode = last_socket_error();
|
||||
if (errcode != ENOTCONN) {
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't shutdown the socket. System error: %d", errcode);
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -1,74 +0,0 @@
|
||||
/* Copyright (c) 2008-2015, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
/*
|
||||
* This file represents a simple cross-platform JNI sockets API
|
||||
* It is used from different classes of the default Avian classpath
|
||||
*/
|
||||
|
||||
#ifndef SOCKETS_H_
|
||||
#define SOCKETS_H_
|
||||
|
||||
#include "jni.h"
|
||||
#include "jni-util.h"
|
||||
#include "avian/common.h"
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
#include <winsock2.h>
|
||||
|
||||
#define ONLY_ON_WINDOWS(x) x
|
||||
|
||||
#ifndef ENOTCONN
|
||||
#define ENOTCONN WSAENOTCONN
|
||||
#endif
|
||||
#else
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define ONLY_ON_WINDOWS(x)
|
||||
#define SOCKET int
|
||||
#define INVALID_SOCKET -1
|
||||
#define SOCKET_ERROR -1
|
||||
#define closesocket(x) close(x)
|
||||
|
||||
#define SD_RECEIVE SHUT_RD
|
||||
#define SD_SEND SHUT_WR
|
||||
#define SD_BOTH SHUT_RDWR
|
||||
|
||||
#endif
|
||||
|
||||
namespace avian {
|
||||
namespace classpath {
|
||||
namespace sockets {
|
||||
|
||||
// Library initialization
|
||||
void init(JNIEnv* ONLY_ON_WINDOWS(e));
|
||||
|
||||
// Socket initialization
|
||||
SOCKET create(JNIEnv* e);
|
||||
void connect(JNIEnv* e, SOCKET sock, long addr, short port);
|
||||
void bind(JNIEnv* e, SOCKET sock, long addr, short port);
|
||||
SOCKET accept(JNIEnv* e, SOCKET sock, long* client_addr, short* client_port);
|
||||
|
||||
// I/O
|
||||
void send(JNIEnv* e, SOCKET sock, const char* buff_ptr, int buff_size);
|
||||
int recv(JNIEnv* e, SOCKET sock, char* buff_ptr, int buff_size);
|
||||
|
||||
// Socket closing
|
||||
void abort(JNIEnv* e, SOCKET sock);
|
||||
void close(JNIEnv* e, SOCKET sock);
|
||||
void close_input(JNIEnv* e, SOCKET sock);
|
||||
void close_output(JNIEnv* e, SOCKET sock);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* SOCKETS_H_ */
|
14
sgx-jvm/avian/corda.pro
Normal file
14
sgx-jvm/avian/corda.pro
Normal file
@ -0,0 +1,14 @@
|
||||
# proguard include file (http://proguard.sourceforge.net)
|
||||
|
||||
# We need these for Corda deserialisation:
|
||||
-keep class sun.security.ec.ECPublicKeyImpl
|
||||
-keep class sun.security.ec.ECPrivateKeyImpl
|
||||
-keep class org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPublicKey
|
||||
-keep class org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPrivateCrtKey
|
||||
|
||||
-keep class java.lang.invoke.SerializedLambda {
|
||||
private java.lang.Object readResolve();
|
||||
}
|
||||
|
||||
-keep class com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl
|
||||
|
@ -184,6 +184,10 @@ ifneq ($(openjdk),)
|
||||
x := $(error "android and openjdk are incompatible")
|
||||
endif
|
||||
|
||||
ifeq ($(openjdk-image),)
|
||||
openjdk-image = $(openjdk)/jre
|
||||
endif
|
||||
|
||||
ifneq ($(openjdk-src),)
|
||||
include openjdk-src.mk
|
||||
options := $(options)-openjdk-src
|
||||
@ -2382,8 +2386,6 @@ $(openjdk-jar-dep):
|
||||
@mkdir -p $(classpath-build)
|
||||
(cd $(classpath-build) && \
|
||||
$(jar) xf "$$($(native-path) "$(openjdk-image)/lib/rt.jar")" && \
|
||||
$(jar) xf "$$($(native-path) "$(openjdk-image)/lib/jsse.jar")" && \
|
||||
$(jar) xf "$$($(native-path) "$(openjdk-image)/lib/jce.jar")" && \
|
||||
$(jar) xf "$$($(native-path) "$(openjdk-image)/lib/charsets.jar")" && \
|
||||
$(jar) xf "$$($(native-path) "$(openjdk-image)/lib/resources.jar")" && \
|
||||
$(jar) xf "$$($(native-path) "$(openjdk-image)/lib/ext/sunec.jar")")
|
||||
|
@ -94,7 +94,6 @@ openjdk-headers-classes = \
|
||||
sun.misc.VMSupport \
|
||||
sun.misc.Version \
|
||||
sun.misc.URLClassPath \
|
||||
sun.net.spi.DefaultProxySelector \
|
||||
sun.nio.ch.IOStatus \
|
||||
sun.reflect.ConstantPool \
|
||||
sun.reflect.NativeConstructorAccessorImpl \
|
||||
@ -214,7 +213,6 @@ else
|
||||
"-I$(openjdk-src)/solaris/native/java/lang" \
|
||||
"-I$(openjdk-src)/solaris/native/java/net" \
|
||||
"-I$(openjdk-src)/solaris/native/java/util" \
|
||||
"-I$(openjdk-src)/solaris/native/sun/management" \
|
||||
"-I$(openjdk-src)/solaris/native/sun/nio/ch" \
|
||||
"-I$(openjdk-src)/solaris/javavm/include" \
|
||||
"-I$(openjdk-src)/solaris/hpi/include" \
|
||||
|
@ -1341,6 +1341,9 @@ class Thread {
|
||||
return flags;
|
||||
}
|
||||
|
||||
bool isBlacklisting();
|
||||
void startBlacklisting();
|
||||
|
||||
JNIEnvVTable* vtable;
|
||||
Machine* m;
|
||||
Thread* parent;
|
||||
|
@ -183,6 +183,12 @@ extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
t->m->classpath->makeString(t, array, offset, length));
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT void JNICALL
|
||||
Avian_avian_SystemClassLoader_startBlacklisting0(Thread* t, object, uintptr_t*)
|
||||
{
|
||||
t->startBlacklisting();
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_avian_SystemClassLoader_appLoader(Thread* t, object, uintptr_t*)
|
||||
{
|
||||
|
@ -66,6 +66,7 @@ class MyClasspath : public Classpath {
|
||||
0,
|
||||
0,
|
||||
group,
|
||||
0,
|
||||
0);
|
||||
}
|
||||
|
||||
|
@ -3355,7 +3355,7 @@ uint64_t jvmInitProperties(Thread* t, uintptr_t* arguments)
|
||||
local::setProperty(
|
||||
t, method, *properties, "java.vm.vendor", "Avian Contributors");
|
||||
|
||||
local::setProperty(t, method, *properties, "java.vm.name", "Avian");
|
||||
local::setProperty(t, method, *properties, "java.vm.name", "Avian (Corda)");
|
||||
#ifdef AVIAN_VERSION
|
||||
local::setProperty(t, method, *properties, "java.vm.version", AVIAN_VERSION);
|
||||
#endif
|
||||
|
@ -3964,6 +3964,18 @@ void Thread::dispose()
|
||||
m->processor->dispose(this);
|
||||
}
|
||||
|
||||
bool Thread::isBlacklisting()
|
||||
{
|
||||
return (javaThread != NULL) && javaThread->blacklisting();
|
||||
}
|
||||
|
||||
void Thread::startBlacklisting()
|
||||
{
|
||||
if (javaThread != NULL) {
|
||||
javaThread->setBlacklisting(this, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void shutDown(Thread* t)
|
||||
{
|
||||
ACQUIRE(t, t->m->shutdownLock);
|
||||
@ -4884,6 +4896,40 @@ GcClass* resolveSystemClass(Thread* t,
|
||||
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
/*
|
||||
* We require that SystemClassLoader.isForbidden() has already
|
||||
* been executed once before isBlacklisting is set to true.
|
||||
* Otherwise this code-block recurses until the stack explodes.
|
||||
*/
|
||||
if (t->isBlacklisting()
|
||||
&& ::strcmp("avian/SystemClassLoader", reinterpret_cast<const char*>(spec->body().begin()))) {
|
||||
GcMethod* forbid = resolveMethod(t,
|
||||
roots(t)->bootLoader(),
|
||||
"avian/SystemClassLoader",
|
||||
"isForbidden",
|
||||
"(Ljava/lang/String;)Z");
|
||||
GcString *name = t->m->classpath->makeString(t, spec, 0, spec->length());
|
||||
GcInt *result = cast<GcInt>(t, t->m->processor->invoke(t, forbid, NULL, name));
|
||||
if (UNLIKELY(t->exception)) {
|
||||
if (throw_) {
|
||||
GcThrowable* e = t->exception;
|
||||
t->exception = 0;
|
||||
vm::throw_(t, e);
|
||||
} else {
|
||||
t->exception = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (result->value() == JNI_TRUE) {
|
||||
if (throw_) {
|
||||
throwNew(t, throwType, "%s", spec->body().begin());
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GcClass* class_ = findLoadedClass(t, loader, spec);
|
||||
if (class_ == 0) {
|
||||
PROTECT(t, class_);
|
||||
|
@ -188,6 +188,7 @@
|
||||
(require object interruptLock)
|
||||
(require uint8_t interrupted)
|
||||
(require uint8_t unparked)
|
||||
(require uint8_t blacklisting)
|
||||
(alias peer uint64_t eetop)
|
||||
(alias peer uint64_t nativePeer)
|
||||
(require uint64_t peer))
|
||||
|
@ -51,16 +51,6 @@ public class BufferedInputStreamTest
|
||||
}
|
||||
//on all following calls block. The spec says, that a least one byte is returned, if the
|
||||
//stream is not at EOF.
|
||||
while(available() == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(100);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.nio.BufferOverflowException;
|
||||
@ -9,7 +9,7 @@ public class Buffers {
|
||||
System.loadLibrary("test");
|
||||
}
|
||||
|
||||
private static void testArrays(Factory factory1, Factory factory2) throws IOException {
|
||||
private static void testArrays(Factory factory1, Factory factory2) throws UnsupportedEncodingException {
|
||||
final int size = 64;
|
||||
ByteBuffer b1 = factory1.allocate(size);
|
||||
ByteBuffer b2 = factory2.allocate(size);
|
||||
@ -118,16 +118,6 @@ public class Buffers {
|
||||
}
|
||||
};
|
||||
|
||||
Factory direct = new Factory() {
|
||||
public ByteBuffer allocate(int capacity) {
|
||||
return ByteBuffer.allocateDirect(capacity);
|
||||
}
|
||||
|
||||
public void dispose(ByteBuffer b) {
|
||||
// ignore
|
||||
}
|
||||
};
|
||||
|
||||
Factory native_ = new Factory() {
|
||||
public ByteBuffer allocate(int capacity) {
|
||||
return allocateNative(capacity);
|
||||
@ -140,22 +130,11 @@ public class Buffers {
|
||||
|
||||
testPrimativeGetAndSet(array, array);
|
||||
testArrays(array, array);
|
||||
testPrimativeGetAndSet(array, direct);
|
||||
testArrays(array, direct);
|
||||
testPrimativeGetAndSet(array, native_);
|
||||
testArrays(array, native_);
|
||||
|
||||
testPrimativeGetAndSet(direct, array);
|
||||
testArrays(direct, array);
|
||||
testPrimativeGetAndSet(direct, direct);
|
||||
testArrays(direct, direct);
|
||||
testPrimativeGetAndSet(direct, native_);
|
||||
testArrays(direct, native_);
|
||||
|
||||
testPrimativeGetAndSet(native_, array);
|
||||
testArrays(native_, array);
|
||||
testPrimativeGetAndSet(native_, direct);
|
||||
testArrays(native_, direct);
|
||||
testPrimativeGetAndSet(native_, native_);
|
||||
testArrays(native_, native_);
|
||||
|
||||
|
@ -1,54 +0,0 @@
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorCompletionService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class CompletionServiceTest {
|
||||
public static void main(String args[]) throws InterruptedException, ExecutionException {
|
||||
Executor dumbExecutor = new Executor() {
|
||||
@Override
|
||||
public void execute(Runnable task) {
|
||||
new Thread(task).start();
|
||||
}
|
||||
};
|
||||
|
||||
pollNoResultTest(dumbExecutor);
|
||||
pollTimeoutNoResultTest(dumbExecutor);
|
||||
takeTest(dumbExecutor);
|
||||
}
|
||||
|
||||
private static void verify(boolean val) {
|
||||
if (! val) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
private static void pollNoResultTest(Executor executor) {
|
||||
ExecutorCompletionService<Object> ecs = new ExecutorCompletionService<Object>(executor);
|
||||
|
||||
verify(ecs.poll() == null);
|
||||
}
|
||||
|
||||
private static void pollTimeoutNoResultTest(Executor executor) throws InterruptedException {
|
||||
long delayTime = 0;
|
||||
ExecutorCompletionService<Object> ecs = new ExecutorCompletionService<Object>(executor);
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
verify(ecs.poll(delayTime, TimeUnit.MILLISECONDS) == null);
|
||||
verify(System.currentTimeMillis() - startTime >= delayTime);
|
||||
}
|
||||
|
||||
private static void takeTest(Executor executor) throws InterruptedException, ExecutionException {
|
||||
ExecutorCompletionService<Object> ecs = new ExecutorCompletionService<Object>(executor);
|
||||
final Object result = new Object();
|
||||
ecs.submit(new Callable<Object>() {
|
||||
@Override
|
||||
public Object call() throws Exception {
|
||||
return result;
|
||||
}
|
||||
});
|
||||
|
||||
verify(ecs.take().get() == result);
|
||||
}
|
||||
}
|
@ -11,10 +11,6 @@ public class FutureTaskTest {
|
||||
public static void main(String[] args) throws InterruptedException, ExecutionException {
|
||||
isDoneTest(false);
|
||||
isDoneTest(true);
|
||||
getCallableResultTest();
|
||||
getRunnableResultTest();
|
||||
getTimeoutFail();
|
||||
getExecutionExceptionTest();
|
||||
}
|
||||
|
||||
private static void isDoneTest(final boolean throwException) {
|
||||
@ -34,72 +30,4 @@ public class FutureTaskTest {
|
||||
throw new RuntimeException("Future should be done");
|
||||
}
|
||||
}
|
||||
|
||||
private static void getCallableResultTest() throws InterruptedException, ExecutionException {
|
||||
final Object result = new Object();
|
||||
FutureTask<Object> future = new FutureTask<Object>(new Callable<Object>() {
|
||||
@Override
|
||||
public Object call() throws Exception {
|
||||
return result;
|
||||
}
|
||||
});
|
||||
|
||||
future.run();
|
||||
if (future.get() != result) {
|
||||
throw new RuntimeException("Bad result returned: " + future.get());
|
||||
}
|
||||
}
|
||||
|
||||
private static void getRunnableResultTest() throws InterruptedException, ExecutionException {
|
||||
final Object result = new Object();
|
||||
FutureTask<Object> future = new FutureTask<Object>(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// nothing here
|
||||
}
|
||||
}, result);
|
||||
|
||||
future.run();
|
||||
if (future.get() != result) {
|
||||
throw new RuntimeException("Bad result returned: " + future.get());
|
||||
}
|
||||
}
|
||||
|
||||
private static void getTimeoutFail() throws InterruptedException,
|
||||
ExecutionException {
|
||||
RunnableFuture<?> future = new FutureTask<Object>(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// wont run
|
||||
}
|
||||
}, null);
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
try {
|
||||
future.get(DELAY_TIME, TimeUnit.MILLISECONDS);
|
||||
throw new RuntimeException("Exception should have been thrown");
|
||||
} catch (TimeoutException e) {
|
||||
long catchTime = System.currentTimeMillis();
|
||||
if (catchTime - startTime < DELAY_TIME) {
|
||||
throw new RuntimeException("get with timeout did not block long enough");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void getExecutionExceptionTest() throws InterruptedException, ExecutionException {
|
||||
FutureTask<Object> future = new FutureTask<Object>(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}, null);
|
||||
|
||||
future.run();
|
||||
try {
|
||||
future.get();
|
||||
throw new RuntimeException("Exception should have thrown");
|
||||
} catch (ExecutionException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,208 +0,0 @@
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class LinkedBlockingQueueTest {
|
||||
private static final int DELAY_TILL_ACTION = 10;
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
remainingCapacityTest();
|
||||
QueueHelper.sizeTest(new LinkedBlockingQueue<Object>());
|
||||
QueueHelper.isEmptyTest(new LinkedBlockingQueue<Object>());
|
||||
QueueHelper.addTest(new LinkedBlockingQueue<Object>());
|
||||
addCapacityFail();
|
||||
offerTest();
|
||||
offerWithTimeoutTest();
|
||||
offerTimeoutTest();
|
||||
putTest();
|
||||
QueueHelper.addAllTest(new LinkedBlockingQueue<Object>());
|
||||
addAllFail();
|
||||
QueueHelper.elementTest(new LinkedBlockingQueue<Object>());
|
||||
QueueHelper.elementFail(new LinkedBlockingQueue<Object>());
|
||||
pollEmptyTest();
|
||||
pollTest();
|
||||
pollTimeoutTest();
|
||||
takeTest();
|
||||
QueueHelper.removeEmptyFail(new LinkedBlockingQueue<Object>());
|
||||
QueueHelper.removeTest(new LinkedBlockingQueue<Object>());
|
||||
drainToTest();
|
||||
drainToLimitTest();
|
||||
QueueHelper.containsTest(new LinkedBlockingQueue<Object>());
|
||||
QueueHelper.containsAllTest(new LinkedBlockingQueue<Object>());
|
||||
QueueHelper.removeObjectTest(new LinkedBlockingQueue<Object>());
|
||||
QueueHelper.removeAllTest(new LinkedBlockingQueue<Object>());
|
||||
QueueHelper.clearTest(new LinkedBlockingQueue<Object>());
|
||||
QueueHelper.toArrayTest(new LinkedBlockingQueue<Object>());
|
||||
}
|
||||
|
||||
private static void verify(boolean val) {
|
||||
if (! val) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
private static void remainingCapacityTest() {
|
||||
LinkedBlockingQueue<Object> lbq = new LinkedBlockingQueue<Object>(2);
|
||||
verify(lbq.remainingCapacity() == 2);
|
||||
|
||||
lbq.add(new Object());
|
||||
verify(lbq.remainingCapacity() == 1);
|
||||
}
|
||||
|
||||
private static void addCapacityFail() {
|
||||
LinkedBlockingQueue<Object> lbq = new LinkedBlockingQueue<Object>(1);
|
||||
Object testObject = new Object();
|
||||
lbq.add(testObject);
|
||||
|
||||
try {
|
||||
lbq.add(new Object());
|
||||
throw new RuntimeException("Exception should have thrown");
|
||||
} catch (IllegalStateException e) {
|
||||
// expected
|
||||
}
|
||||
|
||||
verify(lbq.size() == 1);
|
||||
verify(lbq.peek() == testObject);
|
||||
}
|
||||
|
||||
private static void offerTest() {
|
||||
LinkedBlockingQueue<Object> lbq = new LinkedBlockingQueue<Object>(1);
|
||||
Object testObject = new Object();
|
||||
verify(lbq.offer(testObject));
|
||||
verify(! lbq.offer(new Object()));
|
||||
|
||||
verify(lbq.size() == 1);
|
||||
verify(lbq.peek() == testObject);
|
||||
}
|
||||
|
||||
private static void offerWithTimeoutTest() throws InterruptedException {
|
||||
final LinkedBlockingQueue<Object> lbq = new LinkedBlockingQueue<Object>(1);
|
||||
lbq.add(new Object());
|
||||
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
// sleep to make sure offer call starts first
|
||||
Thread.sleep(DELAY_TILL_ACTION);
|
||||
lbq.take();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
|
||||
// should accept once thread starts
|
||||
verify(lbq.offer(new Object(), 10, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
private static void offerTimeoutTest() throws InterruptedException {
|
||||
LinkedBlockingQueue<Object> lbq = new LinkedBlockingQueue<Object>(1);
|
||||
lbq.add(new Object());
|
||||
|
||||
verify(! lbq.offer(new Object(), 10, TimeUnit.MILLISECONDS));
|
||||
}
|
||||
|
||||
private static void putTest() throws InterruptedException {
|
||||
LinkedBlockingQueue<Object> lbq = new LinkedBlockingQueue<Object>();
|
||||
Object testObject = new Object();
|
||||
lbq.put(testObject);
|
||||
|
||||
verify(lbq.size() == 1);
|
||||
verify(lbq.peek() == testObject);
|
||||
}
|
||||
|
||||
private static void addAllFail() {
|
||||
LinkedBlockingQueue<Object> lbq = new LinkedBlockingQueue<Object>(1);
|
||||
LinkedList<Object> toAdd = new LinkedList<Object>();
|
||||
toAdd.add(new Object());
|
||||
toAdd.add(new Object());
|
||||
|
||||
try {
|
||||
lbq.addAll(toAdd);
|
||||
throw new RuntimeException("Exception should have thrown");
|
||||
} catch (IllegalStateException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
private static void pollEmptyTest() {
|
||||
LinkedBlockingQueue<Object> lbq = new LinkedBlockingQueue<Object>();
|
||||
|
||||
verify(lbq.poll() == null);
|
||||
}
|
||||
|
||||
private static void pollTest() {
|
||||
LinkedBlockingQueue<Object> lbq = new LinkedBlockingQueue<Object>();
|
||||
Object testObject = new Object();
|
||||
lbq.add(testObject);
|
||||
|
||||
verify(lbq.poll() == testObject);
|
||||
}
|
||||
|
||||
private static void pollTimeoutTest() throws InterruptedException {
|
||||
final LinkedBlockingQueue<Object> lbq = new LinkedBlockingQueue<Object>();
|
||||
final Object testObject = new Object();
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(DELAY_TILL_ACTION);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
lbq.add(testObject);
|
||||
}
|
||||
}).start();
|
||||
|
||||
|
||||
verify(lbq.poll(DELAY_TILL_ACTION * 10, TimeUnit.MILLISECONDS) == testObject);
|
||||
}
|
||||
|
||||
private static void takeTest() throws InterruptedException {
|
||||
final LinkedBlockingQueue<Object> lbq = new LinkedBlockingQueue<Object>();
|
||||
final Object testObject = new Object();
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(DELAY_TILL_ACTION);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
lbq.add(testObject);
|
||||
}
|
||||
}).start();
|
||||
|
||||
|
||||
verify(lbq.take() == testObject);
|
||||
}
|
||||
|
||||
private static void drainToTest() {
|
||||
int objQty = 2;
|
||||
LinkedBlockingQueue<Object> lbq = new LinkedBlockingQueue<Object>();
|
||||
for (int i = 0; i < objQty; i++) {
|
||||
lbq.add(new Object());
|
||||
}
|
||||
|
||||
LinkedList<Object> drainToResult = new LinkedList<Object>();
|
||||
verify(lbq.drainTo(drainToResult) == objQty);
|
||||
verify(drainToResult.size() == objQty);
|
||||
}
|
||||
|
||||
private static void drainToLimitTest() {
|
||||
int objQty = 4;
|
||||
int limit = 2;
|
||||
LinkedBlockingQueue<Object> lbq = new LinkedBlockingQueue<Object>();
|
||||
for (int i = 0; i < objQty; i++) {
|
||||
lbq.add(new Object());
|
||||
}
|
||||
|
||||
LinkedList<Object> drainToResult = new LinkedList<Object>();
|
||||
verify(lbq.drainTo(drainToResult, limit) == limit);
|
||||
verify(drainToResult.size() == limit);
|
||||
verify(lbq.size() == objQty - limit);
|
||||
}
|
||||
}
|
@ -29,7 +29,6 @@ public class MemoryRamp implements Runnable {
|
||||
* @return time to create and access array in milliseconds
|
||||
*/
|
||||
private static long mem() {
|
||||
long start = System.currentTimeMillis();
|
||||
final byte[] array = new byte[ARRAY_SIZE];
|
||||
if (ACCESS_ARRAY) {
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
@ -37,7 +36,7 @@ public class MemoryRamp implements Runnable {
|
||||
byte x = array[i]; //read
|
||||
}
|
||||
}
|
||||
return System.currentTimeMillis() - start;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -46,7 +45,6 @@ public class MemoryRamp implements Runnable {
|
||||
*/
|
||||
private static long memMulti(int numOfThreads) {
|
||||
Thread[] threads = new Thread[numOfThreads];
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
threads[i] = new Thread(new MemoryRamp(), "mem-");
|
||||
@ -61,6 +59,6 @@ public class MemoryRamp implements Runnable {
|
||||
catch (InterruptedException iex) {
|
||||
throw new RuntimeException(iex);
|
||||
}
|
||||
return System.currentTimeMillis() - start;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -254,8 +254,6 @@ public class Misc {
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println(new java.util.Date().toString());
|
||||
|
||||
System.out.println('x');
|
||||
System.out.println(true);
|
||||
System.out.println(42);
|
||||
|
@ -1,73 +0,0 @@
|
||||
package extra;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.io.OutputStream;
|
||||
import java.io.FileInputStream;
|
||||
|
||||
public class SendFile {
|
||||
private static class SocketOutputStream extends OutputStream {
|
||||
private final SocketChannel channel;
|
||||
private final Selector selector;
|
||||
public SocketOutputStream(String host, int port) throws Exception {
|
||||
channel = SocketChannel.open();
|
||||
channel.connect(new InetSocketAddress(host, port));
|
||||
channel.configureBlocking(false);
|
||||
selector = Selector.open();
|
||||
channel.register(selector, SelectionKey.OP_WRITE, null);
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
channel.close();
|
||||
}
|
||||
|
||||
public void write(int c) {
|
||||
throw new RuntimeException("Do not use!");
|
||||
}
|
||||
public void write(byte[] buffer, int offset, int length)
|
||||
throws IOException {
|
||||
ByteBuffer buf = ByteBuffer.wrap(buffer);
|
||||
buf.position(offset);
|
||||
buf.limit(offset+length);
|
||||
while (buf.hasRemaining()) {
|
||||
selector.select(10000);
|
||||
for (SelectionKey key : selector.selectedKeys()) {
|
||||
if (key.isWritable() && (key.channel() == channel)) {
|
||||
channel.write(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendFile(String file, String host, int port)
|
||||
throws Exception {
|
||||
System.out.println("Sending " + file);
|
||||
OutputStream os = new SocketOutputStream(host, port);
|
||||
FileInputStream is = new FileInputStream(file);
|
||||
byte[] buf = new byte[16384];
|
||||
int count=-1;
|
||||
while ((count = is.read(buf)) >= 0) {
|
||||
os.write(buf, 0, count);
|
||||
}
|
||||
is.close();
|
||||
os.close();
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
if (args.length != 2) {
|
||||
System.out.println("Usage: SendFile file host");
|
||||
} else {
|
||||
try {
|
||||
sendFile(args[0], args[1], 8988);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,92 +0,0 @@
|
||||
package extra;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
public class SendServer {
|
||||
private static char cIndex = 'A';
|
||||
private static ByteBuffer inBuf = ByteBuffer.allocate(8192);
|
||||
|
||||
private static void dumpByteBuffer(char note, ByteBuffer buf) {
|
||||
System.out.println(note + ": Buffer position: " + buf.position() + " limit: " +
|
||||
buf.limit() + " capacity: " + buf.capacity() + " remaining: " +
|
||||
buf.remaining());
|
||||
}
|
||||
|
||||
private static class Connection {
|
||||
private final char myIndex;
|
||||
private final java.io.FileOutputStream fos;
|
||||
|
||||
public Connection() throws Exception {
|
||||
myIndex = cIndex++;
|
||||
fos = new java.io.FileOutputStream("dump." + myIndex);
|
||||
}
|
||||
|
||||
public void handleRead(SocketChannel channel) throws Exception {
|
||||
int count = -1;
|
||||
while ((count = channel.read(inBuf)) > 0) {
|
||||
System.out.println(myIndex + ": read " + count);
|
||||
}
|
||||
inBuf.flip();
|
||||
fos.write(inBuf.array(), inBuf.arrayOffset()+inBuf.position(), inBuf.remaining());
|
||||
inBuf.position(inBuf.limit());
|
||||
if (count < 0) {
|
||||
System.out.println(myIndex + ": Closing channel");
|
||||
fos.close();
|
||||
channel.close();
|
||||
}
|
||||
// dumpByteBuffer(myIndex, inBuf);
|
||||
inBuf.compact();
|
||||
}
|
||||
}
|
||||
|
||||
public void runMainLoop() throws Exception {
|
||||
boolean keepRunning = true;
|
||||
int port = 8988;
|
||||
ServerSocketChannel serverChannel = ServerSocketChannel.open();
|
||||
try {
|
||||
serverChannel.configureBlocking(false);
|
||||
serverChannel.socket().bind(new InetSocketAddress("0.0.0.0", port));
|
||||
Selector selector = Selector.open();
|
||||
serverChannel.register(selector, SelectionKey.OP_ACCEPT, null);
|
||||
while (keepRunning) {
|
||||
System.out.println("Running main loop");
|
||||
selector.select(10000);
|
||||
for (SelectionKey key : selector.selectedKeys()) {
|
||||
if (key.isAcceptable()) {
|
||||
System.out.println("Accepting new connection");
|
||||
SocketChannel c = ((ServerSocketChannel) key.channel()).accept();
|
||||
if (c != null) {
|
||||
c.configureBlocking(false);
|
||||
c.register(selector, SelectionKey.OP_READ, new Connection());
|
||||
}
|
||||
} else {
|
||||
SocketChannel c = (SocketChannel) key.channel();
|
||||
if (c.isOpen() && key.isReadable()) {
|
||||
Connection connection = (Connection)key.attachment();
|
||||
connection.handleRead(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
selector.selectedKeys().clear();
|
||||
}
|
||||
} finally {
|
||||
serverChannel.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
try {
|
||||
System.out.println("Starting server");
|
||||
if (args.length > 0) {
|
||||
new SendServer().runMainLoop();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
package extra;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
public class Sockets {
|
||||
|
||||
/**
|
||||
* @param args
|
||||
* @throws IOException
|
||||
* @throws UnknownHostException
|
||||
*/
|
||||
public static void main(String[] args) throws UnknownHostException,
|
||||
IOException {
|
||||
System.out.print("Requesting... " + args[0] + "\n");
|
||||
Socket sock = new Socket(args[0], 80);
|
||||
try {
|
||||
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
|
||||
String request = "GET /?gws_rd=cr HTTP/1.1\r\n"
|
||||
+ "Host: " + args[0] + "\r\n" + "Accept: */*\r\n"
|
||||
+ "User-Agent: Java\r\n" + "Connection: close\r\n" + "\r\n";
|
||||
bw.write(request);
|
||||
bw.flush();
|
||||
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream()));
|
||||
String read = null;
|
||||
while ((read = br.readLine()) != null) {
|
||||
System.out.println(read);
|
||||
}
|
||||
bw.close();
|
||||
} finally {
|
||||
sock.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -23,6 +23,7 @@ set(ENCLAVE_SIGNED_OUTPUT_LIB cordaenclave.signed.so)
|
||||
set(SGX_SIGN_TOOL ${SGX_SDK}/build/linux/sgx_sign)
|
||||
set(PROGUARD_JAR_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../dependencies/root/usr/share/java/proguard.jar)
|
||||
set(AVIAN_PATH ${PROJECT_SOURCE_DIR}/../../avian)
|
||||
set(JDK_IMAGE ${PROJECT_SOURCE_DIR}/../../jdk8u/build/linux-x86_64-normal-server-release/images/j2re-image)
|
||||
set(ENCLAVE_JAR_PATH ${PROJECT_SOURCE_DIR}/../../../verify-enclave/build/libs/corda-enclavelet.jar)
|
||||
set(AVIAN_PROCESS "-debug-openjdk-src")
|
||||
|
||||
@ -55,8 +56,8 @@ set(PRIVATE_KEY_NAME ${CMAKE_CURRENT_SOURCE_DIR}/selfsigning.pem)
|
||||
|
||||
# Now add the compiled class files to our copy of the boot jar (as we need a single uni-jar for everything).
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/encjars/classpath.jar ${CMAKE_CURRENT_BINARY_DIR}/encjars/app.jar ${CMAKE_CURRENT_BINARY_DIR}/encjars/corda-enclavelet.jar ${CMAKE_CURRENT_BINARY_DIR}/encjars/jce.jar ${CMAKE_CURRENT_BINARY_DIR}/encjars/jsse.jar ${CMAKE_CURRENT_BINARY_DIR}/encjars/sunjce_provider.jar
|
||||
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/create-boot-jar.sh ${AVIAN_PATH}/build/linux-x86_64${AVIAN_PROCESS} ${ENCLAVE_JAR_PATH} ${CMAKE_CURRENT_BINARY_DIR}/encjars ${PROGUARD_JAR_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/proguard.pro ${JAVA_HOME}
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/encjars/classpath.jar ${CMAKE_CURRENT_BINARY_DIR}/encjars/app.jar ${CMAKE_CURRENT_BINARY_DIR}/encjars/corda-enclavelet.jar ${CMAKE_CURRENT_BINARY_DIR}/encjars/jce.jar ${CMAKE_CURRENT_BINARY_DIR}/encjars/jsse.jar
|
||||
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/create-boot-jar.sh ${AVIAN_PATH}/build/linux-x86_64${AVIAN_PROCESS} ${ENCLAVE_JAR_PATH} ${CMAKE_CURRENT_BINARY_DIR}/encjars ${PROGUARD_JAR_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/proguard.pro ${JDK_IMAGE}
|
||||
DEPENDS ${ENCLAVE_JAR_PATH}
|
||||
)
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
# 3) path to the output dir
|
||||
# 4) path to proguard jar
|
||||
# 5) path to proguard conf
|
||||
# 6) path to openjdk install
|
||||
# 6) path to openjdk image
|
||||
|
||||
if [ ! -d "$1" ]; then echo "$1 is not a directory"; exit 1; fi
|
||||
if [ ! -e "$2" ]; then echo "$2 does not exist"; exit 1; fi
|
||||
@ -21,7 +21,7 @@ appjar=$( readlink -f $2 )
|
||||
outputjardir=$( readlink -f $3 )
|
||||
proguard_jar=$( readlink -f $4 )
|
||||
proguard_conf=$( readlink -f $5 )
|
||||
openjdk_libs=$6/jre/lib
|
||||
openjdk_libs=$6/lib
|
||||
|
||||
mkdir -p $outputjardir
|
||||
if [ ! -e $openjdk_libs/jsse.jar ]; then
|
||||
@ -29,7 +29,7 @@ if [ ! -e $openjdk_libs/jsse.jar ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cmd="java -jar $proguard_jar @$avianpath/../../vm.pro @$avianpath/../../openjdk.pro @$proguard_conf -injars $bootjar -injars $appjar -injars $openjdk_libs/jsse.jar -injars $openjdk_libs/jce.jar -injars $openjdk_libs/ext/sunjce_provider.jar -outjars $outputjardir"
|
||||
cmd="java -jar $proguard_jar @$avianpath/../../vm.pro @$avianpath/../../openjdk.pro @$avianpath/../../corda.pro @$proguard_conf -injars $bootjar -injars $appjar -injars $openjdk_libs/jsse.jar -injars $openjdk_libs/jce.jar -outjars $outputjardir"
|
||||
# echo $cmd
|
||||
$cmd
|
||||
|
||||
@ -37,9 +37,12 @@ mkdir -p $outputjardir/temp
|
||||
cd $outputjardir/temp
|
||||
jar xf ../jce.jar
|
||||
jar xf ../jsse.jar
|
||||
jar xf ../sunjce_provider.jar
|
||||
jar xf $openjdk_libs/charsets.jar
|
||||
jar xf $2
|
||||
rm -f META-INF/*.DSA
|
||||
rm -f META-INF/*.RSA
|
||||
rm -f META-INF/*.SF
|
||||
rm -f META-INF/*.MF
|
||||
jar cf ../app.jar *
|
||||
cd ..
|
||||
rm -r temp
|
||||
|
@ -35,8 +35,8 @@ void check_transaction(void *reqbuf, size_t buflen, char *error) {
|
||||
vmArgs.version = JNI_VERSION_1_2;
|
||||
vmArgs.ignoreUnrecognized = JNI_TRUE;
|
||||
|
||||
char xmxOption[256];
|
||||
snprintf(xmxOption, 256, "-Xmx%d", g_global_data.heap_size);
|
||||
char xmxOption[32];
|
||||
snprintf(xmxOption, sizeof(xmxOption), "-Xmx%d", g_global_data.heap_size);
|
||||
JavaVMOption options[] = {
|
||||
// Tell Avian to call the functions above to find the embedded jar data.
|
||||
// We separate the app into boot and app jars because some code does not
|
||||
@ -49,9 +49,8 @@ void check_transaction(void *reqbuf, size_t buflen, char *error) {
|
||||
vmArgs.nOptions = sizeof(options) / sizeof(JavaVMOption);
|
||||
|
||||
JavaVM* vm = NULL;
|
||||
void* env_void = NULL;
|
||||
JNI_CreateJavaVM(&vm, &env_void, &vmArgs);
|
||||
JNIEnv* env = static_cast<JNIEnv*>(env_void);
|
||||
JNIEnv* env = NULL;
|
||||
JNI_CreateJavaVM(&vm, reinterpret_cast<void**>(&env), &vmArgs);
|
||||
|
||||
env->FindClass("com/r3/enclaves/txverify/EnclaveletSerializationScheme");
|
||||
if (!env->ExceptionCheck()) {
|
||||
@ -60,7 +59,7 @@ void check_transaction(void *reqbuf, size_t buflen, char *error) {
|
||||
jmethodID m = env->GetStaticMethodID(c, "verifyInEnclave", "([B)V");
|
||||
if (!env->ExceptionCheck()) {
|
||||
jbyteArray reqbits = env->NewByteArray((jsize) buflen);
|
||||
env->SetByteArrayRegion(reqbits, 0, buflen, (const jbyte *)reqbuf);
|
||||
env->SetByteArrayRegion(reqbits, 0, buflen, static_cast<const jbyte*>(reqbuf));
|
||||
jobject result = env->CallStaticObjectMethod(c, m, reqbits);
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
<ProdID>0</ProdID>
|
||||
<ISVSVN>0</ISVSVN>
|
||||
<StackMaxSize>0x280000</StackMaxSize>
|
||||
<HeapMaxSize>0x5500000</HeapMaxSize>
|
||||
<HeapMaxSize>0x8000000</HeapMaxSize>
|
||||
<HeapExecutable>1</HeapExecutable>
|
||||
<TCSNum>10</TCSNum>
|
||||
<TCSPolicy>1</TCSPolicy>
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
extern "C" {
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_com_r3_enclaves_txverify_NativeSgxApi_verify(JNIEnv *env, jobject, jstring enclave_path, jbyteArray transaction) {
|
||||
JNIEXPORT jstring JNICALL Java_com_r3_enclaves_txverify_NativeSgxApi_verify(JNIEnv *env, jclass, jstring enclave_path, jbyteArray transaction) {
|
||||
sgx_launch_token_t token = {0};
|
||||
sgx_enclave_id_t enclave_id = {0};
|
||||
int updated = 0;
|
||||
@ -26,4 +26,4 @@ JNIEXPORT jstring JNICALL Java_com_r3_enclaves_txverify_NativeSgxApi_verify(JNIE
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -365,7 +365,7 @@ int CLoader::build_secs(sgx_attributes_t * const secs_attr, sgx_misc_attribute_t
|
||||
int ret = enclave_creator->create_enclave(&m_secs, &m_enclave_id, &m_start_addr, is_ae(&m_metadata->enclave_css));
|
||||
if(SGX_SUCCESS == ret)
|
||||
{
|
||||
SE_TRACE(SE_TRACE_NOTICE, "enclave start address = %p, size = %x\n", m_start_addr, m_metadata->enclave_size);
|
||||
SE_TRACE(SE_TRACE_NOTICE, "enclave start address = %p, size = 0x%x\n", m_start_addr, m_metadata->enclave_size);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -67,11 +67,16 @@ jar {
|
||||
task integrationTest(type: Test) {
|
||||
testClassesDirs = sourceSets.integrationTest.output.classesDirs
|
||||
classpath = sourceSets.integrationTest.runtimeClasspath
|
||||
jvmArgs '-Djava.library.path=../sgx-jvm/jvm-enclave/jni/build'
|
||||
systemProperties['java.library.path'] = '../sgx-jvm/jvm-enclave/jni/build'
|
||||
}
|
||||
|
||||
test {
|
||||
// Pending Gradle bug: https://github.com/gradle/gradle/issues/2657
|
||||
//systemProperties['java.system.class.loader'] = 'com.r3.enclaves.DummySystemClassLoader'
|
||||
}
|
||||
|
||||
task generateNativeSgxHeaders(type: Exec) {
|
||||
def classpath = sourceSets.main.output.classesDirs.asPath
|
||||
commandLine "javah", "-o", "build/native/include/jni_sgx_api.h", "-cp", classpath, "com.r3.enclaves.txverify.NativeSgxApi"
|
||||
commandLine "javah", "-o", "$buildDir/native/include/jni_sgx_api.h", "-cp", classpath, "com.r3.enclaves.txverify.NativeSgxApi"
|
||||
dependsOn classes
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import net.corda.core.contracts.Attachment
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.serialization.SerializedBytes
|
||||
import net.corda.core.serialization.deserialize
|
||||
import net.corda.core.transactions.LedgerTransaction
|
||||
import net.corda.core.transactions.WireTransaction
|
||||
import java.io.File
|
||||
|
||||
@ -14,9 +15,22 @@ import java.io.File
|
||||
|
||||
/** This is just used to simplify marshalling across the enclave boundary (EDL is a bit awkward) */
|
||||
@CordaSerializable
|
||||
class TransactionVerificationRequest(val wtxToVerify: SerializedBytes<WireTransaction>,
|
||||
val dependencies: Array<SerializedBytes<WireTransaction>>,
|
||||
val attachments: Array<ByteArray>)
|
||||
class TransactionVerificationRequest(private val wtxToVerify: SerializedBytes<WireTransaction>,
|
||||
private val dependencies: Array<SerializedBytes<WireTransaction>>,
|
||||
val attachments: Array<ByteArray>) {
|
||||
fun toLedgerTransaction(): LedgerTransaction {
|
||||
val deps = dependencies.map { it.deserialize() }.associateBy(WireTransaction::id)
|
||||
val attachments = attachments.map { it.deserialize<Attachment>() }
|
||||
val attachmentMap = attachments.associateBy(Attachment::id)
|
||||
val contractAttachmentMap = attachments.mapNotNull { it as? MockContractAttachment }.associateBy(MockContractAttachment::contract)
|
||||
return wtxToVerify.deserialize().toLedgerTransaction(
|
||||
resolveIdentity = { null },
|
||||
resolveAttachment = { attachmentMap[it] },
|
||||
resolveStateRef = { deps[it.txhash]?.outputs?.get(it.index) },
|
||||
resolveContractAttachment = { contractAttachmentMap[it.contract]?.id }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns either null to indicate success when the transactions are validated, or a string with the
|
||||
@ -30,21 +44,26 @@ class TransactionVerificationRequest(val wtxToVerify: SerializedBytes<WireTransa
|
||||
*/
|
||||
@Throws(Exception::class)
|
||||
fun verifyInEnclave(reqBytes: ByteArray) {
|
||||
val req = reqBytes.deserialize<TransactionVerificationRequest>()
|
||||
val wtxToVerify = req.wtxToVerify.deserialize()
|
||||
val dependencies = req.dependencies.map { it.deserialize() }.associateBy { it.id }
|
||||
val attachments = req.attachments.map { it.deserialize<Attachment>() }
|
||||
val attachmentMap = attachments.associateBy(Attachment::id)
|
||||
val contractAttachmentMap = attachments.mapNotNull { it as? MockContractAttachment }.associateBy { it.contract }
|
||||
val ltx = wtxToVerify.toLedgerTransaction(
|
||||
resolveIdentity = { null },
|
||||
resolveAttachment = { attachmentMap[it] },
|
||||
resolveStateRef = { dependencies[it.txhash]?.outputs?.get(it.index) },
|
||||
resolveContractAttachment = { contractAttachmentMap[it.contract]?.id }
|
||||
)
|
||||
val ltx = deserialise(reqBytes)
|
||||
// Prevent this thread from linking new classes against any
|
||||
// blacklisted classes, e.g. ones needed by Kryo or by the
|
||||
// JVM itself. Note that java.lang.Thread is also blacklisted.
|
||||
startClassBlacklisting()
|
||||
ltx.verify()
|
||||
}
|
||||
|
||||
private fun startClassBlacklisting() {
|
||||
val systemClassLoader = ClassLoader.getSystemClassLoader()
|
||||
systemClassLoader.javaClass.getMethod("startBlacklisting").apply {
|
||||
invoke(systemClassLoader)
|
||||
}
|
||||
}
|
||||
|
||||
private fun deserialise(reqBytes: ByteArray): LedgerTransaction {
|
||||
return reqBytes.deserialize<TransactionVerificationRequest>()
|
||||
.toLedgerTransaction()
|
||||
}
|
||||
|
||||
// Note: This is only here for debugging purposes
|
||||
fun main(args: Array<String>) {
|
||||
Log.TRACE()
|
||||
|
@ -5,6 +5,7 @@ import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.core.serialization.internal.SerializationEnvironmentImpl
|
||||
import net.corda.core.serialization.internal.nodeSerializationEnv
|
||||
import net.corda.core.utilities.ByteSequence
|
||||
import net.corda.core.utilities.toHexString
|
||||
import net.corda.nodeapi.internal.serialization.*
|
||||
import net.corda.nodeapi.internal.serialization.amqp.AbstractAMQPSerializationScheme
|
||||
import net.corda.nodeapi.internal.serialization.amqp.AmqpHeaderV1_0
|
||||
@ -29,6 +30,11 @@ private class EnclaveletSerializationScheme {
|
||||
* incoming request received.
|
||||
*/
|
||||
KRYO_P2P_CONTEXT)
|
||||
|
||||
/*
|
||||
* Ensure that we initialise JAXP before blacklisting is enabled.
|
||||
*/
|
||||
ByteArray(0).toHexString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,5 +6,6 @@ object NativeSgxApi {
|
||||
System.loadLibrary("untrusted_corda_sgx")
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
external fun verify(enclavePath: String, transactionBytes: ByteArray): String?
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,6 @@
|
||||
package com.r3.enclaves
|
||||
|
||||
@Suppress("unused")
|
||||
class DummySystemClassLoader(parent: ClassLoader) : ClassLoader(parent) {
|
||||
fun startBlacklisting() {}
|
||||
}
|
@ -7,6 +7,7 @@ import net.corda.finance.`issued by`
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.finance.contracts.asset.DUMMY_CASH_ISSUER
|
||||
import net.corda.testing.*
|
||||
import org.junit.Ignore
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import java.nio.file.Files
|
||||
@ -18,6 +19,8 @@ class EnclaveletTest {
|
||||
@Rule
|
||||
@JvmField
|
||||
val testSerialization = SerializationEnvironmentRule()
|
||||
|
||||
@Ignore("Pending Gradle bug: https://github.com/gradle/gradle/issues/2657")
|
||||
@Test
|
||||
fun success() {
|
||||
ledger {
|
||||
@ -50,6 +53,7 @@ class EnclaveletTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Ignore("Pending Gradle bug: https://github.com/gradle/gradle/issues/2657")
|
||||
@Test
|
||||
fun fail() {
|
||||
ledger {
|
||||
|
Loading…
Reference in New Issue
Block a user