mirror of
https://github.com/corda/corda.git
synced 2024-12-28 00:38:55 +00:00
Add 'sgx-jvm/avian/' from commit '09e4fe60d01f4f4bfb6b2976973bb4913ef61edc'
git-subtree-dir: sgx-jvm/avian git-subtree-mainline:f978eab8d1
git-subtree-split:09e4fe60d0
This commit is contained in:
commit
9bb3d6b972
7
sgx-jvm/avian/.clang-format
Normal file
7
sgx-jvm/avian/.clang-format
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
BasedOnStyle: Chromium
|
||||||
|
IndentCaseLabels: false
|
||||||
|
BreakBeforeBraces: Stroustrup
|
||||||
|
AllowShortFunctionsOnASingleLine: false
|
||||||
|
BreakBeforeBinaryOperators: true
|
||||||
|
...
|
17
sgx-jvm/avian/.gitignore
vendored
Normal file
17
sgx-jvm/avian/.gitignore
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
.gdb_history
|
||||||
|
/build
|
||||||
|
*~
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
bin
|
||||||
|
/lib
|
||||||
|
/distrib
|
||||||
|
*.pdb
|
||||||
|
*.swp
|
||||||
|
/.gradle
|
||||||
|
/*.sublime-*
|
||||||
|
workspace/
|
||||||
|
src/.cproject
|
||||||
|
/cmake-build
|
||||||
|
/cmake-build
|
27
sgx-jvm/avian/.mailmap
Normal file
27
sgx-jvm/avian/.mailmap
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Carsten Elton Sørensen <ces@HADDOCK.premitech.net>
|
||||||
|
Carsten Elton Sørensen <csoren@gmail.com>
|
||||||
|
Dain Darnell <dain.darnell@readytalk.com>
|
||||||
|
Dain Darnell <dain@dazar.(none)>
|
||||||
|
Edison Guo <hydra1983@gmail.com>
|
||||||
|
Jason Treadwell <derBierBrauer@yahoo.com>
|
||||||
|
Jason Treadwell <jason.treadwell@readytalk.com>
|
||||||
|
Jason Treadwell <jet@debian-armel.(none)>
|
||||||
|
Jason Treadwell <jet@jet-lappy.(none)>
|
||||||
|
Jason Treadwell <jet@jet.ecovate.com>
|
||||||
|
Jason Treadwell <jet@jet.readytalk.com>
|
||||||
|
Jason Treadwell <jet@jetl.readytalk.com>
|
||||||
|
Jason Treadwell <jet@jetp.(none)>
|
||||||
|
Jason Treadwell <jet@nonames-power-mac-g4-agp-graphics.local>
|
||||||
|
Joel Dice <Joel Dice@joeldicexpvm.(none)>
|
||||||
|
Joel Dice <Joel@JDICEVM7.(none)>
|
||||||
|
Joel Dice <dicej@bstevenstestnb.readytalk.com>
|
||||||
|
Joel Dice <dicej@osxdesktop-2.local>
|
||||||
|
Anonymous <anonymous@example.com>
|
||||||
|
Joshua Warner <jwarner@radio.ecovate.com>
|
||||||
|
Matt Weaver <mweaver@gorgotron.readytalk.com>
|
||||||
|
Mike Jensen <jentfoo@gmail.com>
|
||||||
|
Mike Jensen <mjensen@jentbox.ecovate.com>
|
||||||
|
Mike Jensen <mjensen@lennyjent.ecovate.com>
|
||||||
|
Terek Campbell <terek.campbell@colorado.edu>
|
||||||
|
Thiago Bedin Frustaci <frustaci@gmail.com>
|
||||||
|
Zsombor Gegesy <gzsombor@gmail.com>
|
25
sgx-jvm/avian/.travis.yml
Normal file
25
sgx-jvm/avian/.travis.yml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
language: cpp
|
||||||
|
cache: apt
|
||||||
|
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
- osx
|
||||||
|
|
||||||
|
env:
|
||||||
|
matrix:
|
||||||
|
- BUILD_STEP=""
|
||||||
|
# disabled until/unless jfrog.org credentials are updated and someone
|
||||||
|
# decides they care about published artifacts:
|
||||||
|
# - BUILD_STEP="PUBLISH"
|
||||||
|
global:
|
||||||
|
- TERM=dumb
|
||||||
|
- secure: rh1utD4shKmYtokItuRYEF9WsfTnvZO5XqnTU4DHTS7quHHgLihtOO2/3+B+2W2hEd5Obr2or8zx+zmzWcNUyLokZ0j/FRLWSScNkLzTtm12pupLrncY+/g1NIdfbhn+OLRIzBz6zB6m6a2qWFEJ+bScUNGD/7wZVtzkujqlDEE=
|
||||||
|
- secure: j9DOzZMCYk/BzhKK9u4XMKpCzyGOsvP2cLTp6cXE7/tkWDAPVv6BFmeqNbiLTEqk0aGX+HYbY/2YVtpRZmDzfeWtnBFF5mL1Y1tgzx1Kf155C+P6rZgt5PiQTUdXlp2umuRifY1BbXAPc3DZ2UOPUjWKnLHVbZLQRgO1zimmMx8=
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
fast_finish: true
|
||||||
|
exclude:
|
||||||
|
- os: osx
|
||||||
|
env: BUILD_STEP=""
|
||||||
|
|
||||||
|
script: ./test/ci.sh ${BUILD_STEP}
|
31
sgx-jvm/avian/.utility/push-javadoc-to-gh-pages.sh
Executable file
31
sgx-jvm/avian/.utility/push-javadoc-to-gh-pages.sh
Executable file
@ -0,0 +1,31 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# This script was originally written by maxiaohao in the aws-mock GitHub project.
|
||||||
|
# https://github.com/treelogic-swe/aws-mock/
|
||||||
|
|
||||||
|
if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
|
||||||
|
|
||||||
|
echo "Start to publish lastest Javadoc to gh-pages..."
|
||||||
|
|
||||||
|
cd build/
|
||||||
|
|
||||||
|
if test -d gh-pages/avian-web
|
||||||
|
then
|
||||||
|
cd gh-pages/avian-web
|
||||||
|
git pull
|
||||||
|
else
|
||||||
|
git clone --quiet https://${GH_TOKEN}@github.com/ReadyTalk/readytalk.github.io gh-pages > /dev/null
|
||||||
|
cd gh-pages/avian-web
|
||||||
|
git config user.email "travis@travis-ci.org"
|
||||||
|
git config user.name "travis-ci"
|
||||||
|
fi
|
||||||
|
|
||||||
|
git rm -rf ./javadoc
|
||||||
|
cp -Rf ../javadoc ./javadoc
|
||||||
|
git add -f .
|
||||||
|
git commit -m "Latest javadoc on successful Travis build $TRAVIS_BUILD_NUMBER auto-pushed to readytalk.github.io"
|
||||||
|
if ! git push -fq origin master &> /dev/null; then
|
||||||
|
echo "Error pushing gh-pages to origin. Bad GH_TOKEN? GitHub down?"
|
||||||
|
else
|
||||||
|
echo "Done magic with auto publishment to readytalk.github.io."
|
||||||
|
fi
|
||||||
|
fi
|
29
sgx-jvm/avian/CMakeLists.txt
Normal file
29
sgx-jvm/avian/CMakeLists.txt
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# NOTE that this CMake file doesn't current build all of avian.
|
||||||
|
# It only builds what's required for example/kaleidoscope.
|
||||||
|
|
||||||
|
cmake_minimum_required (VERSION 2.6)
|
||||||
|
project (avian)
|
||||||
|
|
||||||
|
include_directories (include src)
|
||||||
|
|
||||||
|
add_definitions (
|
||||||
|
-DAVIAN_TARGET_FORMAT=AVIAN_FORMAT_MACHO
|
||||||
|
|
||||||
|
-DAVIAN_TARGET_ARCH=AVIAN_ARCH_X86_64
|
||||||
|
|
||||||
|
-DTARGET_BYTES_PER_WORD=8
|
||||||
|
-D__STDC_LIMIT_MACROS
|
||||||
|
-D__STDC_CONSTANT_MACROS
|
||||||
|
)
|
||||||
|
|
||||||
|
include ("cmake/Platform.cmake")
|
||||||
|
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PLATFORM_CXX_FLAGS}")
|
||||||
|
|
||||||
|
include (CTest)
|
||||||
|
|
||||||
|
# Sadly, we can't use the 'test' target, as that's coopted by ctest
|
||||||
|
add_custom_target(check ${CMAKE_CTEST_COMMAND} -V)
|
||||||
|
|
||||||
|
add_subdirectory (src)
|
||||||
|
add_subdirectory (unittest)
|
15
sgx-jvm/avian/LICENSE.txt
Normal file
15
sgx-jvm/avian/LICENSE.txt
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
ISC License
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
750
sgx-jvm/avian/README.md
Normal file
750
sgx-jvm/avian/README.md
Normal file
@ -0,0 +1,750 @@
|
|||||||
|
Avian - A lightweight Java Virtual Machine (JVM)
|
||||||
|
================================================
|
||||||
|
|
||||||
|
[![Build Status](https://travis-ci.org/ReadyTalk/avian.png?branch=master)](https://travis-ci.org/ReadyTalk/avian)
|
||||||
|
|
||||||
|
Quick Start
|
||||||
|
-----------
|
||||||
|
|
||||||
|
These are examples of building Avian on various operating systems for
|
||||||
|
the x86_64 architecture. You may need to modify JAVA_HOME according
|
||||||
|
to where the JDK is installed on your system. In all cases, be sure
|
||||||
|
to use forward slashes in the path.
|
||||||
|
|
||||||
|
#### on Linux:
|
||||||
|
$ export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
|
||||||
|
$ make
|
||||||
|
$ build/linux-x86_64/avian -cp build/linux-x86_64/test Hello
|
||||||
|
|
||||||
|
#### on Mac OS X:
|
||||||
|
$ export JAVA_HOME=$(/usr/libexec/java_home)
|
||||||
|
$ make
|
||||||
|
$ build/macosx-x86_64/avian -cp build/macosx-x86_64/test Hello
|
||||||
|
|
||||||
|
#### on Windows (Cygwin):
|
||||||
|
$ git clone git@github.com:ReadyTalk/win64.git ../win64
|
||||||
|
$ export JAVA_HOME="/cygdrive/c/Program Files/Java/jdk1.7.0_45"
|
||||||
|
$ make
|
||||||
|
$ build/windows-x86_64/avian -cp build/windows-x86_64/test Hello
|
||||||
|
|
||||||
|
#### on FreeBSD:
|
||||||
|
$ export JAVA_HOME=/usr/local/openjdk7
|
||||||
|
$ gmake
|
||||||
|
$ build/freebsd-x86_64/avian -cp build/freebsd-x86_64/test Hello
|
||||||
|
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
Avian is a lightweight virtual machine and class library designed to
|
||||||
|
provide a useful subset of Java's features, suitable for building
|
||||||
|
self-contained applications. More information is available at the
|
||||||
|
project [web site](http://readytalk.github.io/avian).
|
||||||
|
|
||||||
|
If you have any trouble building, running, or embedding Avian, please
|
||||||
|
post a message to our [discussion group](http://groups.google.com/group/avian).
|
||||||
|
|
||||||
|
That's also the place for any other questions, comments, or
|
||||||
|
suggestions you might have.
|
||||||
|
|
||||||
|
|
||||||
|
Supported Platforms
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Avian can currently target the following platforms:
|
||||||
|
|
||||||
|
* Linux (i386, x86_64, ARM, and ARM64)
|
||||||
|
* Windows (i386 and x86_64)
|
||||||
|
* Mac OS X (i386 and x86_64)
|
||||||
|
* Apple iOS (i386, x86_64, ARM, and ARM64)
|
||||||
|
* FreeBSD (i386, x86_64)
|
||||||
|
|
||||||
|
|
||||||
|
Building
|
||||||
|
--------
|
||||||
|
|
||||||
|
Build requirements include:
|
||||||
|
|
||||||
|
* GNU make 3.80 or later
|
||||||
|
* GCC 4.6 or later
|
||||||
|
or LLVM Clang 3.1 or later (see use-clang option below)
|
||||||
|
* JDK 1.6 or later
|
||||||
|
* MinGW 3.4 or later (only if compiling for Windows)
|
||||||
|
* zlib 1.2.3 or later
|
||||||
|
|
||||||
|
Earlier versions of some of these packages may also work but have not
|
||||||
|
been tested.
|
||||||
|
|
||||||
|
The build is directed by a single makefile and may be influenced via
|
||||||
|
certain flags described below, all of which are optional.
|
||||||
|
|
||||||
|
$ make \
|
||||||
|
platform={linux,windows,macosx,ios,freebsd} \
|
||||||
|
arch={i386,x86_64,arm,arm64} \
|
||||||
|
process={compile,interpret} \
|
||||||
|
mode={debug,debug-fast,fast,small} \
|
||||||
|
lzma=<lzma source directory> \
|
||||||
|
bootimage={true,false} \
|
||||||
|
tails={true,false} \
|
||||||
|
continuations={true,false} \
|
||||||
|
use-clang={true,false} \
|
||||||
|
openjdk=<openjdk installation directory> \
|
||||||
|
openjdk-src=<openjdk source directory> \
|
||||||
|
android=<android source directory>
|
||||||
|
|
||||||
|
* `platform` - the target platform
|
||||||
|
* _default:_ output of $(uname -s | tr [:upper:] [:lower:]),
|
||||||
|
normalized in some cases (e.g. CYGWIN_NT-5.1 -> windows)
|
||||||
|
|
||||||
|
* `arch` - the target architecture
|
||||||
|
* _default:_ output of $(uname -m), normalized in some cases
|
||||||
|
(e.g. i686 -> i386)
|
||||||
|
|
||||||
|
* `process` - choice between pure interpreter or JIT compiler
|
||||||
|
* _default:_ compile
|
||||||
|
|
||||||
|
* `mode` - which set of compilation flags to use to determine
|
||||||
|
optimization level, debug symbols, and whether to enable
|
||||||
|
assertions
|
||||||
|
* _default:_ fast
|
||||||
|
|
||||||
|
* `lzma` - if set, support use of LZMA to compress embedded JARs and
|
||||||
|
boot images. The value of this option should be a directory
|
||||||
|
containing a recent LZMA SDK (available [here](http://www.7-zip.org/sdk.html)). Currently, only version 9.20 of
|
||||||
|
the SDK has been tested, but other versions might work.
|
||||||
|
* _default:_ not set
|
||||||
|
|
||||||
|
* `armv6` - if true, don't use any instructions newer than armv6. By
|
||||||
|
default, we assume the target is armv7 or later, and thus requires explicit
|
||||||
|
memory barrier instructions to ensure cache coherency
|
||||||
|
|
||||||
|
* `bootimage` - if true, create a boot image containing the pre-parsed
|
||||||
|
class library and ahead-of-time compiled methods. This option is
|
||||||
|
only valid for process=compile builds. Note that you may need to
|
||||||
|
specify both build-arch=x86_64 and arch=x86_64 on 64-bit systems
|
||||||
|
where "uname -m" prints "i386".
|
||||||
|
* _default:_ false
|
||||||
|
|
||||||
|
* `tails` - if true, optimize each tail call by replacing the caller's
|
||||||
|
stack frame with the callee's. This convention ensures proper
|
||||||
|
tail recursion, suitable for languages such as Scheme. This
|
||||||
|
option is only valid for process=compile builds.
|
||||||
|
* _default:_ false
|
||||||
|
|
||||||
|
* `continuations` - if true, support continuations via the
|
||||||
|
avian.Continuations methods callWithCurrentContinuation and
|
||||||
|
dynamicWind. See Continuations.java for details. This option is
|
||||||
|
only valid for process=compile builds.
|
||||||
|
* _default:_ false
|
||||||
|
|
||||||
|
* `use-clang` - if true, use LLVM's clang instead of GCC to build.
|
||||||
|
Note that this does not currently affect cross compiles, only
|
||||||
|
native builds.
|
||||||
|
* _default:_ false
|
||||||
|
|
||||||
|
* `openjdk` - if set, use the OpenJDK class library instead of the
|
||||||
|
default Avian class library. See "Building with the OpenJDK Class
|
||||||
|
Library" below for details.
|
||||||
|
* _default:_ not set
|
||||||
|
|
||||||
|
* `openjdk-src` - if this and the openjdk option above are both set,
|
||||||
|
build an embeddable VM using the OpenJDK class library. The JNI
|
||||||
|
components of the OpenJDK class library will be built from the
|
||||||
|
sources found under the specified directory. See "Building with
|
||||||
|
the OpenJDK Class Library" below for details.
|
||||||
|
* _default:_ not set
|
||||||
|
|
||||||
|
* `android` - if set, use the Android class library instead of the
|
||||||
|
default Avian class library. See "Building with the Android Class
|
||||||
|
Library" below for details.
|
||||||
|
* _default:_ not set
|
||||||
|
|
||||||
|
These flags determine the name of the directory used for the build.
|
||||||
|
The name always starts with _${platform}-${arch}_, and each non-default
|
||||||
|
build option is appended to the name. For example, a debug build with
|
||||||
|
bootimage enabled on Linux/x86_64 would be built in
|
||||||
|
_build/linux-x86_64-debug-bootimage_. This allows you to build with
|
||||||
|
several different sets of options independently and even
|
||||||
|
simultaneously without doing a clean build each time.
|
||||||
|
|
||||||
|
Note that not all combinations of these flags are valid. For instance,
|
||||||
|
non-jailbroken iOS devices do not allow JIT compilation, so only
|
||||||
|
process=interpret or bootimage=true builds will run on such
|
||||||
|
devices. See [here](https://github.com/ReadyTalk/hello-ios) for an
|
||||||
|
example of an Xcode project for iOS which uses Avian.
|
||||||
|
|
||||||
|
If you are compiling for Windows, you may either cross-compile using
|
||||||
|
MinGW or build natively on Windows under Cygwin.
|
||||||
|
|
||||||
|
#### Installing Cygwin:
|
||||||
|
|
||||||
|
__1.__ Download and run setup.exe from [cygwin's website](http://www.cygwin.com), installing the base
|
||||||
|
system and these packages: make, gcc-mingw-g++,
|
||||||
|
mingw64-i686-gcc-g++, mingw64-x86_64-gcc-g++, and (optionally) git.
|
||||||
|
|
||||||
|
You may also find our win32 repository useful: (run this from the
|
||||||
|
directory containing the avian directory)
|
||||||
|
|
||||||
|
$ git clone git@github.com:ReadyTalk/win32.git
|
||||||
|
|
||||||
|
This gives you the Windows JNI headers, zlib headers and library, and
|
||||||
|
a few other useful libraries like OpenSSL, libjpeg, and libpng.
|
||||||
|
There's also a win64 repository for 64-bit builds:
|
||||||
|
|
||||||
|
$ git clone git@github.com:ReadyTalk/win64.git
|
||||||
|
|
||||||
|
|
||||||
|
Building with the Microsoft Visual C++ Compiler
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
You can also build using the MSVC compiler, which makes debugging with
|
||||||
|
tools like WinDbg and Visual Studio much easier. Note that you will
|
||||||
|
still need to have GCC installed - MSVC is only used to compile the
|
||||||
|
C++ portions of the VM, while the assembly code and helper tools are
|
||||||
|
built using GCC.
|
||||||
|
|
||||||
|
*Note that the MSVC build isn't tested regularly, so is fairly likely to be broken.*
|
||||||
|
|
||||||
|
Avian targets MSVC 11 and above (it uses c++ features not available in older versions).
|
||||||
|
|
||||||
|
To build with MSVC, install Cygwin as described above and set the
|
||||||
|
following environment variables:
|
||||||
|
|
||||||
|
$ export PATH="/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/cygdrive/c/Program Files/Microsoft Visual Studio 11.0/Common7/IDE:/cygdrive/c/Program Files/Microsoft Visual Studio 11.0/VC/BIN:/cygdrive/c/Program Files/Microsoft Visual Studio 11.0/Common7/Tools:/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v3.5:/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v2.0.50727:/cygdrive/c/Program Files/Microsoft Visual Studio 11.0/VC/VCPackages:/cygdrive/c/Program Files/Microsoft SDKs/Windows/v6.0A/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem"
|
||||||
|
$ export LIBPATH="C:\WINDOWS\Microsoft.NET\Framework\v3.5;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;C:\Program Files\Microsoft Visual Studio 11.0\VC\LIB;"
|
||||||
|
$ export VCINSTALLDIR="C:\Program Files\Microsoft Visual Studio 11.0\VC"
|
||||||
|
$ export LIB="C:\Program Files\Microsoft Visual Studio 11.0\VC\LIB;C:\Program Files\Microsoft SDKs\Windows\v6.0A\lib;"
|
||||||
|
$ export INCLUDE="C:\Program Files\Microsoft Visual Studio 11.0\VC\INCLUDE;C:\Program Files\Microsoft SDKs\Windows\v6.0A\include;"
|
||||||
|
|
||||||
|
Adjust these definitions as necessary according to your MSVC
|
||||||
|
installation.
|
||||||
|
|
||||||
|
Finally, build with the msvc flag set to the MSVC tool directory:
|
||||||
|
|
||||||
|
$ make msvc="/cygdrive/c/Program Files/Microsoft Visual Studio 11.0/VC"
|
||||||
|
|
||||||
|
|
||||||
|
Building with the OpenJDK Class Library
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
By default, Avian uses its own lightweight class library. However,
|
||||||
|
that library only contains a relatively small subset of the classes
|
||||||
|
and methods included in the JRE. If your application requires
|
||||||
|
features beyond that subset, you may want to tell Avian to use
|
||||||
|
OpenJDK's class library instead. To do so, specify the directory
|
||||||
|
where OpenJDK is installed, e.g.:
|
||||||
|
|
||||||
|
$ make openjdk=/usr/lib/jvm/java-7-openjdk
|
||||||
|
|
||||||
|
This will build Avian as a conventional JVM (e.g. libjvm.so) which
|
||||||
|
loads its boot class library and native libraries (e.g. libjava.so)
|
||||||
|
from _/usr/lib/jvm/java-7-openjdk/jre_ at runtime. Note that you must
|
||||||
|
use an absolute path here, or else the result will not work when run
|
||||||
|
from other directories. In this configuration, OpenJDK needs to
|
||||||
|
remain installed for Avian to work, and you can run applications like
|
||||||
|
this:
|
||||||
|
|
||||||
|
$ build/linux-x86_64-openjdk/avian-dynamic -cp /path/to/my/application \
|
||||||
|
com.example.MyApplication
|
||||||
|
|
||||||
|
Alternatively, you can enable a stand-alone build using OpenJDK by
|
||||||
|
specifying the location of the OpenJDK source code, e.g.:
|
||||||
|
|
||||||
|
$ make openjdk=$(pwd)/../jdk7/build/linux-amd64/j2sdk-image \
|
||||||
|
openjdk-src=$(pwd)/../jdk7/jdk/src
|
||||||
|
|
||||||
|
You must ensure that the path specified for openjdk-src does not have
|
||||||
|
any spaces in it; make gets confused when dependency paths include
|
||||||
|
spaces, and we haven't found away around that except to avoid paths
|
||||||
|
with spaces entirely.
|
||||||
|
|
||||||
|
The result of such a build is a self-contained binary which does not
|
||||||
|
depend on external libraries, jars, or other files. In this case, the
|
||||||
|
specified paths are used only at build time; anything needed at
|
||||||
|
runtime is embedded in the binary. Thus, the process of running an
|
||||||
|
application is simplified:
|
||||||
|
|
||||||
|
$ build/linux-x86_64-openjdk-src/avian -cp /path/to/my/application \
|
||||||
|
com.example.MyApplication
|
||||||
|
|
||||||
|
Note that the resulting binary will be very large due to the size of
|
||||||
|
OpenJDK's class library. This can be mitigated using UPX, preferably
|
||||||
|
an LZMA-enabled version:
|
||||||
|
|
||||||
|
$ upx --lzma --best build/linux-x86_64-openjdk-src/avian
|
||||||
|
|
||||||
|
You can reduce the size futher for embedded builds by using ProGuard
|
||||||
|
and the supplied openjdk.pro configuration file (see "Embedding with
|
||||||
|
ProGuard and a Boot Image" below). Note that you'll still need to use
|
||||||
|
vm.pro in that case -- openjdk.pro just adds additional constraints
|
||||||
|
specific to the OpenJDK port. Also see
|
||||||
|
[app.mk](https://github.com/ReadyTalk/avian-swt-examples/blob/master/app.mk)
|
||||||
|
in the _avian-swt-examples_ project for an example of using Avian,
|
||||||
|
OpenJDK, ProGuard, and UPX in concert.
|
||||||
|
|
||||||
|
Here are some examples of how to install OpenJDK and build Avian with
|
||||||
|
it on various OSes:
|
||||||
|
|
||||||
|
#### Debian-based Linux:
|
||||||
|
_Conventional build:_
|
||||||
|
|
||||||
|
$ apt-get install openjdk-7-jdk
|
||||||
|
$ make openjdk=/usr/lib/jvm/java-7-openjdk test
|
||||||
|
|
||||||
|
_Stand-alone build:_
|
||||||
|
|
||||||
|
$ apt-get install openjdk-7-jdk
|
||||||
|
$ apt-get source openjdk-7-jdk
|
||||||
|
$ apt-get build-dep openjdk-7-jdk
|
||||||
|
$ (cd openjdk-7-7~b147-2.0 && dpkg-buildpackage)
|
||||||
|
$ make openjdk=/usr/lib/jvm/java-7-openjdk \
|
||||||
|
openjdk-src=$(pwd)/openjdk-7-7~b147-2.0/build/openjdk/jdk/src \
|
||||||
|
test
|
||||||
|
|
||||||
|
####Mac OS X:
|
||||||
|
_Prerequisite:_ Build OpenJDK 7 according to [this site](https://wikis.oracle.com/display/OpenJDK/Mac+OS+X+Port).
|
||||||
|
|
||||||
|
_Conventional build:_
|
||||||
|
|
||||||
|
$ make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image test
|
||||||
|
|
||||||
|
_Stand-alone build:_
|
||||||
|
|
||||||
|
$ make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image \
|
||||||
|
openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test
|
||||||
|
|
||||||
|
####Windows (Cygwin):
|
||||||
|
_Prerequisite:_ Build OpenJDK 7 according to [this site](http://weblogs.java.net/blog/simonis/archive/2011/10/28/yaojowbi-yet-another-openjdk-windows-build-instruction). Alternatively, use https://github.com/alexkasko/openjdk-unofficial-builds.
|
||||||
|
|
||||||
|
_Conventional build:_
|
||||||
|
|
||||||
|
$ make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image test
|
||||||
|
|
||||||
|
_Stand-alone build:_
|
||||||
|
|
||||||
|
$ make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image \
|
||||||
|
openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test
|
||||||
|
|
||||||
|
Currently, only OpenJDK 7 is supported. Later versions might work,
|
||||||
|
but have not yet been tested.
|
||||||
|
|
||||||
|
|
||||||
|
Building with the Android Class Library
|
||||||
|
---------------------------------------
|
||||||
|
As an alternative to both the Avian and OpenJDK class libaries, you
|
||||||
|
can also build with the Android class library. Now it should work on Linux, OS X and Windows.
|
||||||
|
|
||||||
|
The simpliest way to build Avian with Android classpath is to use `avian-pack` project: https://github.com/bigfatbrowncat/avian-pack
|
||||||
|
|
||||||
|
Avian-pack consists of Avian itself with some Android components (such as libcore and icu4c).
|
||||||
|
|
||||||
|
Note that we use the upstream OpenSSL repository and apply the
|
||||||
|
Android patches to it. This is because it is not clear how to build
|
||||||
|
the Android fork of OpenSSL directly without checking out and building
|
||||||
|
the entire platform. As of this writing, the patches apply cleanly
|
||||||
|
against OpenSSL 1.0.1h, so that's the tag we check out, but this may
|
||||||
|
change in the future when the Android fork rebases against a new
|
||||||
|
OpenSSL version.
|
||||||
|
|
||||||
|
Installing
|
||||||
|
----------
|
||||||
|
|
||||||
|
Installing Avian is as simple as copying the executable to the desired
|
||||||
|
directory:
|
||||||
|
|
||||||
|
$ cp build/${platform}-${arch}/avian ~/bin/
|
||||||
|
|
||||||
|
|
||||||
|
Embedding
|
||||||
|
---------
|
||||||
|
|
||||||
|
The following series of commands illustrates how to produce a
|
||||||
|
stand-alone executable out of a Java application using Avian.
|
||||||
|
|
||||||
|
Note: if you are building on Cygwin, prepend "x86_64-w64-mingw32-" or
|
||||||
|
"i686-w64-mingw32-" to the ar, g++, gcc, strip, and dlltool commands
|
||||||
|
below (e.g. x86_64-w64-mingw32-gcc).
|
||||||
|
|
||||||
|
__1.__ Build Avian, create a new directory, and populate it with the
|
||||||
|
VM object files and bootstrap classpath jar.
|
||||||
|
|
||||||
|
$ make
|
||||||
|
$ mkdir hello
|
||||||
|
$ cd hello
|
||||||
|
$ ar x ../build/${platform}-${arch}/libavian.a
|
||||||
|
$ cp ../build/${platform}-${arch}/classpath.jar boot.jar
|
||||||
|
|
||||||
|
__2.__ Build the Java code and add it to the jar.
|
||||||
|
|
||||||
|
$ cat >Hello.java <<EOF
|
||||||
|
public class Hello {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println("hello, world!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
$ javac -bootclasspath boot.jar Hello.java
|
||||||
|
$ jar u0f boot.jar Hello.class
|
||||||
|
|
||||||
|
__3.__ Make an object file out of the jar.
|
||||||
|
|
||||||
|
$ ../build/${platform}-${arch}/binaryToObject/binaryToObject boot.jar \
|
||||||
|
boot-jar.o _binary_boot_jar_start _binary_boot_jar_end ${platform} ${arch}
|
||||||
|
|
||||||
|
If you've built Avian using the `lzma` option, you may optionally
|
||||||
|
compress the jar before generating the object:
|
||||||
|
|
||||||
|
../build/$(platform}-${arch}-lzma/lzma/lzma encode boot.jar boot.jar.lzma
|
||||||
|
&& ../build/${platform}-${arch}-lzma/binaryToObject/binaryToObject \
|
||||||
|
boot.jar.lzma boot-jar.o _binary_boot_jar_start _binary_boot_jar_end \
|
||||||
|
${platform} ${arch}
|
||||||
|
|
||||||
|
Note that you'll need to specify "-Xbootclasspath:[lzma.bootJar]"
|
||||||
|
instead of "-Xbootclasspath:[bootJar]" in the next step if you've used
|
||||||
|
LZMA to compress the jar.
|
||||||
|
|
||||||
|
__4.__ Write a driver which starts the VM and runs the desired main
|
||||||
|
method. Note the bootJar function, which will be called by the VM to
|
||||||
|
get a handle to the embedded jar. We tell the VM about this jar by
|
||||||
|
setting the boot classpath to "[bootJar]".
|
||||||
|
|
||||||
|
$ cat >embedded-jar-main.cpp <<EOF
|
||||||
|
#include "stdint.h"
|
||||||
|
#include "jni.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
|
||||||
|
#if (defined __MINGW32__) || (defined _MSC_VER)
|
||||||
|
# define EXPORT __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
# define EXPORT __attribute__ ((visibility("default"))) \
|
||||||
|
__attribute__ ((used))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
|
||||||
|
# define SYMBOL(x) binary_boot_jar_##x
|
||||||
|
#else
|
||||||
|
# define SYMBOL(x) _binary_boot_jar_##x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
extern const uint8_t SYMBOL(start)[];
|
||||||
|
extern const uint8_t SYMBOL(end)[];
|
||||||
|
|
||||||
|
EXPORT const uint8_t*
|
||||||
|
bootJar(size_t* size)
|
||||||
|
{
|
||||||
|
*size = SYMBOL(end) - SYMBOL(start);
|
||||||
|
return SYMBOL(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
|
extern "C" void __cxa_pure_virtual(void) { abort(); }
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int ac, const char** av)
|
||||||
|
{
|
||||||
|
JavaVMInitArgs vmArgs;
|
||||||
|
vmArgs.version = JNI_VERSION_1_2;
|
||||||
|
vmArgs.nOptions = 1;
|
||||||
|
vmArgs.ignoreUnrecognized = JNI_TRUE;
|
||||||
|
|
||||||
|
JavaVMOption options[vmArgs.nOptions];
|
||||||
|
vmArgs.options = options;
|
||||||
|
|
||||||
|
options[0].optionString = const_cast<char*>("-Xbootclasspath:[bootJar]");
|
||||||
|
|
||||||
|
JavaVM* vm;
|
||||||
|
void* env;
|
||||||
|
JNI_CreateJavaVM(&vm, &env, &vmArgs);
|
||||||
|
JNIEnv* e = static_cast<JNIEnv*>(env);
|
||||||
|
|
||||||
|
jclass c = e->FindClass("Hello");
|
||||||
|
if (not e->ExceptionCheck()) {
|
||||||
|
jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V");
|
||||||
|
if (not e->ExceptionCheck()) {
|
||||||
|
jclass stringClass = e->FindClass("java/lang/String");
|
||||||
|
if (not e->ExceptionCheck()) {
|
||||||
|
jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0);
|
||||||
|
if (not e->ExceptionCheck()) {
|
||||||
|
for (int i = 1; i < ac; ++i) {
|
||||||
|
e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
e->CallStaticVoidMethod(c, m, a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int exitCode = 0;
|
||||||
|
if (e->ExceptionCheck()) {
|
||||||
|
exitCode = -1;
|
||||||
|
e->ExceptionDescribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
vm->DestroyJavaVM();
|
||||||
|
|
||||||
|
return exitCode;
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
__on Linux:__
|
||||||
|
|
||||||
|
$ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \
|
||||||
|
-D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o
|
||||||
|
|
||||||
|
__on Mac OS X:__
|
||||||
|
|
||||||
|
$ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/darwin \
|
||||||
|
-D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o
|
||||||
|
|
||||||
|
__on Windows:__
|
||||||
|
|
||||||
|
$ g++ -fno-exceptions -fno-rtti -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/win32" \
|
||||||
|
-D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o
|
||||||
|
|
||||||
|
__5.__ Link the objects produced above to produce the final
|
||||||
|
executable, and optionally strip its symbols.
|
||||||
|
|
||||||
|
__on Linux:__
|
||||||
|
|
||||||
|
$ g++ -rdynamic *.o -ldl -lpthread -lz -o hello
|
||||||
|
$ strip --strip-all hello
|
||||||
|
|
||||||
|
__on Mac OS X:__
|
||||||
|
|
||||||
|
$ g++ -rdynamic *.o -ldl -lpthread -lz -o hello -framework CoreFoundation
|
||||||
|
$ strip -S -x hello
|
||||||
|
|
||||||
|
__on Windows:__
|
||||||
|
|
||||||
|
$ dlltool -z hello.def *.o
|
||||||
|
$ dlltool -d hello.def -e hello.exp
|
||||||
|
$ gcc hello.exp *.o -L../../win32/lib -lmingwthrd -lm -lz -lws2_32 \
|
||||||
|
-lIphlpapi -mwindows -mconsole -o hello.exe
|
||||||
|
$ strip --strip-all hello.exe
|
||||||
|
|
||||||
|
Embedding with ProGuard and a Boot Image
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
The following illustrates how to embed an application as above, except
|
||||||
|
this time we preprocess the code using ProGuard and build a boot image
|
||||||
|
from it for quicker startup. The pros and cons of using ProGuard are
|
||||||
|
as follow:
|
||||||
|
|
||||||
|
* Pros: ProGuard will eliminate unused code, optimize the rest, and
|
||||||
|
obfuscate it as well for maximum space savings
|
||||||
|
|
||||||
|
* Cons: increased build time, especially for large applications, and
|
||||||
|
extra effort needed to configure it for applications which rely
|
||||||
|
heavily on reflection and/or calls to Java from native code
|
||||||
|
|
||||||
|
For boot image builds:
|
||||||
|
|
||||||
|
* Pros: the boot image build pre-parses all the classes and compiles
|
||||||
|
all the methods, obviating the need for JIT compilation at runtime.
|
||||||
|
This also makes garbage collection faster, since the pre-parsed
|
||||||
|
classes are never visited.
|
||||||
|
|
||||||
|
* Cons: the pre-parsed classes and AOT-compiled methods take up more
|
||||||
|
space in the executable than the equivalent class files. In
|
||||||
|
practice, this can make the executable 30-50% larger. Also, AOT
|
||||||
|
compilation does not yet yield significantly faster or smaller code
|
||||||
|
than JIT compilation. Finally, floating point code may be slower
|
||||||
|
on 32-bit x86 since the compiler cannot assume SSE2 support will be
|
||||||
|
available at runtime, and the x87 FPU is not supported except via
|
||||||
|
out-of-line helper functions.
|
||||||
|
|
||||||
|
Note you can use ProGuard without using a boot image and vice-versa,
|
||||||
|
as desired.
|
||||||
|
|
||||||
|
The following instructions assume we are building for Linux/x86_64.
|
||||||
|
Please refer to the previous example for guidance on other platforms.
|
||||||
|
|
||||||
|
__1.__ Build Avian, create a new directory, and populate it with the
|
||||||
|
VM object files.
|
||||||
|
|
||||||
|
$ make bootimage=true
|
||||||
|
$ mkdir hello
|
||||||
|
$ cd hello
|
||||||
|
$ ar x ../build/linux-x86_64-bootimage/libavian.a
|
||||||
|
|
||||||
|
__2.__ Create a stage1 directory and extract the contents of the
|
||||||
|
class library jar into it.
|
||||||
|
|
||||||
|
$ mkdir stage1
|
||||||
|
$ (cd stage1 && jar xf ../../build/linux-x86_64-bootimage/classpath.jar)
|
||||||
|
|
||||||
|
__3.__ Build the Java code and add it to stage1.
|
||||||
|
|
||||||
|
$ cat >Hello.java <<EOF
|
||||||
|
public class Hello {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println("hello, world!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
$ javac -bootclasspath stage1 -d stage1 Hello.java
|
||||||
|
|
||||||
|
__4.__ Create a ProGuard configuration file specifying Hello.main as
|
||||||
|
the entry point.
|
||||||
|
|
||||||
|
$ cat >hello.pro <<EOF
|
||||||
|
-keep class Hello {
|
||||||
|
public static void main(java.lang.String[]);
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
__5.__ Run ProGuard with stage1 as input and stage2 as output.
|
||||||
|
|
||||||
|
$ java -jar ../../proguard4.6/lib/proguard.jar \
|
||||||
|
-dontusemixedcaseclassnames -injars stage1 -outjars stage2 \
|
||||||
|
@../vm.pro @hello.pro
|
||||||
|
|
||||||
|
(note: The -dontusemixedcaseclassnames option is only needed when
|
||||||
|
building on systems with case-insensitive filesystems such as Windows
|
||||||
|
and OS X. Also, you'll need to add -ignorewarnings if you use the
|
||||||
|
OpenJDK class library since the openjdk-src build does not include all
|
||||||
|
the JARs from OpenJDK, and thus ProGuard will not be able to resolve
|
||||||
|
all referenced classes. If you actually plan to use such classes at
|
||||||
|
runtime, you'll need to add them to stage1 before running ProGuard.
|
||||||
|
Finally, you'll need to add @../openjdk.pro to the above command when
|
||||||
|
using the OpenJDK library.)
|
||||||
|
|
||||||
|
__6.__ Build the boot and code images.
|
||||||
|
|
||||||
|
$ ../build/linux-x86_64-bootimage/bootimage-generator \
|
||||||
|
-cp stage2 \
|
||||||
|
-bootimage bootimage-bin.o \
|
||||||
|
-codeimage codeimage-bin.o \
|
||||||
|
-hostvm ../build/linux-x86_64-interpret/libjvm.so
|
||||||
|
|
||||||
|
Note that you can override the default names for the start and end
|
||||||
|
symbols in the boot/code image by also passing:
|
||||||
|
|
||||||
|
-bootimage-symbols my_bootimage_start:my_bootimage_end \
|
||||||
|
-codeimage-symbols my_codeimage_start:my_codeimage_end
|
||||||
|
|
||||||
|
__7.__ Write a driver which starts the VM and runs the desired main
|
||||||
|
method. Note the bootimageBin function, which will be called by the
|
||||||
|
VM to get a handle to the embedded boot image. We tell the VM about
|
||||||
|
this function via the "avian.bootimage" property.
|
||||||
|
|
||||||
|
Note also that this example includes no resources besides class files.
|
||||||
|
If our application loaded resources such as images and properties
|
||||||
|
files via the classloader, we would also need to embed the jar file
|
||||||
|
containing them. See the previous example for instructions.
|
||||||
|
|
||||||
|
$ cat >bootimage-main.cpp <<EOF
|
||||||
|
#include "stdint.h"
|
||||||
|
#include "jni.h"
|
||||||
|
|
||||||
|
#if (defined __MINGW32__) || (defined _MSC_VER)
|
||||||
|
# define EXPORT __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
# define EXPORT __attribute__ ((visibility("default")))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
|
||||||
|
# define BOOTIMAGE_BIN(x) binary_bootimage_bin_##x
|
||||||
|
# define CODEIMAGE_BIN(x) binary_codeimage_bin_##x
|
||||||
|
#else
|
||||||
|
# define BOOTIMAGE_BIN(x) _binary_bootimage_bin_##x
|
||||||
|
# define CODEIMAGE_BIN(x) _binary_codeimage_bin_##x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
extern const uint8_t BOOTIMAGE_BIN(start)[];
|
||||||
|
extern const uint8_t BOOTIMAGE_BIN(end)[];
|
||||||
|
|
||||||
|
EXPORT const uint8_t*
|
||||||
|
bootimageBin(size_t* size)
|
||||||
|
{
|
||||||
|
*size = BOOTIMAGE_BIN(end) - BOOTIMAGE_BIN(start);
|
||||||
|
return BOOTIMAGE_BIN(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern const uint8_t CODEIMAGE_BIN(start)[];
|
||||||
|
extern const uint8_t CODEIMAGE_BIN(end)[];
|
||||||
|
|
||||||
|
EXPORT const uint8_t*
|
||||||
|
codeimageBin(size_t* size)
|
||||||
|
{
|
||||||
|
*size = CODEIMAGE_BIN(end) - CODEIMAGE_BIN(start);
|
||||||
|
return CODEIMAGE_BIN(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int ac, const char** av)
|
||||||
|
{
|
||||||
|
JavaVMInitArgs vmArgs;
|
||||||
|
vmArgs.version = JNI_VERSION_1_2;
|
||||||
|
vmArgs.nOptions = 2;
|
||||||
|
vmArgs.ignoreUnrecognized = JNI_TRUE;
|
||||||
|
|
||||||
|
JavaVMOption options[vmArgs.nOptions];
|
||||||
|
vmArgs.options = options;
|
||||||
|
|
||||||
|
options[0].optionString
|
||||||
|
= const_cast<char*>("-Davian.bootimage=bootimageBin");
|
||||||
|
|
||||||
|
options[1].optionString
|
||||||
|
= const_cast<char*>("-Davian.codeimage=codeimageBin");
|
||||||
|
|
||||||
|
JavaVM* vm;
|
||||||
|
void* env;
|
||||||
|
JNI_CreateJavaVM(&vm, &env, &vmArgs);
|
||||||
|
JNIEnv* e = static_cast<JNIEnv*>(env);
|
||||||
|
|
||||||
|
jclass c = e->FindClass("Hello");
|
||||||
|
if (not e->ExceptionCheck()) {
|
||||||
|
jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V");
|
||||||
|
if (not e->ExceptionCheck()) {
|
||||||
|
jclass stringClass = e->FindClass("java/lang/String");
|
||||||
|
if (not e->ExceptionCheck()) {
|
||||||
|
jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0);
|
||||||
|
if (not e->ExceptionCheck()) {
|
||||||
|
for (int i = 1; i < ac; ++i) {
|
||||||
|
e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
e->CallStaticVoidMethod(c, m, a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int exitCode = 0;
|
||||||
|
if (e->ExceptionCheck()) {
|
||||||
|
exitCode = -1;
|
||||||
|
e->ExceptionDescribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
vm->DestroyJavaVM();
|
||||||
|
|
||||||
|
return exitCode;
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
$ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \
|
||||||
|
-D_JNI_IMPLEMENTATION_ -c bootimage-main.cpp -o main.o
|
||||||
|
|
||||||
|
__8.__ Link the objects produced above to produce the final
|
||||||
|
executable, and optionally strip its symbols.
|
||||||
|
|
||||||
|
$ g++ -rdynamic *.o -ldl -lpthread -lz -o hello
|
||||||
|
$ strip --strip-all hello
|
||||||
|
|
||||||
|
|
||||||
|
Trademarks
|
||||||
|
----------
|
||||||
|
|
||||||
|
Oracle and Java are registered trademarks of Oracle and/or its
|
||||||
|
affiliates. Other names may be trademarks of their respective owners.
|
||||||
|
|
||||||
|
The Avian project is not affiliated with Oracle.
|
89
sgx-jvm/avian/android.pro
Normal file
89
sgx-jvm/avian/android.pro
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
# these are referenced in JniConstants.cpp:
|
||||||
|
|
||||||
|
-keep class java.text.Bidi$Run
|
||||||
|
-keep class java.math.BigDecimal
|
||||||
|
-keep class java.lang.Boolean
|
||||||
|
-keep class java.lang.Byte
|
||||||
|
-keep class java.nio.charset.CharsetICU {
|
||||||
|
CharsetICU(java.lang.String, java.lang.String, java.lang.String[]);
|
||||||
|
}
|
||||||
|
-keep class java.lang.reflect.Constructor
|
||||||
|
-keep class java.util.zip.Deflater
|
||||||
|
-keep class java.lang.Double
|
||||||
|
-keep class libcore.io.ErrnoException
|
||||||
|
-keep class java.lang.reflect.Field
|
||||||
|
-keep class libcore.icu.NativeDecimalFormat$FieldPositionIterator {
|
||||||
|
void setData(int[]);
|
||||||
|
}
|
||||||
|
-keep class java.io.FileDescriptor
|
||||||
|
-keep class libcore.io.GaiException
|
||||||
|
-keep class java.net.Inet6Address
|
||||||
|
-keep class java.net.InetAddress
|
||||||
|
-keep class java.net.InetSocketAddress
|
||||||
|
-keep class java.net.InetUnixAddress
|
||||||
|
-keep class java.util.zip.Inflater
|
||||||
|
-keep class java.lang.Integer
|
||||||
|
-keep class libcore.icu.LocaleData
|
||||||
|
-keep class java.lang.Long
|
||||||
|
-keep class java.lang.reflect.Method
|
||||||
|
-keep class libcore.util.MutableInt
|
||||||
|
-keep class libcore.util.MutableLong
|
||||||
|
-keep class java.text.ParsePosition
|
||||||
|
-keep class java.util.regex.PatternSyntaxException
|
||||||
|
-keep class java.lang.RealToString
|
||||||
|
-keep class java.net.Socket
|
||||||
|
-keep class java.net.SocketImpl
|
||||||
|
-keep class java.lang.String
|
||||||
|
-keep class libcore.io.StructAddrinfo {
|
||||||
|
<fields>;
|
||||||
|
}
|
||||||
|
-keep class libcore.io.StructFlock
|
||||||
|
-keep class libcore.io.StructGroupReq
|
||||||
|
-keep class libcore.io.StructLinger
|
||||||
|
-keep class libcore.io.StructPasswd {
|
||||||
|
StructPasswd(java.lang.String, int, int, java.lang.String, java.lang.String);
|
||||||
|
}
|
||||||
|
-keep class libcore.io.StructPollfd
|
||||||
|
-keep class libcore.io.StructStat {
|
||||||
|
StructStat(long, long, int, long, int, int, long, long, long, long, long, long, long);
|
||||||
|
}
|
||||||
|
-keep class libcore.io.StructStatFs
|
||||||
|
-keep class libcore.io.StructTimeval
|
||||||
|
-keep class libcore.io.StructUtsname {
|
||||||
|
StructUtsname(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
|
||||||
|
}
|
||||||
|
-keep class libcore.io.StructUcred
|
||||||
|
|
||||||
|
# referenced from libcore native code
|
||||||
|
|
||||||
|
-keep class libcore.icu.LocaleData {
|
||||||
|
<fields>;
|
||||||
|
}
|
||||||
|
|
||||||
|
-keep class org.conscrypt.OpenSSLBIOInputStream {
|
||||||
|
<methods>;
|
||||||
|
}
|
||||||
|
|
||||||
|
-keep class java.util.Calendar {
|
||||||
|
void set(int, int, int, int, int, int);
|
||||||
|
}
|
||||||
|
|
||||||
|
# called from the VM
|
||||||
|
|
||||||
|
-keep class java.lang.Thread {
|
||||||
|
Thread(java.lang.ThreadGroup, java.lang.String, int, boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keep class avian.Classes {
|
||||||
|
java.lang.Class forName(java.lang.String, boolean, java.lang.ClassLoader);
|
||||||
|
int findField(avian.VMClass, java.lang.String);
|
||||||
|
int findMethod(avian.VMClass, java.lang.String, java.lang.Class[]);
|
||||||
|
java.lang.annotation.Annotation getAnnotation(java.lang.ClassLoader, java.lang.Object[]);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keep class java.lang.VMThread {
|
||||||
|
VMThread(java.lang.Thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
# loaded reflectively to handle embedded resources:
|
||||||
|
-keep class avian.avianvmresource.Handler
|
323
sgx-jvm/avian/build.gradle
Normal file
323
sgx-jvm/avian/build.gradle
Normal file
@ -0,0 +1,323 @@
|
|||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
classpath 'org.jfrog.buildinfo:build-info-extractor-gradle:2.2.4'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'native-component'
|
||||||
|
apply plugin: 'ivy-publish'
|
||||||
|
apply plugin: 'java'
|
||||||
|
apply plugin: 'artifactory-publish'
|
||||||
|
|
||||||
|
enum SupportedOS implements OperatingSystem {
|
||||||
|
LINUX, WINDOWS, MACOSX;
|
||||||
|
|
||||||
|
public static final SupportedOS CURRENT;
|
||||||
|
|
||||||
|
static {
|
||||||
|
String p = System.properties['os.name']
|
||||||
|
switch(p.replaceAll(' ', '').toLowerCase()) {
|
||||||
|
case ~/.*linux.*/: CURRENT = LINUX; break;
|
||||||
|
case ~/.*darwin.*/: CURRENT = MACOSX; break;
|
||||||
|
case ~/.*osx.*/: CURRENT = MACOSX; break;
|
||||||
|
case ~/.*win.*/: CURRENT = WINDOWS; break;
|
||||||
|
default:
|
||||||
|
String m = "SupportedOS: unrecognized platform: ${p}"
|
||||||
|
println(m)
|
||||||
|
throw new IllegalArgumentException(m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return toString().toLowerCase()
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDisplayName() {
|
||||||
|
return getName()
|
||||||
|
}
|
||||||
|
public boolean isCurrent() { return this == CURRENT }
|
||||||
|
public boolean isFreeBSD() { return false }
|
||||||
|
public boolean isLinux() { return this == LINUX }
|
||||||
|
public boolean isMacOsX() { return this == MACOSX }
|
||||||
|
public boolean isSolaris() { return false }
|
||||||
|
public boolean isWindows() { return this == WINDOWS }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String adjustArch(String arch) {
|
||||||
|
switch(arch) {
|
||||||
|
case ~/.*64.*/: return 'x86_64'
|
||||||
|
default: return 'i386'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ext {
|
||||||
|
currentPlatform = SupportedOS.CURRENT.getName()
|
||||||
|
currentArch = adjustArch(System.properties['os.arch'])
|
||||||
|
currentPlatformArch = "${currentPlatform}-${currentArch}"
|
||||||
|
|
||||||
|
platform = project.hasProperty('platform') ? platform : currentPlatform
|
||||||
|
arch = project.hasProperty('arch') ? arch : currentArch
|
||||||
|
platformArch = "${platform}-${arch}"
|
||||||
|
|
||||||
|
java_home = System.properties.'java.home'
|
||||||
|
if(java_home.endsWith("/jre")) {
|
||||||
|
java_home = java_home.substring(0, java_home.length() - "/jre".length())
|
||||||
|
}
|
||||||
|
java_home = java_home
|
||||||
|
|
||||||
|
libDir = "${buildDir}/lib"
|
||||||
|
lzmaDir = "${libDir}/lzma"
|
||||||
|
|
||||||
|
buildOptions = ['', '-lzma']
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
ivy {
|
||||||
|
name "ivyLocal"
|
||||||
|
url "${System.env.HOME}/.ivy2/local"
|
||||||
|
layout 'maven'
|
||||||
|
}
|
||||||
|
|
||||||
|
ivy {
|
||||||
|
name "jcenter"
|
||||||
|
if(version.contains("SNAPSHOT")) {
|
||||||
|
url "http://oss.jfrog.org/artifactory/oss-snapshot-local"
|
||||||
|
} else {
|
||||||
|
url "http://oss.jfrog.org/artifactory/oss-release-local"
|
||||||
|
}
|
||||||
|
layout 'maven'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
create('windows-i386')
|
||||||
|
create('windows-x86_64')
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
'windows-i386' "com.readytalk:win32:1.0.0-SNAPSHOT"
|
||||||
|
'windows-x86_64' "com.readytalk:win64:1.0.0-SNAPSHOT"
|
||||||
|
}
|
||||||
|
|
||||||
|
model {
|
||||||
|
platforms {
|
||||||
|
create(platformArch) {
|
||||||
|
operatingSystem SupportedOS.valueOf(platform.toUpperCase())
|
||||||
|
architecture "${arch}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
buildOptions.each { buildOption ->
|
||||||
|
platforms.each { platform ->
|
||||||
|
if(platform.operatingSystem.name == "windows") {
|
||||||
|
def artifactName = platform.architecture.name == "i386" ? 'win32' : 'win64'
|
||||||
|
|
||||||
|
task "extract${platform.name}${buildOption}"(type: Copy) {
|
||||||
|
from {
|
||||||
|
tarTree(configurations."${platform.name}".find { it.name =~ artifactName })
|
||||||
|
}
|
||||||
|
into "${libDir}/tools"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task "build${platform.name}${buildOption}"(type: Exec) {
|
||||||
|
executable "make"
|
||||||
|
args "platform=${platform.operatingSystem.name}",
|
||||||
|
"arch=${platform.architecture.name}"
|
||||||
|
|
||||||
|
if(buildOption == "-lzma") {
|
||||||
|
dependsOn 'extractLzma'
|
||||||
|
args "lzma=${lzmaDir}"
|
||||||
|
}
|
||||||
|
|
||||||
|
if(platform.operatingSystem.name == "windows") {
|
||||||
|
dependsOn "extract${platform.name}${buildOption}"
|
||||||
|
args "win32=${libDir}/tools/win32",
|
||||||
|
"win64=${libDir}/tools/win64"
|
||||||
|
}
|
||||||
|
environment JAVA_HOME: java_home
|
||||||
|
}
|
||||||
|
|
||||||
|
assemble {
|
||||||
|
dependsOn "build${platform.name}${buildOption}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile) {
|
||||||
|
sourceCompatibility = "1.6"
|
||||||
|
targetCompatibility = "1.6"
|
||||||
|
|
||||||
|
options.with {
|
||||||
|
encoding = "UTF-8"
|
||||||
|
bootClasspath = sourceSets.main.output.classesDir
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
java {
|
||||||
|
srcDir 'classpath'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
javadoc {
|
||||||
|
title = "Avian v${version} Class Library API"
|
||||||
|
}
|
||||||
|
|
||||||
|
task javadocJar(type: Jar) {
|
||||||
|
dependsOn javadoc
|
||||||
|
classifier = 'javadoc'
|
||||||
|
from {
|
||||||
|
javadoc.destinationDir
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
baseName "classpath-avian"
|
||||||
|
}
|
||||||
|
|
||||||
|
task downloadLzma(type: Exec) {
|
||||||
|
commandLine "curl"
|
||||||
|
args "--create-dirs", "-o", "${lzmaDir}/lzma920.tar.bz2", "-f", "http://oss.readytalk.com/avian-web/lzma920.tar.bz2"
|
||||||
|
}
|
||||||
|
|
||||||
|
task extractLzma(type: Copy) {
|
||||||
|
dependsOn downloadLzma
|
||||||
|
from {
|
||||||
|
tarTree(resources.bzip2("${lzmaDir}/lzma920.tar.bz2"))
|
||||||
|
}
|
||||||
|
into lzmaDir
|
||||||
|
}
|
||||||
|
|
||||||
|
task install {
|
||||||
|
dependsOn assemble, publish
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
repositories {
|
||||||
|
add(project.repositories."ivyLocal")
|
||||||
|
}
|
||||||
|
|
||||||
|
publications {
|
||||||
|
|
||||||
|
ivy(IvyPublication) {
|
||||||
|
from components.java
|
||||||
|
|
||||||
|
artifact(javadocJar)
|
||||||
|
|
||||||
|
artifact("vm.pro") {
|
||||||
|
name "vm"
|
||||||
|
type "proguard"
|
||||||
|
extension "pro"
|
||||||
|
}
|
||||||
|
|
||||||
|
module "classpath-avian"
|
||||||
|
}
|
||||||
|
|
||||||
|
create("tools-avian-${currentPlatformArch}", IvyPublication) {
|
||||||
|
module "tools-avian-${currentPlatformArch}"
|
||||||
|
|
||||||
|
def publishBinSuffix = currentPlatform == "windows" ? "exe" : "bin"
|
||||||
|
def binSuffix = currentPlatform == "windows" ? ".exe" : ""
|
||||||
|
artifact("${buildDir}/${currentPlatform}-${currentArch}/binaryToObject/binaryToObject${binSuffix}") {
|
||||||
|
name "binaryToObject"
|
||||||
|
type publishBinSuffix
|
||||||
|
extension publishBinSuffix
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildOptions.each { buildOption ->
|
||||||
|
platforms.each { platform ->
|
||||||
|
def binSuffix=""
|
||||||
|
def publishBinSuffix="bin"
|
||||||
|
|
||||||
|
create("${platform.name}${buildOption}", IvyPublication) {
|
||||||
|
def nativeBuildDir = "${buildDir}/${platform.operatingSystem.name}-${platform.architecture.name}${buildOption}"
|
||||||
|
|
||||||
|
if(platform.operatingSystem.name == "windows") {
|
||||||
|
publishBinSuffix = "exe"
|
||||||
|
binSuffix = ".${publishBinSuffix}"
|
||||||
|
}
|
||||||
|
|
||||||
|
module "runtime-avian${buildOption}-${platform.name}"
|
||||||
|
|
||||||
|
artifact("${nativeBuildDir}/avian${binSuffix}") {
|
||||||
|
name "avian"
|
||||||
|
type publishBinSuffix
|
||||||
|
extension publishBinSuffix
|
||||||
|
}
|
||||||
|
|
||||||
|
artifact("${nativeBuildDir}/libavian.a") {
|
||||||
|
name "libavian"
|
||||||
|
type "a"
|
||||||
|
extension "a"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buildOption == "-lzma") {
|
||||||
|
artifact("${nativeBuildDir}/libavian-lzma.a") {
|
||||||
|
name "libavian-lzma"
|
||||||
|
type "a"
|
||||||
|
extension "a"
|
||||||
|
}
|
||||||
|
|
||||||
|
artifact("${nativeBuildDir}/lzma/lzma${binSuffix}") {
|
||||||
|
name "lzma"
|
||||||
|
type publishBinSuffix
|
||||||
|
extension publishBinSuffix
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
artifactoryPublish {
|
||||||
|
onlyIf {
|
||||||
|
// TRAVIS_BRANCH reports master if it is a master build or a PR going to master
|
||||||
|
// TRAVIS_PULL_REQUEST reports false if not a pull request and the PR number if it is
|
||||||
|
System.env.'TRAVIS_BRANCH' == "master" && System.env.'TRAVIS_PULL_REQUEST' == "false"
|
||||||
|
}
|
||||||
|
dependsOn assemble
|
||||||
|
}
|
||||||
|
|
||||||
|
artifactory {
|
||||||
|
contextUrl = "http://oss.jfrog.org"
|
||||||
|
|
||||||
|
resolve {
|
||||||
|
repository {
|
||||||
|
repoKey = 'libs-releases'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
publish {
|
||||||
|
repository {
|
||||||
|
repoKey = 'oss-snapshot-local'
|
||||||
|
username = System.env.BINTRAY_USER
|
||||||
|
password = System.env.BINTRAY_API_KEY
|
||||||
|
ivy {
|
||||||
|
ivyLayout = "[organisation]/[module]/[revision]/ivy-[revision].xml"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defaults {
|
||||||
|
platforms.each {
|
||||||
|
publications it.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task wrapper(type: Wrapper) {
|
||||||
|
distributionUrl = 'http://services.gradle.org/distributions/gradle-2.0-bin.zip'
|
||||||
|
}
|
17
sgx-jvm/avian/classpath/avian/Addendum.java
Normal file
17
sgx-jvm/avian/classpath/avian/Addendum.java
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class Addendum {
|
||||||
|
public Singleton pool;
|
||||||
|
public Object annotationTable;
|
||||||
|
public Object signature;
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.InvocationHandler;
|
||||||
|
|
||||||
|
public class AnnotationInvocationHandler implements InvocationHandler {
|
||||||
|
private Object[] data;
|
||||||
|
|
||||||
|
public AnnotationInvocationHandler(Object[] data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object invoke(Object proxy, Method method, Object[] arguments) {
|
||||||
|
String name = method.getName();
|
||||||
|
for (int i = 2; i < data.length; i += 2) {
|
||||||
|
if (name.equals(data[i])) {
|
||||||
|
return data[i + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return method.getDefaultValue();
|
||||||
|
}
|
||||||
|
}
|
135
sgx-jvm/avian/classpath/avian/Assembler.java
Normal file
135
sgx-jvm/avian/classpath/avian/Assembler.java
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
import static avian.Stream.write1;
|
||||||
|
import static avian.Stream.write2;
|
||||||
|
import static avian.Stream.write4;
|
||||||
|
|
||||||
|
import avian.ConstantPool.PoolEntry;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class Assembler {
|
||||||
|
public static final int ACC_PUBLIC = 1 << 0;
|
||||||
|
public static final int ACC_STATIC = 1 << 3;
|
||||||
|
|
||||||
|
public static final int aaload = 0x32;
|
||||||
|
public static final int aastore = 0x53;
|
||||||
|
public static final int aload = 0x19;
|
||||||
|
public static final int aload_0 = 0x2a;
|
||||||
|
public static final int aload_1 = 0x2b;
|
||||||
|
public static final int astore_0 = 0x4b;
|
||||||
|
public static final int anewarray = 0xbd;
|
||||||
|
public static final int areturn = 0xb0;
|
||||||
|
public static final int dload = 0x18;
|
||||||
|
public static final int dreturn = 0xaf;
|
||||||
|
public static final int dup = 0x59;
|
||||||
|
public static final int fload = 0x17;
|
||||||
|
public static final int freturn = 0xae;
|
||||||
|
public static final int getfield = 0xb4;
|
||||||
|
public static final int goto_ = 0xa7;
|
||||||
|
public static final int iload = 0x15;
|
||||||
|
public static final int invokeinterface = 0xb9;
|
||||||
|
public static final int invokespecial = 0xb7;
|
||||||
|
public static final int invokestatic = 0xb8;
|
||||||
|
public static final int invokevirtual = 0xb6;
|
||||||
|
public static final int ireturn = 0xac;
|
||||||
|
public static final int jsr = 0xa8;
|
||||||
|
public static final int ldc_w = 0x13;
|
||||||
|
public static final int lload = 0x16;
|
||||||
|
public static final int lreturn = 0xad;
|
||||||
|
public static final int new_ = 0xbb;
|
||||||
|
public static final int pop = 0x57;
|
||||||
|
public static final int putfield = 0xb5;
|
||||||
|
public static final int ret = 0xa9;
|
||||||
|
public static final int return_ = 0xb1;
|
||||||
|
|
||||||
|
public static void writeClass(OutputStream out,
|
||||||
|
List<PoolEntry> pool,
|
||||||
|
int name,
|
||||||
|
int super_,
|
||||||
|
int[] interfaces,
|
||||||
|
FieldData[] fields,
|
||||||
|
MethodData[] methods)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
int codeAttributeName = ConstantPool.addUtf8(pool, "Code");
|
||||||
|
|
||||||
|
write4(out, 0xCAFEBABE);
|
||||||
|
write2(out, 0); // minor version
|
||||||
|
write2(out, 50); // major version
|
||||||
|
|
||||||
|
write2(out, pool.size() + 1);
|
||||||
|
for (PoolEntry e: pool) {
|
||||||
|
e.writeTo(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
write2(out, ACC_PUBLIC); // flags
|
||||||
|
write2(out, name + 1);
|
||||||
|
write2(out, super_ + 1);
|
||||||
|
|
||||||
|
write2(out, interfaces.length);
|
||||||
|
for (int i: interfaces) {
|
||||||
|
write2(out, i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
write2(out, fields.length);
|
||||||
|
for (FieldData f: fields) {
|
||||||
|
write2(out, f.flags);
|
||||||
|
write2(out, f.nameIndex + 1);
|
||||||
|
write2(out, f.specIndex + 1);
|
||||||
|
write2(out, 0); // attribute count
|
||||||
|
}
|
||||||
|
|
||||||
|
write2(out, methods.length);
|
||||||
|
for (MethodData m: methods) {
|
||||||
|
write2(out, m.flags);
|
||||||
|
write2(out, m.nameIndex + 1);
|
||||||
|
write2(out, m.specIndex + 1);
|
||||||
|
|
||||||
|
write2(out, 1); // attribute count
|
||||||
|
write2(out, codeAttributeName + 1);
|
||||||
|
write4(out, m.code.length);
|
||||||
|
out.write(m.code);
|
||||||
|
}
|
||||||
|
|
||||||
|
write2(out, 0); // attribute count
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MethodData {
|
||||||
|
public final int flags;
|
||||||
|
public final int nameIndex;
|
||||||
|
public final int specIndex;
|
||||||
|
public final byte[] code;
|
||||||
|
|
||||||
|
public MethodData(int flags, int nameIndex, int specIndex, byte[] code) {
|
||||||
|
this.flags = flags;
|
||||||
|
this.nameIndex = nameIndex;
|
||||||
|
this.specIndex = specIndex;
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class FieldData {
|
||||||
|
public final int flags;
|
||||||
|
public final int nameIndex;
|
||||||
|
public final int specIndex;
|
||||||
|
|
||||||
|
public FieldData(int flags, int nameIndex, int specIndex) {
|
||||||
|
this.flags = flags;
|
||||||
|
this.nameIndex = nameIndex;
|
||||||
|
this.specIndex = specIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
sgx-jvm/avian/classpath/avian/Atomic.java
Normal file
20
sgx-jvm/avian/classpath/avian/Atomic.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
public class Atomic {
|
||||||
|
public static native long getOffset(Field field);
|
||||||
|
|
||||||
|
public static native boolean compareAndSwapObject
|
||||||
|
(Object o, long offset, Object old, Object new_);
|
||||||
|
}
|
16
sgx-jvm/avian/classpath/avian/Callback.java
Normal file
16
sgx-jvm/avian/classpath/avian/Callback.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public interface Callback<T> {
|
||||||
|
public void handleResult(T result);
|
||||||
|
public void handleException(Throwable exception);
|
||||||
|
}
|
54
sgx-jvm/avian/classpath/avian/Cell.java
Normal file
54
sgx-jvm/avian/classpath/avian/Cell.java
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class Cell <T> {
|
||||||
|
public T value;
|
||||||
|
public Cell<T> next;
|
||||||
|
|
||||||
|
public Cell(T value, Cell<T> next) {
|
||||||
|
this.value = value;
|
||||||
|
this.next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("(");
|
||||||
|
for (Cell c = this; c != null; c = c.next) {
|
||||||
|
sb.append(value);
|
||||||
|
if (c.next != null) {
|
||||||
|
sb.append(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append(")");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <Car> Cell<Car> cons(Car car, Cell<Car> cdr) {
|
||||||
|
return new Cell(car, cdr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> boolean equal(T a, T b) {
|
||||||
|
return (a == null && b == null) || (a != null && a.equals(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <Car> boolean equal(Cell<Car> a, Cell<Car> b) {
|
||||||
|
while (a != null) {
|
||||||
|
if (b == null || (! equal(a.value, b.value))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
a = a.next;
|
||||||
|
b = b.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return b == null;
|
||||||
|
}
|
||||||
|
}
|
32
sgx-jvm/avian/classpath/avian/ClassAddendum.java
Normal file
32
sgx-jvm/avian/classpath/avian/ClassAddendum.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class ClassAddendum extends Addendum {
|
||||||
|
public Object[] interfaceTable;
|
||||||
|
public InnerClassReference[] innerClassTable;
|
||||||
|
/**
|
||||||
|
* If this value is negative, all the methods in VMClass.methodTable
|
||||||
|
* were declared in that class. Otherwise, only the first
|
||||||
|
* declaredMethodCount methods in that table were declared in that
|
||||||
|
* class, while the rest were declared in interfaces implemented or
|
||||||
|
* extended by that class.
|
||||||
|
*/
|
||||||
|
public int declaredMethodCount;
|
||||||
|
|
||||||
|
public byte[] enclosingClass;
|
||||||
|
|
||||||
|
public Pair enclosingMethod;
|
||||||
|
|
||||||
|
public VMMethod[] bootstrapMethodTable;
|
||||||
|
|
||||||
|
public VMMethod[] bootstrapLambdaTable;
|
||||||
|
}
|
604
sgx-jvm/avian/classpath/avian/Classes.java
Normal file
604
sgx-jvm/avian/classpath/avian/Classes.java
Normal file
@ -0,0 +1,604 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
import static avian.Stream.read1;
|
||||||
|
import static avian.Stream.read2;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.security.CodeSource;
|
||||||
|
import java.security.AllPermission;
|
||||||
|
import java.security.Permissions;
|
||||||
|
import java.security.ProtectionDomain;
|
||||||
|
import java.security.cert.Certificate;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Proxy;
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class Classes {
|
||||||
|
private static final int LinkFlag = 1 << 8;
|
||||||
|
|
||||||
|
public static native VMClass defineVMClass
|
||||||
|
(ClassLoader loader, byte[] b, int offset, int length);
|
||||||
|
|
||||||
|
public static native VMClass primitiveClass(char name);
|
||||||
|
|
||||||
|
public static native void initialize(VMClass vmClass);
|
||||||
|
|
||||||
|
public static native boolean isAssignableFrom(VMClass a, VMClass b);
|
||||||
|
|
||||||
|
public static native VMClass getVMClass(Object o);
|
||||||
|
|
||||||
|
public static native VMClass toVMClass(Class c);
|
||||||
|
|
||||||
|
public static native VMMethod toVMMethod(Method m);
|
||||||
|
|
||||||
|
private static native VMClass resolveVMClass(ClassLoader loader, byte[] spec)
|
||||||
|
throws ClassNotFoundException;
|
||||||
|
|
||||||
|
public static VMClass loadVMClass(ClassLoader loader,
|
||||||
|
byte[] nameBytes, int offset, int length)
|
||||||
|
{
|
||||||
|
byte[] spec = new byte[length + 1];
|
||||||
|
System.arraycopy(nameBytes, offset, spec, 0, length);
|
||||||
|
|
||||||
|
try {
|
||||||
|
VMClass c = resolveVMClass(loader, spec);
|
||||||
|
if (c == null) {
|
||||||
|
throw new NoClassDefFoundError();
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
NoClassDefFoundError error = new NoClassDefFoundError
|
||||||
|
(new String(nameBytes, offset, length));
|
||||||
|
error.initCause(e);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object parseAnnotationValue(ClassLoader loader,
|
||||||
|
Object pool,
|
||||||
|
InputStream in)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
switch (read1(in)) {
|
||||||
|
case 'Z':
|
||||||
|
return Boolean.valueOf(Singleton.getInt(pool, read2(in) - 1) != 0);
|
||||||
|
|
||||||
|
case 'B':
|
||||||
|
return Byte.valueOf((byte) Singleton.getInt(pool, read2(in) - 1));
|
||||||
|
|
||||||
|
case 'C':
|
||||||
|
return Character.valueOf((char) Singleton.getInt(pool, read2(in) - 1));
|
||||||
|
|
||||||
|
case 'S':
|
||||||
|
return Short.valueOf((short) Singleton.getInt(pool, read2(in) - 1));
|
||||||
|
|
||||||
|
case 'I':
|
||||||
|
return Integer.valueOf(Singleton.getInt(pool, read2(in) - 1));
|
||||||
|
|
||||||
|
case 'F':
|
||||||
|
return Float.valueOf
|
||||||
|
(Float.intBitsToFloat(Singleton.getInt(pool, read2(in) - 1)));
|
||||||
|
|
||||||
|
case 'J': {
|
||||||
|
return Long.valueOf(Singleton.getLong(pool, read2(in) - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'D': {
|
||||||
|
return Double.valueOf
|
||||||
|
(Double.longBitsToDouble(Singleton.getLong(pool, read2(in) - 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
case 's': {
|
||||||
|
byte[] data = (byte[]) Singleton.getObject(pool, read2(in) - 1);
|
||||||
|
|
||||||
|
return new String(data, 0, data.length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'e': {
|
||||||
|
byte[] typeName = (byte[]) Singleton.getObject(pool, read2(in) - 1);
|
||||||
|
byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1);
|
||||||
|
|
||||||
|
return Enum.valueOf
|
||||||
|
(SystemClassLoader.getClass
|
||||||
|
(loadVMClass(loader, typeName, 1, typeName.length - 3)),
|
||||||
|
new String(name, 0, name.length - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'c':{
|
||||||
|
byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1);
|
||||||
|
|
||||||
|
return SystemClassLoader.getClass
|
||||||
|
(loadVMClass(loader, name, 1, name.length - 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
case '@':
|
||||||
|
return getAnnotation(loader, parseAnnotation(loader, pool, in));
|
||||||
|
|
||||||
|
case '[': {
|
||||||
|
Object[] array = new Object[read2(in)];
|
||||||
|
for (int i = 0; i < array.length; ++i) {
|
||||||
|
array[i] = parseAnnotationValue(loader, pool, in);
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: throw new AssertionError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object[] parseAnnotation(ClassLoader loader,
|
||||||
|
Object pool,
|
||||||
|
InputStream in)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
byte[] typeName = (byte[]) Singleton.getObject(pool, read2(in) - 1);
|
||||||
|
Object[] annotation = new Object[(read2(in) + 1) * 2];
|
||||||
|
annotation[1] = SystemClassLoader.getClass
|
||||||
|
(loadVMClass(loader, typeName, 1, typeName.length - 3));
|
||||||
|
|
||||||
|
for (int i = 2; i < annotation.length; i += 2) {
|
||||||
|
byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1);
|
||||||
|
annotation[i] = new String(name, 0, name.length - 1);
|
||||||
|
annotation[i + 1] = parseAnnotationValue(loader, pool, in);
|
||||||
|
}
|
||||||
|
|
||||||
|
return annotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object[] parseAnnotationTable(ClassLoader loader,
|
||||||
|
Object pool,
|
||||||
|
InputStream in)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
Object[] table = new Object[read2(in)];
|
||||||
|
for (int i = 0; i < table.length; ++i) {
|
||||||
|
table[i] = parseAnnotation(loader, pool, in);
|
||||||
|
}
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void parseAnnotationTable(ClassLoader loader,
|
||||||
|
Addendum addendum)
|
||||||
|
{
|
||||||
|
if (addendum != null && addendum.annotationTable instanceof byte[]) {
|
||||||
|
try {
|
||||||
|
addendum.annotationTable = parseAnnotationTable
|
||||||
|
(loader, addendum.pool, new ByteArrayInputStream
|
||||||
|
((byte[]) addendum.annotationTable));
|
||||||
|
} catch (IOException e) {
|
||||||
|
AssertionError error = new AssertionError();
|
||||||
|
error.initCause(e);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int resolveSpec(ClassLoader loader, byte[] spec, int start) {
|
||||||
|
int result;
|
||||||
|
int end;
|
||||||
|
switch (spec[start]) {
|
||||||
|
case 'L':
|
||||||
|
++ start;
|
||||||
|
end = start;
|
||||||
|
while (spec[end] != ';') ++ end;
|
||||||
|
result = end + 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '[':
|
||||||
|
end = start + 1;
|
||||||
|
while (spec[end] == '[') ++ end;
|
||||||
|
switch (spec[end]) {
|
||||||
|
case 'L':
|
||||||
|
++ end;
|
||||||
|
while (spec[end] != ';') ++ end;
|
||||||
|
++ end;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
++ end;
|
||||||
|
}
|
||||||
|
result = end;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return start + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadVMClass(loader, spec, start, end - start);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int declaredMethodCount(VMClass c) {
|
||||||
|
ClassAddendum a = c.addendum;
|
||||||
|
if (a != null) {
|
||||||
|
int count = a.declaredMethodCount;
|
||||||
|
if (count >= 0) {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VMMethod[] table = c.methodTable;
|
||||||
|
return table == null ? 0 : table.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void link(VMClass c, ClassLoader loader) {
|
||||||
|
acquireClassLock();
|
||||||
|
try {
|
||||||
|
if ((c.vmFlags & LinkFlag) == 0) {
|
||||||
|
if (c.super_ != null) {
|
||||||
|
link(c.super_, loader);
|
||||||
|
}
|
||||||
|
|
||||||
|
parseAnnotationTable(loader, c.addendum);
|
||||||
|
|
||||||
|
if (c.interfaceTable != null) {
|
||||||
|
int stride = ((c.flags & Modifier.INTERFACE) != 0 ? 1 : 2);
|
||||||
|
for (int i = 0; i < c.interfaceTable.length; i += stride) {
|
||||||
|
link((VMClass) c.interfaceTable[i], loader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VMMethod[] methodTable = c.methodTable;
|
||||||
|
if (methodTable != null) {
|
||||||
|
for (int i = 0; i < methodTable.length; ++i) {
|
||||||
|
VMMethod m = methodTable[i];
|
||||||
|
|
||||||
|
for (int j = 1; j < m.spec.length;) {
|
||||||
|
j = resolveSpec(loader, m.spec, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
parseAnnotationTable(loader, m.addendum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c.fieldTable != null) {
|
||||||
|
for (int i = 0; i < c.fieldTable.length; ++i) {
|
||||||
|
VMField f = c.fieldTable[i];
|
||||||
|
|
||||||
|
resolveSpec(loader, f.spec, 0);
|
||||||
|
|
||||||
|
parseAnnotationTable(loader, f.addendum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.vmFlags |= LinkFlag;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
releaseClassLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void link(VMClass c) {
|
||||||
|
link(c, c.loader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Class forName(String name, boolean initialize,
|
||||||
|
ClassLoader loader)
|
||||||
|
throws ClassNotFoundException
|
||||||
|
{
|
||||||
|
if (loader == null) {
|
||||||
|
loader = Class.class.getClassLoader();
|
||||||
|
}
|
||||||
|
Class c = loader.loadClass(name);
|
||||||
|
VMClass vmc = SystemClassLoader.vmClass(c);
|
||||||
|
link(vmc, loader);
|
||||||
|
if (initialize) {
|
||||||
|
initialize(vmc);
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Class forCanonicalName(String name) {
|
||||||
|
return forCanonicalName(null, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Class forCanonicalName(ClassLoader loader, String name) {
|
||||||
|
try {
|
||||||
|
if (name.startsWith("[")) {
|
||||||
|
return forName(name, true, loader);
|
||||||
|
} else if (name.startsWith("L")) {
|
||||||
|
return forName(name.substring(1, name.length() - 1), true, loader);
|
||||||
|
} else {
|
||||||
|
if (name.length() == 1) {
|
||||||
|
return SystemClassLoader.getClass
|
||||||
|
(primitiveClass(name.charAt(0)));
|
||||||
|
} else {
|
||||||
|
throw new ClassNotFoundException(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int next(char c, String s, int start) {
|
||||||
|
for (int i = start; i < s.length(); ++i) {
|
||||||
|
if (s.charAt(i) == c) return i;
|
||||||
|
}
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Class[] getParameterTypes(VMMethod vmMethod) {
|
||||||
|
int count = vmMethod.parameterCount;
|
||||||
|
|
||||||
|
Class[] types = new Class[count];
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
String spec = new String
|
||||||
|
(vmMethod.spec, 1, vmMethod.spec.length - 2);
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (int i = 0; i < spec.length(); ++i) {
|
||||||
|
char c = spec.charAt(i);
|
||||||
|
if (c == ')') {
|
||||||
|
break;
|
||||||
|
} else if (c == 'L') {
|
||||||
|
int start = i + 1;
|
||||||
|
i = next(';', spec, start);
|
||||||
|
String name = spec.substring(start, i).replace('/', '.');
|
||||||
|
types[index++] = Class.forName(name, true, vmMethod.class_.loader);
|
||||||
|
} else if (c == '[') {
|
||||||
|
int start = i;
|
||||||
|
while (spec.charAt(i) == '[') ++i;
|
||||||
|
|
||||||
|
if (spec.charAt(i) == 'L') {
|
||||||
|
i = next(';', spec, i + 1);
|
||||||
|
String name = spec.substring(start, i).replace('/', '.');
|
||||||
|
types[index++] = Class.forName
|
||||||
|
(name, true, vmMethod.class_.loader);
|
||||||
|
} else {
|
||||||
|
String name = spec.substring(start, i + 1);
|
||||||
|
types[index++] = forCanonicalName(vmMethod.class_.loader, name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String name = spec.substring(i, i + 1);
|
||||||
|
types[index++] = forCanonicalName(vmMethod.class_.loader, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int findField(VMClass vmClass, String name) {
|
||||||
|
if (vmClass.fieldTable != null) {
|
||||||
|
link(vmClass);
|
||||||
|
|
||||||
|
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
|
||||||
|
if (toString(vmClass.fieldTable[i].name).equals(name)) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toString(byte[] array) {
|
||||||
|
return new String(array, 0, array.length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean match(VMClass a, VMClass b) {
|
||||||
|
// TODO: in theory we should be able to just do an == comparison
|
||||||
|
// here instead of recursively comparing array element types.
|
||||||
|
// However, the VM currently can create multiple array classes for
|
||||||
|
// the same element type. We should fix that so that there's only
|
||||||
|
// ever one of each per classloader, eliminating the need for a
|
||||||
|
// recursive comparison. See also the native implementation of
|
||||||
|
// isAssignableFrom.
|
||||||
|
if (a.arrayDimensions > 0) {
|
||||||
|
return match(a.arrayElementClass, b.arrayElementClass);
|
||||||
|
} else {
|
||||||
|
return a == b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean match(Class[] a, Class[] b) {
|
||||||
|
if (a.length == b.length) {
|
||||||
|
for (int i = 0; i < a.length; ++i) {
|
||||||
|
if (! match(toVMClass(a[i]), toVMClass(b[i]))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static VMMethod findMethod(ClassLoader loader,
|
||||||
|
String class_,
|
||||||
|
String name,
|
||||||
|
String spec)
|
||||||
|
throws ClassNotFoundException
|
||||||
|
{
|
||||||
|
VMClass c = SystemClassLoader.vmClass(loader.loadClass(class_));
|
||||||
|
VMMethod[] methodTable = c.methodTable;
|
||||||
|
if (methodTable != null) {
|
||||||
|
link(c);
|
||||||
|
|
||||||
|
for (int i = 0; i < methodTable.length; ++i) {
|
||||||
|
VMMethod m = methodTable[i];
|
||||||
|
if (toString(m.name).equals(name) && toString(m.spec).equals(spec)) {
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int findMethod(VMClass vmClass, String name,
|
||||||
|
Class[] parameterTypes)
|
||||||
|
{
|
||||||
|
VMMethod[] methodTable = vmClass.methodTable;
|
||||||
|
if (methodTable != null) {
|
||||||
|
link(vmClass);
|
||||||
|
|
||||||
|
if (parameterTypes == null) {
|
||||||
|
parameterTypes = new Class[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < methodTable.length; ++i) {
|
||||||
|
VMMethod m = methodTable[i];
|
||||||
|
if (toString(m.name).equals(name)
|
||||||
|
&& match(parameterTypes, getParameterTypes(m)))
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int countMethods(VMClass vmClass, boolean publicOnly) {
|
||||||
|
int count = 0;
|
||||||
|
VMMethod[] methodTable = vmClass.methodTable;
|
||||||
|
if (methodTable != null) {
|
||||||
|
for (int i = 0, j = declaredMethodCount(vmClass); i < j; ++i) {
|
||||||
|
VMMethod m = methodTable[i];
|
||||||
|
if (((! publicOnly) || ((m.flags & Modifier.PUBLIC)) != 0)
|
||||||
|
&& (! toString(m.name).startsWith("<")))
|
||||||
|
{
|
||||||
|
++ count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Method[] getMethods(VMClass vmClass, boolean publicOnly) {
|
||||||
|
Method[] array = new Method[countMethods(vmClass, publicOnly)];
|
||||||
|
VMMethod[] methodTable = vmClass.methodTable;
|
||||||
|
if (methodTable != null) {
|
||||||
|
link(vmClass);
|
||||||
|
|
||||||
|
int ai = 0;
|
||||||
|
for (int i = 0, j = declaredMethodCount(vmClass); i < j; ++i) {
|
||||||
|
VMMethod m = methodTable[i];
|
||||||
|
if (((! publicOnly) || ((m.flags & Modifier.PUBLIC) != 0))
|
||||||
|
&& ! toString(m.name).startsWith("<"))
|
||||||
|
{
|
||||||
|
array[ai++] = makeMethod(SystemClassLoader.getClass(vmClass), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int countFields(VMClass vmClass, boolean publicOnly) {
|
||||||
|
int count = 0;
|
||||||
|
if (vmClass.fieldTable != null) {
|
||||||
|
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
|
||||||
|
if ((! publicOnly)
|
||||||
|
|| ((vmClass.fieldTable[i].flags & Modifier.PUBLIC))
|
||||||
|
!= 0)
|
||||||
|
{
|
||||||
|
++ count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Field[] getFields(VMClass vmClass, boolean publicOnly) {
|
||||||
|
Field[] array = new Field[countFields(vmClass, publicOnly)];
|
||||||
|
if (vmClass.fieldTable != null) {
|
||||||
|
link(vmClass);
|
||||||
|
|
||||||
|
int ai = 0;
|
||||||
|
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
|
||||||
|
if (((vmClass.fieldTable[i].flags & Modifier.PUBLIC) != 0)
|
||||||
|
|| (! publicOnly))
|
||||||
|
{
|
||||||
|
array[ai++] = makeField(SystemClassLoader.getClass(vmClass), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Annotation getAnnotation(ClassLoader loader, Object[] a) {
|
||||||
|
if (a[0] == null) {
|
||||||
|
a[0] = Proxy.newProxyInstance
|
||||||
|
(loader, new Class[] { (Class) a[1] },
|
||||||
|
new AnnotationInvocationHandler(a));
|
||||||
|
}
|
||||||
|
return (Annotation) a[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object getAnnotationDefaultValue(ClassLoader loader,
|
||||||
|
MethodAddendum addendum) {
|
||||||
|
if (addendum == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
byte[] annotationDefault = (byte[]) addendum.annotationDefault;
|
||||||
|
if (annotationDefault == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return parseAnnotationValue(loader, addendum.pool,
|
||||||
|
new ByteArrayInputStream(annotationDefault));
|
||||||
|
} catch (IOException e) {
|
||||||
|
AssertionError error = new AssertionError();
|
||||||
|
error.initCause(e);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int index(VMMethod m) {
|
||||||
|
VMMethod[] table = m.class_.methodTable;
|
||||||
|
for (int i = 0; i < table.length; ++i) {
|
||||||
|
if (m == table[i]) return i;
|
||||||
|
}
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Method makeMethod(VMMethod m) {
|
||||||
|
return makeMethod(SystemClassLoader.getClass(m.class_), index(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ProtectionDomain getProtectionDomain(VMClass c) {
|
||||||
|
CodeSource source = null;
|
||||||
|
if (c.source != null) {
|
||||||
|
try {
|
||||||
|
source = new CodeSource
|
||||||
|
(new URL(new String(c.source, 0, c.source.length - 1)),
|
||||||
|
(Certificate[]) null);
|
||||||
|
} catch (MalformedURLException ignored) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
Permissions p = new Permissions();
|
||||||
|
p.add(new AllPermission());
|
||||||
|
|
||||||
|
return new ProtectionDomain(source, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static native Method makeMethod(Class c, int slot);
|
||||||
|
|
||||||
|
public static native Field makeField(Class c, int slot);
|
||||||
|
|
||||||
|
private static native void acquireClassLock();
|
||||||
|
|
||||||
|
private static native void releaseClassLock();
|
||||||
|
|
||||||
|
public static native String makeString(byte[] array, int offset, int length);
|
||||||
|
}
|
5
sgx-jvm/avian/classpath/avian/Code.java
Normal file
5
sgx-jvm/avian/classpath/avian/Code.java
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package avian;
|
||||||
|
|
||||||
|
abstract class Code {
|
||||||
|
// VM-visible fields in types.def
|
||||||
|
}
|
242
sgx-jvm/avian/classpath/avian/ConstantPool.java
Normal file
242
sgx-jvm/avian/classpath/avian/ConstantPool.java
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
import static avian.Stream.write1;
|
||||||
|
import static avian.Stream.write2;
|
||||||
|
import static avian.Stream.write4;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class ConstantPool {
|
||||||
|
private static final int CONSTANT_Integer = 3;
|
||||||
|
private static final int CONSTANT_Utf8 = 1;
|
||||||
|
private static final int CONSTANT_String = 8;
|
||||||
|
private static final int CONSTANT_Class = 7;
|
||||||
|
private static final int CONSTANT_NameAndType = 12;
|
||||||
|
private static final int CONSTANT_Fieldref = 9;
|
||||||
|
private static final int CONSTANT_Methodref = 10;
|
||||||
|
|
||||||
|
public static int add(List<PoolEntry> pool, PoolEntry e) {
|
||||||
|
int i = 0;
|
||||||
|
for (PoolEntry existing: pool) {
|
||||||
|
if (existing.equals(e)) {
|
||||||
|
return i;
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pool.add(e);
|
||||||
|
return pool.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int addInteger(List<PoolEntry> pool, int value) {
|
||||||
|
return add(pool, new IntegerPoolEntry(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int addUtf8(List<PoolEntry> pool, String value) {
|
||||||
|
return add(pool, new Utf8PoolEntry(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int addString(List<PoolEntry> pool, String value) {
|
||||||
|
return add(pool, new StringPoolEntry(addUtf8(pool, value)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int addClass(List<PoolEntry> pool, String name) {
|
||||||
|
return add(pool, new ClassPoolEntry(addUtf8(pool, name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int addNameAndType(List<PoolEntry> pool,
|
||||||
|
String name,
|
||||||
|
String type)
|
||||||
|
{
|
||||||
|
return add(pool, new NameAndTypePoolEntry
|
||||||
|
(addUtf8(pool, name),
|
||||||
|
addUtf8(pool, type)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int addFieldRef(List<PoolEntry> pool,
|
||||||
|
String className,
|
||||||
|
String name,
|
||||||
|
String spec)
|
||||||
|
{
|
||||||
|
return add(pool, new FieldRefPoolEntry
|
||||||
|
(addClass(pool, className),
|
||||||
|
addNameAndType(pool, name, spec)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int addMethodRef(List<PoolEntry> pool,
|
||||||
|
String className,
|
||||||
|
String name,
|
||||||
|
String spec)
|
||||||
|
{
|
||||||
|
return add(pool, new MethodRefPoolEntry
|
||||||
|
(addClass(pool, className),
|
||||||
|
addNameAndType(pool, name, spec)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface PoolEntry {
|
||||||
|
public void writeTo(OutputStream out) throws IOException;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class IntegerPoolEntry implements PoolEntry {
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
public IntegerPoolEntry(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeTo(OutputStream out) throws IOException {
|
||||||
|
write1(out, CONSTANT_Integer);
|
||||||
|
write4(out, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
return o instanceof IntegerPoolEntry
|
||||||
|
&& ((IntegerPoolEntry) o).value == value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Utf8PoolEntry implements PoolEntry {
|
||||||
|
private final String data;
|
||||||
|
|
||||||
|
public Utf8PoolEntry(String data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeTo(OutputStream out) throws IOException {
|
||||||
|
write1(out, CONSTANT_Utf8);
|
||||||
|
byte[] bytes = data.getBytes();
|
||||||
|
write2(out, bytes.length);
|
||||||
|
out.write(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
return o instanceof Utf8PoolEntry
|
||||||
|
&& ((Utf8PoolEntry) o).data.equals(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class StringPoolEntry implements PoolEntry {
|
||||||
|
private final int valueIndex;
|
||||||
|
|
||||||
|
public StringPoolEntry(int valueIndex) {
|
||||||
|
this.valueIndex = valueIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeTo(OutputStream out) throws IOException {
|
||||||
|
write1(out, CONSTANT_String);
|
||||||
|
write2(out, valueIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
return o instanceof StringPoolEntry
|
||||||
|
&& ((StringPoolEntry) o).valueIndex == valueIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ClassPoolEntry implements PoolEntry {
|
||||||
|
private final int nameIndex;
|
||||||
|
|
||||||
|
public ClassPoolEntry(int nameIndex) {
|
||||||
|
this.nameIndex = nameIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeTo(OutputStream out) throws IOException {
|
||||||
|
write1(out, CONSTANT_Class);
|
||||||
|
write2(out, nameIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
return o instanceof ClassPoolEntry
|
||||||
|
&& ((ClassPoolEntry) o).nameIndex == nameIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class NameAndTypePoolEntry implements PoolEntry {
|
||||||
|
private final int nameIndex;
|
||||||
|
private final int typeIndex;
|
||||||
|
|
||||||
|
public NameAndTypePoolEntry(int nameIndex, int typeIndex) {
|
||||||
|
this.nameIndex = nameIndex;
|
||||||
|
this.typeIndex = typeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeTo(OutputStream out) throws IOException {
|
||||||
|
write1(out, CONSTANT_NameAndType);
|
||||||
|
write2(out, nameIndex + 1);
|
||||||
|
write2(out, typeIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o instanceof NameAndTypePoolEntry) {
|
||||||
|
NameAndTypePoolEntry other = (NameAndTypePoolEntry) o;
|
||||||
|
return other.nameIndex == nameIndex && other.typeIndex == typeIndex;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class FieldRefPoolEntry implements PoolEntry {
|
||||||
|
private final int classIndex;
|
||||||
|
private final int nameAndTypeIndex;
|
||||||
|
|
||||||
|
public FieldRefPoolEntry(int classIndex, int nameAndTypeIndex) {
|
||||||
|
this.classIndex = classIndex;
|
||||||
|
this.nameAndTypeIndex = nameAndTypeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeTo(OutputStream out) throws IOException {
|
||||||
|
write1(out, CONSTANT_Fieldref);
|
||||||
|
write2(out, classIndex + 1);
|
||||||
|
write2(out, nameAndTypeIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o instanceof FieldRefPoolEntry) {
|
||||||
|
FieldRefPoolEntry other = (FieldRefPoolEntry) o;
|
||||||
|
return other.classIndex == classIndex
|
||||||
|
&& other.nameAndTypeIndex == nameAndTypeIndex;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MethodRefPoolEntry implements PoolEntry {
|
||||||
|
private final int classIndex;
|
||||||
|
private final int nameAndTypeIndex;
|
||||||
|
|
||||||
|
public MethodRefPoolEntry(int classIndex, int nameAndTypeIndex) {
|
||||||
|
this.classIndex = classIndex;
|
||||||
|
this.nameAndTypeIndex = nameAndTypeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeTo(OutputStream out) throws IOException {
|
||||||
|
write1(out, CONSTANT_Methodref);
|
||||||
|
write2(out, classIndex + 1);
|
||||||
|
write2(out, nameAndTypeIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o instanceof MethodRefPoolEntry) {
|
||||||
|
MethodRefPoolEntry other = (MethodRefPoolEntry) o;
|
||||||
|
return other.classIndex == classIndex
|
||||||
|
&& other.nameAndTypeIndex == nameAndTypeIndex;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
327
sgx-jvm/avian/classpath/avian/Continuations.java
Normal file
327
sgx-jvm/avian/classpath/avian/Continuations.java
Normal file
@ -0,0 +1,327 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class provides methods to capture continuations and manage
|
||||||
|
* control flow when calling continuations.
|
||||||
|
*
|
||||||
|
* <p>A continuation is a snapshot of a thread's call stack which can
|
||||||
|
* be captured via <code>callWithCurrentContinuation</code> and later
|
||||||
|
* restored any number of times. The program may restore this
|
||||||
|
* snapshot by either feeding it a result (to be returned by
|
||||||
|
* <code>callWithCurrentContinuation</code>) or feeding it an
|
||||||
|
* exception (to be thrown by
|
||||||
|
* <code>callWithCurrentContinuation</code>). Continuations may be
|
||||||
|
* used to implement features such as coroutines, generators, and
|
||||||
|
* cooperative multitasking.
|
||||||
|
*
|
||||||
|
* <p>This class provides two static methods,
|
||||||
|
* <code>callWithCurrentContinuation</code> and
|
||||||
|
* <code>dynamicWind</code>, with similar semantics to the Scheme
|
||||||
|
* functions <code>call-with-current-continuation</code> and
|
||||||
|
* <code>dynamic-wind</code>, respectively. In addition, we define
|
||||||
|
* how continuations work with respect to native code, exceptions,
|
||||||
|
* try/finally blocks, synchronized blocks, and multithreading.
|
||||||
|
*
|
||||||
|
* <h3>Continuations and Continuation Contexts</h3>
|
||||||
|
*
|
||||||
|
* <p>A continuation can be thought of as a singly-linked list of
|
||||||
|
* stack frames representing the call trace, where the head of the
|
||||||
|
* list is the frame of the method most recently called (i.e. the top
|
||||||
|
* of the stack). However, this trace only extends as far as the most
|
||||||
|
* recent chain of Java frames - it ends just prior to the most recent
|
||||||
|
* native frame in the stack. The reason for this is that the VM
|
||||||
|
* cannot, in general, safely capture and restore native frames.
|
||||||
|
* Therefore, each call from native code to Java (including the
|
||||||
|
* original invocation of <code>main(String[])</code> or
|
||||||
|
* <code>Thread.run()</code>) represents a new continuation context in
|
||||||
|
* which continuations may be captured, and these will only contain
|
||||||
|
* frames from within that context.
|
||||||
|
*
|
||||||
|
* <p>Calling a continuation (i.e. feeding it a result or exception)
|
||||||
|
* causes the current continuation to be replaced with the called
|
||||||
|
* continuation. When the last method in this new continuation
|
||||||
|
* returns, it returns to the native frame which created the current
|
||||||
|
* context, which may or may not be the same as the context in which
|
||||||
|
* that continuation was created.
|
||||||
|
*
|
||||||
|
* <p>We define the return type of a continuation context as the
|
||||||
|
* return type of the first method called in that context. A
|
||||||
|
* continuation may be called from a different context than the one in
|
||||||
|
* which it was created, provided the return type of the latter is
|
||||||
|
* compatible with the current context.
|
||||||
|
*
|
||||||
|
* <p>Given a thread executing in context "A" which wants to call a
|
||||||
|
* continuation created in context "B", the following rules apply:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
*
|
||||||
|
* <li>If the return type of "A" is <code>void</code>, the return
|
||||||
|
* type of "B" may be anything, including <code>void</code></li>
|
||||||
|
*
|
||||||
|
* <li>If the return type of "A" is a primitive type, the return
|
||||||
|
* type of "B" must match exactly</li>
|
||||||
|
*
|
||||||
|
* <li>If the return type of "A" is an object type, that type must
|
||||||
|
* be assignable from the return type of "B" (i.e. the latter must
|
||||||
|
* either be the same as the former or a superclass or
|
||||||
|
* superinterface of it)</li>
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>A thread may call a continuation created by a different thread
|
||||||
|
* provided the return types are compatible. Multiple threads may
|
||||||
|
* safely call the same continuation simultaneously without
|
||||||
|
* synchronization. Any attempt to call a continuation from a context
|
||||||
|
* with an incompatible return type will throw an {@link
|
||||||
|
* avian.IncompatibleContinuationException}.
|
||||||
|
*
|
||||||
|
* <h3>Winding, Unwinding, and Rewinding</h3>
|
||||||
|
*
|
||||||
|
* <p>Traditionally, Java provides one way to wind the execution stack
|
||||||
|
* (method calls) and two ways to unwind it (normal returns and
|
||||||
|
* exception unwinding). With continuations, we add a new way to
|
||||||
|
* rewind the stack and a new way to unwind it.
|
||||||
|
*
|
||||||
|
* <p>The call stack of a continuation may share frames with other
|
||||||
|
* continuations - in which case they share a common history. When
|
||||||
|
* calling a continuation "B" from the current continuation "A", the
|
||||||
|
* VM must unwind past any frames which are in "A" but not in "B" and
|
||||||
|
* rewind past any frames in "B" but not in "A". During this
|
||||||
|
* unwinding and rewinding, control may pass through synchronized and
|
||||||
|
* try/finally blocks while going down the old stack and up the new
|
||||||
|
* stack.
|
||||||
|
*
|
||||||
|
* <p>However, unlike the traditional processes of winding and
|
||||||
|
* unwinding, the VM will ignore these blocks - monitors will not be
|
||||||
|
* released or acquired and finally blocks will not execute. This is
|
||||||
|
* by design. The purpose of such a block is to acquire a resource,
|
||||||
|
* such as a file handle or monitor, once before executing a task and
|
||||||
|
* release it after the task is finished, regardless of how often the
|
||||||
|
* task might temporarily yield control to other continuations.
|
||||||
|
*
|
||||||
|
* <p>Alternatively, one might wish to acquire and release a resource
|
||||||
|
* each time control (re)winds to or unwinds from a continuation,
|
||||||
|
* respectively. In this case, one may use <code>dynamicWind</code>
|
||||||
|
* to register functions which will run every time that frame is
|
||||||
|
* passed, regardless of how the stack is wound or unwound.
|
||||||
|
*/
|
||||||
|
public class Continuations {
|
||||||
|
private Continuations() { }
|
||||||
|
|
||||||
|
private static final ThreadLocal<Reset> latestReset = new ThreadLocal();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Captures the current continuation, passing a reference to the
|
||||||
|
* specified receiver.
|
||||||
|
*
|
||||||
|
* <p>This method will either return the result returned by
|
||||||
|
* <code>receiver.call(Callback)</code>, propagate the exception
|
||||||
|
* thrown by that method, return the result passed to the
|
||||||
|
* handleResult(T) method of the continuation, or throw the
|
||||||
|
* exception passed to the handleException(Throwable) method of the
|
||||||
|
* continuation.
|
||||||
|
*/
|
||||||
|
public static native <T> T callWithCurrentContinuation
|
||||||
|
(Function<Callback<T>,T> receiver) throws Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls the specified "before" and "after" tasks each time a
|
||||||
|
* continuation containing the call is wound or unwound,
|
||||||
|
* respectively.
|
||||||
|
*
|
||||||
|
* <p>This method first calls <code>before.run()</code>, then
|
||||||
|
* <code>thunk.call()</code>, and finally <code>after.run()</code>,
|
||||||
|
* returning the result of the second call. If
|
||||||
|
* <code>before.run()</code> does not return normally, the second
|
||||||
|
* and third calls will not happen. If <code>thunk.call()</code>
|
||||||
|
* throws an exception, <code>after.run()</code>, will be called
|
||||||
|
* before the exception is propagated.
|
||||||
|
*
|
||||||
|
* <p>If <code>thunk.call()</code> calls a continuation (directly or
|
||||||
|
* via a subroutine) which does not include the current call to
|
||||||
|
* <code>dynamicWind</code>, <code>after.run()</code> will be called
|
||||||
|
* before control passes to that continuation. If this call throws
|
||||||
|
* an exception, the exception will propagate to the current caller
|
||||||
|
* of <code>dynamicWind</code>.
|
||||||
|
*
|
||||||
|
* <p>If <code>thunk.call()</code> creates a continuation which is
|
||||||
|
* later called from a continuation which does not include the
|
||||||
|
* current call to <code>dynamicWind</code>,
|
||||||
|
* <code>before.run()</code> will be called before control passes to
|
||||||
|
* that continuation. As above, if this call throws an exception,
|
||||||
|
* the exception will propagate to the current caller of
|
||||||
|
* <code>dynamicWind</code>.
|
||||||
|
*/
|
||||||
|
public static <T> T dynamicWind(Runnable before,
|
||||||
|
Callable<T> thunk,
|
||||||
|
Runnable after)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
UnwindResult result = dynamicWind2(before, thunk, after);
|
||||||
|
if (result.continuation != null) {
|
||||||
|
after.run();
|
||||||
|
if (result.exception != null) {
|
||||||
|
result.continuation.handleException(result.exception);
|
||||||
|
} else {
|
||||||
|
result.continuation.handleResult(result.result);
|
||||||
|
}
|
||||||
|
throw new AssertionError();
|
||||||
|
} else {
|
||||||
|
return (T) result.result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <B,C> C reset(final Callable<B> thunk) throws Exception {
|
||||||
|
final Reset reset = new Reset(latestReset.get());
|
||||||
|
latestReset.set(reset);
|
||||||
|
try {
|
||||||
|
Object result = callWithCurrentContinuation
|
||||||
|
(new Function<Callback<Object>,Object>() {
|
||||||
|
public Object call(Callback continuation) throws Exception {
|
||||||
|
reset.continuation = continuation;
|
||||||
|
return thunk.call();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
Cell<Function> shift = reset.shifts;
|
||||||
|
if (shift != null) {
|
||||||
|
reset.shifts = shift.next;
|
||||||
|
result = shift.value.call(result);
|
||||||
|
} else {
|
||||||
|
return (C) result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
latestReset.set(reset.next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <A,B,C> A shift
|
||||||
|
(final Function<Function<A,B>,C> receiver)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
return (A) callWithCurrentContinuation
|
||||||
|
(new Function<Callback<Object>,Object>() {
|
||||||
|
public Object call(final Callback continuation) {
|
||||||
|
final Reset reset = latestReset.get();
|
||||||
|
reset.shifts = new Cell(new Function() {
|
||||||
|
public Object call(Object ignored) throws Exception {
|
||||||
|
return receiver.call
|
||||||
|
(new Function() {
|
||||||
|
public Object call(final Object argument)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
return callWithCurrentContinuation
|
||||||
|
(new Function<Callback<Object>,Object>() {
|
||||||
|
public Object call
|
||||||
|
(final Callback shiftContinuation)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
reset.shifts = new Cell
|
||||||
|
(new Function() {
|
||||||
|
public Object call(Object result)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
shiftContinuation.handleResult(result);
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
reset.shifts);
|
||||||
|
|
||||||
|
continuation.handleResult(argument);
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleException(Throwable exception) {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
}, reset.shifts);
|
||||||
|
|
||||||
|
reset.continuation.handleResult(null);
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native UnwindResult dynamicWind2(Runnable before,
|
||||||
|
Callable thunk,
|
||||||
|
Runnable after)
|
||||||
|
throws Exception;
|
||||||
|
|
||||||
|
private static UnwindResult wind(Runnable before,
|
||||||
|
Callable thunk,
|
||||||
|
Runnable after)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
before.run();
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new UnwindResult(null, thunk.call(), null);
|
||||||
|
} finally {
|
||||||
|
after.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void rewind(Runnable before,
|
||||||
|
Callback continuation,
|
||||||
|
Object result,
|
||||||
|
Throwable exception)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
before.run();
|
||||||
|
|
||||||
|
if (exception != null) {
|
||||||
|
continuation.handleException(exception);
|
||||||
|
} else {
|
||||||
|
continuation.handleResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Continuation<T> implements Callback<T> {
|
||||||
|
public native void handleResult(T result);
|
||||||
|
public native void handleException(Throwable exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class UnwindResult {
|
||||||
|
public final Continuation continuation;
|
||||||
|
public final Object result;
|
||||||
|
public final Throwable exception;
|
||||||
|
|
||||||
|
public UnwindResult(Continuation continuation, Object result,
|
||||||
|
Throwable exception)
|
||||||
|
{
|
||||||
|
this.continuation = continuation;
|
||||||
|
this.result = result;
|
||||||
|
this.exception = exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Reset {
|
||||||
|
public Callback continuation;
|
||||||
|
public final Reset next;
|
||||||
|
public Cell<Function> shifts;
|
||||||
|
|
||||||
|
public Reset(Reset next) {
|
||||||
|
this.next = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
310
sgx-jvm/avian/classpath/avian/Data.java
Normal file
310
sgx-jvm/avian/classpath/avian/Data.java
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.AbstractSet;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
public class Data {
|
||||||
|
public static int nextPowerOfTwo(int n) {
|
||||||
|
int r = 1;
|
||||||
|
while (r < n) r <<= 1;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <V> boolean equal(V a, V b) {
|
||||||
|
return a == null ? b == null : a.equals(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T[] toArray(Collection collection, T[] array) {
|
||||||
|
Class c = array.getClass().getComponentType();
|
||||||
|
|
||||||
|
if (array.length < collection.size()) {
|
||||||
|
array = (T[]) java.lang.reflect.Array.newInstance(c, collection.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (Object o: collection) {
|
||||||
|
if (c.isInstance(o)) {
|
||||||
|
array[i++] = (T) o;
|
||||||
|
} else {
|
||||||
|
throw new ArrayStoreException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toString(Collection c) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("[");
|
||||||
|
for (Iterator it = c.iterator(); it.hasNext();) {
|
||||||
|
sb.append(it.next());
|
||||||
|
if (it.hasNext()) {
|
||||||
|
sb.append(",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append("]");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toString(Map m) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("{");
|
||||||
|
for (Iterator<Entry> it = m.entrySet().iterator(); it.hasNext();) {
|
||||||
|
Entry e = it.next();
|
||||||
|
sb.append(e.getKey())
|
||||||
|
.append("=")
|
||||||
|
.append(e.getValue());
|
||||||
|
if (it.hasNext()) {
|
||||||
|
sb.append(",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append("}");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface EntryMap<K,V> {
|
||||||
|
public int size();
|
||||||
|
|
||||||
|
public Entry<K,V> find(Object key);
|
||||||
|
|
||||||
|
public Entry<K,V> remove(Object key);
|
||||||
|
|
||||||
|
public void clear();
|
||||||
|
|
||||||
|
public Iterator<Entry<K,V>> iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class EntrySet<K, V> extends AbstractSet<Entry<K, V>> {
|
||||||
|
private final EntryMap<K, V> map;
|
||||||
|
|
||||||
|
public EntrySet(EntryMap<K, V> map) {
|
||||||
|
this.map = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return map.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return map.size() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(Object o) {
|
||||||
|
return (o instanceof Entry<?,?>)
|
||||||
|
&& map.find(((Entry<?,?>)o).getKey()) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean add(Entry<K, V> e) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean remove(Object o) {
|
||||||
|
return (o instanceof Entry<?,?>)
|
||||||
|
&& map.remove(((Entry<?,?>) o).getKey()) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean remove(Entry<K, V> e) {
|
||||||
|
return map.remove(e.getKey()) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] toArray() {
|
||||||
|
return toArray(new Object[size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T[] toArray(T[] array) {
|
||||||
|
return Data.toArray(this, array);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator<Entry<K, V>> iterator() {
|
||||||
|
return map.iterator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class KeySet<K> extends AbstractSet<K> {
|
||||||
|
private final EntryMap<K, ?> map;
|
||||||
|
|
||||||
|
public KeySet(EntryMap<K, ?> map) {
|
||||||
|
this.map = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return map.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return map.size() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(Object key) {
|
||||||
|
return map.find(key) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean add(K key) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean remove(Object key) {
|
||||||
|
return map.remove(key) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] toArray() {
|
||||||
|
return toArray(new Object[size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T[] toArray(T[] array) {
|
||||||
|
return Data.toArray(this, array);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator<K> iterator() {
|
||||||
|
return new KeyIterator(map.iterator());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Values<K, V> implements Collection<V> {
|
||||||
|
private final EntryMap<K, V> map;
|
||||||
|
|
||||||
|
public Values(EntryMap<K, V> map) {
|
||||||
|
this.map = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return map.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return map.size() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(Object value) {
|
||||||
|
for (Iterator<Entry<K, V>> it = map.iterator(); it.hasNext();) {
|
||||||
|
if (equal(it.next().getValue(), value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsAll(Collection<?> c) {
|
||||||
|
if (c == null) {
|
||||||
|
throw new NullPointerException("collection is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Iterator<?> it = c.iterator(); it.hasNext();) {
|
||||||
|
if (! contains(it.next())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean add(V value) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean addAll(Collection<? extends V> collection) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean remove(Object value) {
|
||||||
|
for (Iterator<Entry<K, V>> it = map.iterator();
|
||||||
|
it.hasNext();)
|
||||||
|
{
|
||||||
|
if (equal(it.next().getValue(), value)) {
|
||||||
|
it.remove();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeAll(Collection<?> c) {
|
||||||
|
boolean changed = false;
|
||||||
|
for (Iterator<Entry<K, V>> it = map.iterator(); it.hasNext();) {
|
||||||
|
if (c.contains(it.next().getValue())) {
|
||||||
|
it.remove();
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] toArray() {
|
||||||
|
return toArray(new Object[size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T[] toArray(T[] array) {
|
||||||
|
return Data.toArray(this, array);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator<V> iterator() {
|
||||||
|
return new ValueIterator(map.iterator());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class KeyIterator<K, V> implements Iterator<K> {
|
||||||
|
private final Iterator<Entry<K, V>> it;
|
||||||
|
|
||||||
|
public KeyIterator(Iterator<Entry<K, V>> it) {
|
||||||
|
this.it = it;
|
||||||
|
}
|
||||||
|
|
||||||
|
public K next() {
|
||||||
|
return it.next().getKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasNext() {
|
||||||
|
return it.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove() {
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ValueIterator<K, V> implements Iterator<V> {
|
||||||
|
private final Iterator<Entry<K, V>> it;
|
||||||
|
|
||||||
|
public ValueIterator(Iterator<Entry<K, V>> it) {
|
||||||
|
this.it = it;
|
||||||
|
}
|
||||||
|
|
||||||
|
public V next() {
|
||||||
|
return it.next().getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasNext() {
|
||||||
|
return it.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove() {
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
sgx-jvm/avian/classpath/avian/FieldAddendum.java
Normal file
13
sgx-jvm/avian/classpath/avian/FieldAddendum.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class FieldAddendum extends Addendum { }
|
992
sgx-jvm/avian/classpath/avian/FormatString.java
Normal file
992
sgx-jvm/avian/classpath/avian/FormatString.java
Normal file
@ -0,0 +1,992 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.IllegalFormatException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------- //
|
||||||
|
// things that must be done in order to call this semi-complete:
|
||||||
|
// ------------------------------------------------------------------------- //
|
||||||
|
// * get the date formatter working for individual fields at a minimum
|
||||||
|
// ------------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Java flavored printf for classpath-challenged JVMs.
|
||||||
|
*
|
||||||
|
* Each instance of this class is a threadsafe pre-parsed format pattern. Refer
|
||||||
|
* to the very detailed class description of java.util.Formatter in the OpenJDK
|
||||||
|
* API documentation for an explanation of the supported formats.
|
||||||
|
*
|
||||||
|
* Should be easily portable to other Java runtimes that do not include the
|
||||||
|
* printf functionality that was introduced in Java 5.
|
||||||
|
*
|
||||||
|
* Aims to be lightweight and reasonably fast, and provide reasonably complete
|
||||||
|
* API compatibility with the OpenJDK implementation. To clarify what
|
||||||
|
* "reasonably complete" means in this context, this implementation should
|
||||||
|
* accept any valid format string that the OpenJDK version accepts. However,
|
||||||
|
* it should not be relied upon to throw an Exception for every format pattern
|
||||||
|
* that the OpenJDK implementation does.
|
||||||
|
*
|
||||||
|
* If your program's behavior relies on the side effects from an Exception
|
||||||
|
* being thrown for an invalid format string, this might not be for you.
|
||||||
|
*
|
||||||
|
* Perhaps more troubling is the fact that the correct localization of numbers
|
||||||
|
* and temporal values is barely even attempted, even though the parser accepts
|
||||||
|
* the flags without even a warning. However, now you have been warned.
|
||||||
|
*
|
||||||
|
* @author bcg
|
||||||
|
*/
|
||||||
|
public final class FormatString {
|
||||||
|
|
||||||
|
/** Parses a format string and returns a compiled representation of it. */
|
||||||
|
public static final FormatString compile(String fmt) {
|
||||||
|
return new FormatString(fmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The original string value that was parsed */
|
||||||
|
public String source() {
|
||||||
|
return _source;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Processes the supplied arguments through the compiled format string
|
||||||
|
and returns the result as a String. */
|
||||||
|
public final String format(Object... args) {
|
||||||
|
final StringBuilder bldr = new StringBuilder();
|
||||||
|
try {
|
||||||
|
format(bldr, args);
|
||||||
|
return bldr.toString();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Should not get IOException when writing to StringBuilder", e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Processes the supplied arguments through the compiled format string
|
||||||
|
and writes the result of each component directly to an Appendable */
|
||||||
|
public final void format(final Appendable a, Object... fmt_args)
|
||||||
|
throws IOException {
|
||||||
|
final Object[] args = fmt_args != null ? fmt_args : new Object[0];
|
||||||
|
int cntr = 0;
|
||||||
|
for (final FmtCmpnt cmp : _components) {
|
||||||
|
if (cmp._conversion == CONV_LITRL) {
|
||||||
|
a.append(cmp._source);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final Object arg;
|
||||||
|
if (!acceptsArgument(cmp._conversion)) {
|
||||||
|
arg = null;
|
||||||
|
} else {
|
||||||
|
final int index = cmp._argument_index;
|
||||||
|
switch (index) {
|
||||||
|
case AIDX_NONE:
|
||||||
|
if ((cntr) >= args.length) {
|
||||||
|
throw new IllegalFormatException(
|
||||||
|
"Format specified at least " + (cntr+1) +
|
||||||
|
" arguments, but " + cntr + " were supplied."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
arg = args[cntr++];
|
||||||
|
break;
|
||||||
|
case AIDX_PREV:
|
||||||
|
arg = args[cntr];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (index < 1) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
} else if (index > args.length) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
} else {
|
||||||
|
arg = args[index - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
convert(a, arg, cmp._conversion, cmp._flags, cmp._width, cmp._precision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- conversions
|
||||||
|
static final byte CONV_LITRL = 0x0;
|
||||||
|
static final byte CONV_NLINE = 0x1;
|
||||||
|
static final byte CONV_PRCNT = 0x2;
|
||||||
|
static final byte CONV_BOOLN = 0x3;
|
||||||
|
static final byte CONV_DTIME = 0x4;
|
||||||
|
static final byte CONV_STRNG = 0x5;
|
||||||
|
static final byte CONV_HCODE = 0x6;
|
||||||
|
static final byte CONV_CHRCT = 0x7;
|
||||||
|
static final byte CONV_DECML = 0x8;
|
||||||
|
static final byte CONV_OCTAL = 0x9;
|
||||||
|
static final byte CONV_HXDEC = 0xA;
|
||||||
|
static final byte CONV_CPSCI = 0xB;
|
||||||
|
static final byte CONV_GNSCI = 0xC;
|
||||||
|
static final byte CONV_FLOAT = 0xD;
|
||||||
|
static final byte CONV_HXEXP = 0xE;
|
||||||
|
|
||||||
|
//- format component flags
|
||||||
|
static final byte FLAG_FORCE_UPPER_CASE = (byte)(1<<7);
|
||||||
|
static final byte FLAG_NEGATIVES_IN_PARENS = (byte)(1<<6); // ('(')
|
||||||
|
static final byte FLAG_GROUPING_SEPARATORS = (byte)(1<<5); // (',')
|
||||||
|
static final byte FLAG_LEADING_ZERO_PADDED = (byte)(1<<4); // ('0')
|
||||||
|
static final byte FLAG_LEADING_SPACE_PADDED = (byte)(1<<3); // (' ')
|
||||||
|
static final byte FLAG_ALWAYS_INCLUDES_SIGN = (byte)(1<<2); // ('+')
|
||||||
|
static final byte FLAG_ALTERNATE_FORM = (byte)(1<<1); // ('#')
|
||||||
|
static final byte FLAG_LEFT_JUSTIFIED = (byte)(1<<0); // ('-')
|
||||||
|
|
||||||
|
//- conversion capability flags
|
||||||
|
static final byte CFLG_WDTH_SUPPRT = CONV_PRCNT;
|
||||||
|
static final byte CFLG_ACCEPTS_ARG = CONV_BOOLN;
|
||||||
|
static final byte CFLG_NUMERIC_VAL = CONV_DECML;
|
||||||
|
static final byte CFLG_PREC_SUPPRT = CONV_STRNG;
|
||||||
|
|
||||||
|
//- special argument indices
|
||||||
|
static final int AIDX_PREV = -1;
|
||||||
|
static final int AIDX_NONE = 0;
|
||||||
|
|
||||||
|
/** the original serialized format string */
|
||||||
|
private final String _source;
|
||||||
|
|
||||||
|
/** array of components parsed from the source string */
|
||||||
|
private final FmtCmpnt[] _components;
|
||||||
|
|
||||||
|
/*/ keeping this private for now to encourage access through the static
|
||||||
|
compile method, which might allow caching format string instances if it
|
||||||
|
turns out there is an advantage to that. /*/
|
||||||
|
/** Constructor */
|
||||||
|
private FormatString(final String fmt) {
|
||||||
|
this._source = fmt;
|
||||||
|
final List<FmtCmpnt> cmps = new ArrayList<FmtCmpnt>();
|
||||||
|
for ( int i = 0; (i = next(fmt, cmps, i)) > -1; );
|
||||||
|
this._components = cmps.toArray(new FmtCmpnt[cmps.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Iterates over the tokens in an input string to extract the components */
|
||||||
|
private static final int next(
|
||||||
|
final String fmt, final List<FmtCmpnt> cmps, final int startIndex) {
|
||||||
|
final int strln = fmt.length();
|
||||||
|
if (startIndex >= strln) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
final char c = fmt.charAt(startIndex);
|
||||||
|
if (c == '%') {
|
||||||
|
// this is the start of a specifier
|
||||||
|
final FmtSpecBldr bldr = new FmtSpecBldr();
|
||||||
|
for (int i = startIndex + 1; i < strln; i++) {
|
||||||
|
final char ch = fmt.charAt(i);
|
||||||
|
final FmtCmpnt cmp = bldr.append(ch);
|
||||||
|
if (cmp != null) {
|
||||||
|
cmps.add(cmp);
|
||||||
|
return (i+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalFormatException("Incomplete specifier at end of fmt");
|
||||||
|
} else {
|
||||||
|
// this is the start of a literal
|
||||||
|
final StringBuilder literal = new StringBuilder();
|
||||||
|
literal.append(c);
|
||||||
|
for (int i = startIndex + 1; i < strln; i++) {
|
||||||
|
final char ch = fmt.charAt(i);
|
||||||
|
// write the current buffer if the next character starts a specifier
|
||||||
|
if (ch == '%') {
|
||||||
|
final FmtCmpnt cmp = new FmtCmpnt(literal.toString());
|
||||||
|
cmps.add(cmp);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
literal.append(ch);
|
||||||
|
}
|
||||||
|
// write the current buffer if the end of the format has been reached
|
||||||
|
final FmtCmpnt cmp = new FmtCmpnt(literal.toString());
|
||||||
|
cmps.add(cmp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks a flag byte to see if a given flag is set. Only FLAG_* constants
|
||||||
|
from the enclosing class should be passed in for toCheck... otherwise the
|
||||||
|
behavior is undefined. */
|
||||||
|
static final boolean checkFlag(final byte flags, final byte toCheck) {
|
||||||
|
return (flags & toCheck) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks if a given conversion accepts(requires) an argument. Only the CONV_
|
||||||
|
flags from the enclosing class should be passed in, otherwise the result
|
||||||
|
of this method is undefined as should not be used. */
|
||||||
|
static final boolean acceptsArgument(final byte conversion) {
|
||||||
|
return conversion >= CFLG_ACCEPTS_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks if a given conversion allows specifying a precision. Only the CONV_
|
||||||
|
flags from the enclosing class should be passed in, otherwise the result
|
||||||
|
of this method is undefined as should not be used. */
|
||||||
|
static final boolean precisionSupported(final byte conversion) {
|
||||||
|
return conversion >= CFLG_PREC_SUPPRT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks if a given conversion allows specifying a width. Only the CONV_
|
||||||
|
flags from the enclosing class should be passed in, otherwise the result
|
||||||
|
of this method is undefined and should not be trusted. */
|
||||||
|
static final boolean widthSupported(final byte conversion) {
|
||||||
|
return conversion >= CFLG_WDTH_SUPPRT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks if a given conversion expects a numeric value. Only the CONV_
|
||||||
|
flags from the enclosing class should be passed in, otherwise the result
|
||||||
|
of this method is undefined and should not be trusted. */
|
||||||
|
static final boolean isNumeric(final byte conversion) {
|
||||||
|
return conversion >= CFLG_NUMERIC_VAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The newline character for the current platform. */
|
||||||
|
static final String NEWLINE = System.getProperty("line.separator");
|
||||||
|
|
||||||
|
/** Performs conversion on the supplied argument */
|
||||||
|
static final void convert(
|
||||||
|
final Appendable appendable,
|
||||||
|
final Object arg,
|
||||||
|
final byte conversion,
|
||||||
|
final byte flags,
|
||||||
|
final int width,
|
||||||
|
final int precision) throws IOException {
|
||||||
|
int radix = 0;
|
||||||
|
switch (conversion) {
|
||||||
|
case CONV_LITRL:
|
||||||
|
throw new IllegalArgumentException("cannot convert a literal");
|
||||||
|
case CONV_NLINE:
|
||||||
|
appendable.append(NEWLINE);
|
||||||
|
return;
|
||||||
|
case CONV_PRCNT:
|
||||||
|
convertPercent(appendable, arg, flags, width, precision);
|
||||||
|
return;
|
||||||
|
case CONV_BOOLN:
|
||||||
|
convertBoolean(appendable, arg, flags, width, precision);
|
||||||
|
return;
|
||||||
|
case CONV_DTIME:
|
||||||
|
convertDate(appendable, arg, flags, width, precision);
|
||||||
|
return;
|
||||||
|
case CONV_STRNG:
|
||||||
|
convertString(appendable, arg, flags, width, precision);
|
||||||
|
return;
|
||||||
|
case CONV_HCODE:
|
||||||
|
convertHashcode(appendable, arg, flags, width, precision);
|
||||||
|
return;
|
||||||
|
case CONV_CHRCT:
|
||||||
|
convertChar(appendable, arg, flags, width, precision);
|
||||||
|
return;
|
||||||
|
case CONV_DECML: if (radix == 0) { radix = 10; };
|
||||||
|
case CONV_OCTAL: if (radix == 0) { radix = 8; };
|
||||||
|
case CONV_HXDEC: if (radix == 0) { radix = 16; };
|
||||||
|
if (arg instanceof Long) {
|
||||||
|
convertLong(appendable, (Long) arg, flags, width, precision, radix);
|
||||||
|
} else {
|
||||||
|
convertInteger(appendable, arg, flags, width, precision, radix);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case CONV_CPSCI:
|
||||||
|
case CONV_GNSCI:
|
||||||
|
case CONV_FLOAT:
|
||||||
|
case CONV_HXEXP:
|
||||||
|
convertFloat(appendable, arg, flags, width, precision, 10);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new IllegalStateException("not implemented: " + conversion);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void convertPercent(
|
||||||
|
final Appendable a,
|
||||||
|
final Object arg,
|
||||||
|
final byte flags,
|
||||||
|
final int width,
|
||||||
|
final int precision) throws IOException {
|
||||||
|
final String val = "%";
|
||||||
|
appendify(a, val, flags, width, precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void convertDate(
|
||||||
|
final Appendable a,
|
||||||
|
final Object arg,
|
||||||
|
final byte flags,
|
||||||
|
final int width,
|
||||||
|
final int precision) throws IOException {
|
||||||
|
final String val = (arg == null) ? "null" : arg.toString();
|
||||||
|
appendify(a, val, flags, width, precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void convertString(
|
||||||
|
final Appendable a,
|
||||||
|
final Object arg,
|
||||||
|
final byte flags,
|
||||||
|
final int width,
|
||||||
|
final int precision) throws IOException {
|
||||||
|
final String val = (arg == null) ? "null" : arg.toString();
|
||||||
|
appendify(a, val, flags, width, precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void convertHashcode(
|
||||||
|
final Appendable a,
|
||||||
|
final Object arg,
|
||||||
|
final byte flags,
|
||||||
|
final int width,
|
||||||
|
final int precision) throws IOException {
|
||||||
|
final String val = (arg == null)
|
||||||
|
? "null"
|
||||||
|
: Integer.toHexString(arg.hashCode());
|
||||||
|
appendify(a, val, flags, width, precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void convertBoolean(
|
||||||
|
final Appendable a,
|
||||||
|
final Object arg,
|
||||||
|
final byte flags,
|
||||||
|
final int width,
|
||||||
|
final int precision) throws IOException {
|
||||||
|
final String val;
|
||||||
|
if (arg == null) {
|
||||||
|
val = "false";
|
||||||
|
} else if (arg instanceof Boolean) {
|
||||||
|
val = String.valueOf(arg);
|
||||||
|
} else {
|
||||||
|
val = "true";
|
||||||
|
}
|
||||||
|
appendify(a, val, flags, width, precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void convertChar(
|
||||||
|
final Appendable a,
|
||||||
|
final Object arg,
|
||||||
|
final byte flags,
|
||||||
|
final int width,
|
||||||
|
final int precision) throws IOException {
|
||||||
|
final String val;
|
||||||
|
if (arg instanceof Character) {
|
||||||
|
val = ((Character) arg).toString();
|
||||||
|
} else if ( arg instanceof Byte ||
|
||||||
|
arg instanceof Short ||
|
||||||
|
arg instanceof Integer ){
|
||||||
|
final int codePoint = ((Number) arg).intValue();
|
||||||
|
if (codePoint >= 0 && codePoint <= 0x10FFFF) { //<-- isValidCodePoint()?
|
||||||
|
val = new String(Character.toChars(codePoint));
|
||||||
|
} else {
|
||||||
|
throw new IllegalFormatException("Invalid code point: " + arg);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new IllegalFormatException("Cannot do char conversion: " + arg);
|
||||||
|
}
|
||||||
|
appendify(a, val, flags, width, precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: this is broken for octal formats with negative values
|
||||||
|
static void convertLong(
|
||||||
|
final Appendable a,
|
||||||
|
final Long arg,
|
||||||
|
final byte flags,
|
||||||
|
final int width,
|
||||||
|
final int precision,
|
||||||
|
final int radix) throws IOException {
|
||||||
|
final String val;
|
||||||
|
final Long n = arg;
|
||||||
|
final long longValue = n.longValue();
|
||||||
|
if (radix == 10 || longValue > -1) {
|
||||||
|
val = Long.toString(longValue, radix);
|
||||||
|
} else {
|
||||||
|
final long upper = 0xFFFFFFFFL&(longValue>>31);
|
||||||
|
final long lower = 0xFFFFFFFFL&(longValue);
|
||||||
|
val = Long.toString(upper, radix) + Long.toString(lower, radix);
|
||||||
|
}
|
||||||
|
appendify(a, val, flags, width, precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void convertInteger(
|
||||||
|
final Appendable a,
|
||||||
|
final Object arg,
|
||||||
|
final byte flags,
|
||||||
|
final int width,
|
||||||
|
final int precision,
|
||||||
|
final int radix) throws IOException {
|
||||||
|
final String val;
|
||||||
|
final Number n = (Number) arg;
|
||||||
|
final long longValue = n.longValue();
|
||||||
|
final long modifier;
|
||||||
|
if (arg instanceof Integer) modifier = 0xFFFFFFFFL+1; else
|
||||||
|
if (arg instanceof Short) modifier = 0xFFFFL+1; else
|
||||||
|
if (arg instanceof Byte) modifier = 0xFFL+1;
|
||||||
|
else throw new IllegalFormatException(
|
||||||
|
"not an integer number: " + (arg != null ? arg.getClass() : null)
|
||||||
|
);
|
||||||
|
if (radix != 10 && longValue < 0) {
|
||||||
|
val = Long.toString(longValue + modifier, radix);
|
||||||
|
} else {
|
||||||
|
val = Long.toString(longValue, radix);
|
||||||
|
}
|
||||||
|
appendify(a, val, flags, width, precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: I'm lazy, so hexidecimal exponential isn't implemented, sorry - bcg
|
||||||
|
static void convertFloat(
|
||||||
|
final Appendable a,
|
||||||
|
final Object arg,
|
||||||
|
final byte flags,
|
||||||
|
final int width,
|
||||||
|
final int precision,
|
||||||
|
final int radix) throws IOException {
|
||||||
|
final String val;
|
||||||
|
final Number n = (Number) arg;
|
||||||
|
if (arg instanceof Float) {
|
||||||
|
val = Float.toString(n.floatValue());
|
||||||
|
} else if (arg instanceof Double) {
|
||||||
|
val = Double.toString(n.doubleValue());
|
||||||
|
} else {
|
||||||
|
throw new IllegalFormatException(
|
||||||
|
"not a floating point number: " + (arg != null ? arg.getClass() : null)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
appendify(a, val, flags, width, precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void appendify(
|
||||||
|
final Appendable a,
|
||||||
|
final String val,
|
||||||
|
final byte flags,
|
||||||
|
final int width,
|
||||||
|
final int precision) throws IOException {
|
||||||
|
String result = val;
|
||||||
|
if (checkFlag(flags, FLAG_FORCE_UPPER_CASE)) {
|
||||||
|
result = result.toUpperCase();
|
||||||
|
}
|
||||||
|
// TODO: implement other flags
|
||||||
|
// (+) always include sign
|
||||||
|
// (,) grouping separators
|
||||||
|
// (() negatives in parentheses
|
||||||
|
if (precision > 0) {
|
||||||
|
// FIXME: this behavior should be different for floating point numbers
|
||||||
|
final int difference = result.length() - precision;
|
||||||
|
if (difference > 0) {
|
||||||
|
result = result.substring(0, precision);
|
||||||
|
a.append(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (width > 0) {
|
||||||
|
final int difference = width - result.length();
|
||||||
|
final boolean leftJustified = checkFlag(flags, FLAG_LEFT_JUSTIFIED);
|
||||||
|
if (!leftJustified && difference > 0) {
|
||||||
|
char fill = checkFlag(flags, FLAG_LEADING_ZERO_PADDED) ? '0' : ' ';
|
||||||
|
fill(a, difference, fill);
|
||||||
|
}
|
||||||
|
a.append(result);
|
||||||
|
if (leftJustified && difference > 0) {
|
||||||
|
fill(a, difference, ' ');
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
a.append(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void fill(Appendable a, int num, char c) throws IOException {
|
||||||
|
while (num > 0) {
|
||||||
|
a.append(c);
|
||||||
|
num--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Represents a single chunk of the format string, either a literal or one of
|
||||||
|
the specifiers documented in OpenJDK's javadoc for java.util.Formatter.
|
||||||
|
This struct is immutable so can be safely shared across threads. */
|
||||||
|
private static final class FmtCmpnt {
|
||||||
|
|
||||||
|
private final String _source;
|
||||||
|
private final byte _conversion;
|
||||||
|
private final int _argument_index;
|
||||||
|
private final int _width;
|
||||||
|
private final int _precision;
|
||||||
|
private final byte _flags;
|
||||||
|
|
||||||
|
private FmtCmpnt(final String literal) {
|
||||||
|
this(literal, CONV_LITRL, 0, 0, 0, (byte)0);
|
||||||
|
}
|
||||||
|
private FmtCmpnt(
|
||||||
|
final String src,
|
||||||
|
final byte conversion,
|
||||||
|
final int argumentIndex,
|
||||||
|
final int width,
|
||||||
|
final int precision,
|
||||||
|
final byte flags) {
|
||||||
|
this._source = src;
|
||||||
|
this._conversion = conversion;
|
||||||
|
this._argument_index = argumentIndex;
|
||||||
|
this._width = width;
|
||||||
|
this._precision = precision;
|
||||||
|
this._flags = flags;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("{ ")
|
||||||
|
.append("source = '").append(_source).append("', ")
|
||||||
|
.append("conversion = ").append(_conversion).append(", ")
|
||||||
|
.append("flags = ").append(Byte.toString(_flags, 2)).append(", ")
|
||||||
|
.append("arg_index = ").append(_argument_index).append(", ")
|
||||||
|
.append("width = ").append(_width).append(", ")
|
||||||
|
.append("precision = ").append(_precision).append(", ")
|
||||||
|
.append("}");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class for parsing a stream of characters into FmtCmpnt objects.
|
||||||
|
*/
|
||||||
|
private static final class FmtSpecBldr {
|
||||||
|
|
||||||
|
private StringBuilder _source;
|
||||||
|
private byte _conversion;
|
||||||
|
private int _argument_index;
|
||||||
|
private int _width;
|
||||||
|
private int _precision;
|
||||||
|
private byte _flags;
|
||||||
|
|
||||||
|
private FmtSpecBldr() {
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final void init() {
|
||||||
|
_argument_index =
|
||||||
|
_width =
|
||||||
|
_precision =
|
||||||
|
_conversion =
|
||||||
|
_flags = 0;
|
||||||
|
_source = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final FmtCmpnt build() {
|
||||||
|
final FmtCmpnt result = new FmtCmpnt(
|
||||||
|
_source.toString(),
|
||||||
|
_conversion,
|
||||||
|
_argument_index,
|
||||||
|
_width,
|
||||||
|
_precision,
|
||||||
|
_flags
|
||||||
|
);
|
||||||
|
init();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final FmtCmpnt append(char c) {
|
||||||
|
|
||||||
|
if (_source == null) {
|
||||||
|
_source = new StringBuilder();
|
||||||
|
}
|
||||||
|
_source.append(c);
|
||||||
|
|
||||||
|
// FIXME: none of these date formats are implemented, because lazy
|
||||||
|
// if a datetime is specified, after the conversion character a time
|
||||||
|
// format specifier is expected. This is the only case where a character
|
||||||
|
// is allowed after the conversion character.
|
||||||
|
if (_conversion == CONV_DTIME) switch (c) {
|
||||||
|
|
||||||
|
// Hour of the day for the 24-hour clock, formatted as two digits with a
|
||||||
|
// leading zero as necessary i.e. 00 - 23.
|
||||||
|
case 'H':
|
||||||
|
|
||||||
|
// Hour for the 12-hour clock, formatted as two digits with a leading
|
||||||
|
// zero as necessary, i.e. 01 - 12.
|
||||||
|
case 'I':
|
||||||
|
|
||||||
|
// Hour of the day for the 24-hour clock, i.e. 0 - 23.
|
||||||
|
case 'k':
|
||||||
|
|
||||||
|
// Hour for the 12-hour clock, i.e. 1 - 12.
|
||||||
|
case 'l':
|
||||||
|
|
||||||
|
// Minute within the hour formatted as two digits with a leading zero
|
||||||
|
// as necessary, i.e. 00 - 59.
|
||||||
|
case 'M':
|
||||||
|
|
||||||
|
// Seconds within the minute, formatted as two digits with a leading
|
||||||
|
// zero as necessary, i.e. 00 - 60 ("60" is a special value required to
|
||||||
|
// support leap seconds).
|
||||||
|
case 'S':
|
||||||
|
|
||||||
|
// Millisecond within the second formatted as three digits with leading
|
||||||
|
// zeros as necessary, i.e. 000 - 999.
|
||||||
|
case 'L':
|
||||||
|
|
||||||
|
// Nanosecond within the second, formatted as nine digits with leading
|
||||||
|
// zeros as necessary, i.e. 000000000 - 999999999.
|
||||||
|
case 'N':
|
||||||
|
|
||||||
|
// Locale-specific morning or afternoon marker in lower case,
|
||||||
|
// e.g."am" or "pm". Use of the conversion prefix 'T' forces this
|
||||||
|
// output to upper case.
|
||||||
|
case 'p':
|
||||||
|
|
||||||
|
// RFC 822 style numeric time zone offset from GMT, e.g. -0800.
|
||||||
|
case 'z':
|
||||||
|
|
||||||
|
// A string representing the abbreviation for the time zone. The
|
||||||
|
// Formatter's locale will supersede the locale of the argument
|
||||||
|
// (if any).
|
||||||
|
case 'Z':
|
||||||
|
|
||||||
|
// Seconds since the beginning of the epoch
|
||||||
|
// starting at 1 January 1970 00:00:00 UTC,
|
||||||
|
// i.e. Long.MIN_VALUE/1000 to Long.MAX_VALUE/1000.
|
||||||
|
case 's':
|
||||||
|
|
||||||
|
// Milliseconds since the beginning of the epoch
|
||||||
|
// starting at 1 January 1970 00:00:00 UTC,
|
||||||
|
// i.e. Long.MIN_VALUE to Long.MAX_VALUE.
|
||||||
|
case 'Q':
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// The following conversion characters are used for formatting dates:
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Locale-specific full month name, e.g. "January", "February".
|
||||||
|
case 'B':
|
||||||
|
|
||||||
|
// Locale-specific abbreviated month name, e.g. "Jan", "Feb".
|
||||||
|
case 'b':
|
||||||
|
|
||||||
|
// Same as 'b'.
|
||||||
|
case 'h':
|
||||||
|
|
||||||
|
// Locale-specific full name of the day of the week, e.g. "Sunday"
|
||||||
|
case 'A':
|
||||||
|
|
||||||
|
// Locale-specific short name of the day of the week, e.g. "Sun"
|
||||||
|
case 'a':
|
||||||
|
|
||||||
|
// Four-digit year divided by 100, formatted as two digits with leading
|
||||||
|
// zero as necessary, i.e. 00 - 99
|
||||||
|
case 'C':
|
||||||
|
|
||||||
|
// Year, formatted as at least four digits with leading zeros
|
||||||
|
// as necessary, e.g. 0092 equals 92 CE for the Gregorian calendar.
|
||||||
|
case 'Y':
|
||||||
|
|
||||||
|
// Last two digits of the year, formatted with leading zeros
|
||||||
|
// as necessary, i.e. 00 - 99.
|
||||||
|
case 'y':
|
||||||
|
|
||||||
|
// Day of year, formatted as three digits with leading zeros
|
||||||
|
// as necessary, e.g. 001 - 366 for the Gregorian calendar.
|
||||||
|
case 'j':
|
||||||
|
|
||||||
|
// Month, formatted as two digits with leading zeros as necessary,
|
||||||
|
// i.e. 01 - 13.
|
||||||
|
case 'm':
|
||||||
|
|
||||||
|
// Day of month, formatted as two digits with leading zeros as
|
||||||
|
// necessary, i.e. 01 - 31
|
||||||
|
case 'd':
|
||||||
|
|
||||||
|
// Day of month, formatted as two digits, i.e. 1 - 31.
|
||||||
|
case 'e':
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// The following conversion characters are used for formatting common
|
||||||
|
// date/time compositions.
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Time formatted for the 24-hour clock as "%tH:%tM"
|
||||||
|
case 'R':
|
||||||
|
|
||||||
|
// Time formatted for the 24-hour clock as "%tH:%tM:%tS".
|
||||||
|
case 'T':
|
||||||
|
|
||||||
|
// Time formatted for the 12-hour clock as "%tI:%tM:%tS %Tp". The location
|
||||||
|
// of the morning or afternoon marker ('%Tp') may be locale-dependent.
|
||||||
|
case 'r':
|
||||||
|
|
||||||
|
// Date formatted as "%tm/%td/%ty".
|
||||||
|
case 'D':
|
||||||
|
|
||||||
|
// ISO 8601 complete date formatted as "%tY-%tm-%td".
|
||||||
|
case 'F':
|
||||||
|
|
||||||
|
// Date and time formatted as "%ta %tb %td %tT %tZ %tY", e.g.
|
||||||
|
// "Sun Jul 20 16:17:00 EDT 1969".
|
||||||
|
case 'c':
|
||||||
|
return seal(CONV_DTIME);
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new IllegalFormatException("Illegal date/time modifier: " + c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Flags and Switches -----------------------------------------------
|
||||||
|
// these are the possible characters for flags, width, etc. if the input
|
||||||
|
// is not one of these characters, it needs to be a valid conversion char.
|
||||||
|
// because the possible flags can vary based on the type of conversion,
|
||||||
|
// it is easiest to just buffer the flags, argument index, etc. until a
|
||||||
|
// conversion character has been reached. The seal() method will then
|
||||||
|
// work out if the specified flags are valid for the given conversion.
|
||||||
|
switch (c) {
|
||||||
|
case '$':
|
||||||
|
case '<':
|
||||||
|
case '0':
|
||||||
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
case '4':
|
||||||
|
case '5':
|
||||||
|
case '6':
|
||||||
|
case '7':
|
||||||
|
case '8':
|
||||||
|
case '9':
|
||||||
|
case '-':
|
||||||
|
case '+':
|
||||||
|
case '\'':
|
||||||
|
case ' ':
|
||||||
|
case '#':
|
||||||
|
case ',':
|
||||||
|
case '.':
|
||||||
|
case '(':
|
||||||
|
return null;
|
||||||
|
// -- End of Flags and Switches ----------------------------------------
|
||||||
|
|
||||||
|
// -- Conversion characters --------------------------------------------
|
||||||
|
// If this point is reached, then the current character must be a valid
|
||||||
|
// conversion character. If it is not, it should fall through the rest
|
||||||
|
// of the switch statement below and throw an IllegalFormatException
|
||||||
|
|
||||||
|
// string conversion
|
||||||
|
case 'S':
|
||||||
|
setFlagTrue(FLAG_FORCE_UPPER_CASE);
|
||||||
|
case 's':
|
||||||
|
return seal(CONV_STRNG);
|
||||||
|
|
||||||
|
// newline conversion
|
||||||
|
case 'n':
|
||||||
|
return seal(CONV_NLINE);
|
||||||
|
|
||||||
|
// percent conversion
|
||||||
|
case '%':
|
||||||
|
return seal(CONV_PRCNT);
|
||||||
|
|
||||||
|
// decimal numeric conversion
|
||||||
|
case 'd':
|
||||||
|
return seal(CONV_DECML);
|
||||||
|
|
||||||
|
// hexidecimal numeric conversion
|
||||||
|
case 'X':
|
||||||
|
setFlagTrue(FLAG_FORCE_UPPER_CASE);
|
||||||
|
case 'x':
|
||||||
|
return seal(CONV_HXDEC);
|
||||||
|
|
||||||
|
// datetime conversion
|
||||||
|
case 'T':
|
||||||
|
setFlagTrue(FLAG_FORCE_UPPER_CASE);
|
||||||
|
case 't':
|
||||||
|
_conversion = CONV_DTIME;
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// boolean conversion
|
||||||
|
case 'B':
|
||||||
|
setFlagTrue(FLAG_FORCE_UPPER_CASE);
|
||||||
|
case 'b':
|
||||||
|
return seal(CONV_BOOLN);
|
||||||
|
|
||||||
|
// hashcode conversion
|
||||||
|
case 'H':
|
||||||
|
setFlagTrue(FLAG_FORCE_UPPER_CASE);
|
||||||
|
case 'h':
|
||||||
|
return seal(CONV_HCODE);
|
||||||
|
|
||||||
|
// character conversion
|
||||||
|
case 'C':
|
||||||
|
setFlagTrue(FLAG_FORCE_UPPER_CASE);
|
||||||
|
case 'c':
|
||||||
|
return seal(CONV_CHRCT);
|
||||||
|
|
||||||
|
// octal numeric conversion
|
||||||
|
case 'o':
|
||||||
|
return seal(CONV_OCTAL);
|
||||||
|
|
||||||
|
// computerized scientific conversion
|
||||||
|
case 'E':
|
||||||
|
setFlagTrue(FLAG_FORCE_UPPER_CASE);
|
||||||
|
case 'e':
|
||||||
|
return seal(CONV_CPSCI);
|
||||||
|
|
||||||
|
// floating point conversion
|
||||||
|
case 'f':
|
||||||
|
return seal(CONV_FLOAT);
|
||||||
|
|
||||||
|
// general scientific floating point conversion
|
||||||
|
case 'G':
|
||||||
|
setFlagTrue(FLAG_FORCE_UPPER_CASE);
|
||||||
|
case 'g':
|
||||||
|
return seal(CONV_GNSCI);
|
||||||
|
|
||||||
|
// hexidecimal exponential floating point conversion
|
||||||
|
case 'A':
|
||||||
|
setFlagTrue(FLAG_FORCE_UPPER_CASE);
|
||||||
|
case 'a':
|
||||||
|
return seal(CONV_HXEXP);
|
||||||
|
// -- End of Conversion characters --------------------------------------
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new IllegalFormatException(
|
||||||
|
"Invalid character encountered while parsing specifier: " + c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("{ ")
|
||||||
|
.append("source = '").append(_source).append("', ")
|
||||||
|
.append("conversion = ").append(_conversion).append(", ")
|
||||||
|
.append("flags = ").append(Byte.toString(_flags, 2)).append(", ")
|
||||||
|
.append("arg_index = ").append(_argument_index).append(", ")
|
||||||
|
.append("width = ").append(_width).append(", ")
|
||||||
|
.append("precision = ").append(_precision).append(", ")
|
||||||
|
.append("}");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final FmtCmpnt seal(final byte conversion) {
|
||||||
|
|
||||||
|
// throwing IllegalStateException instead of IllegalFormatException
|
||||||
|
// because this should only occur if there is a bug in the append()
|
||||||
|
// method. In that case I'd prefer to fail fast even if the user is
|
||||||
|
// explicitly trying to catch IllegalFormatException.
|
||||||
|
if (conversion < 0 || conversion > 0xE) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
this._conversion = conversion;
|
||||||
|
|
||||||
|
// if the length is less than 2, it must mean that only the conversion
|
||||||
|
// character was specified. Since a conversion character by itself is a
|
||||||
|
// valid pattern, just build and return
|
||||||
|
if (_source.length() < 2) {
|
||||||
|
return build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// spec format: [argument_index$][flags][width][.precision]
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// the last character of the spec is the conversion character which has
|
||||||
|
// already been translated the appropriate byte by the append() method,
|
||||||
|
// so the last character gets chopped off before processing
|
||||||
|
final String spec = _source.substring(0, _source.length() - 1);
|
||||||
|
|
||||||
|
// if argument index is supported, it should be followed by a '$' and be
|
||||||
|
// comprised only of digit characters, or it should be a single '<' char
|
||||||
|
final int dollarIndex = spec.indexOf('$');
|
||||||
|
if (dollarIndex > -1) {
|
||||||
|
if (acceptsArgument(conversion)) {
|
||||||
|
if (spec.charAt(dollarIndex - 1) == '<') {
|
||||||
|
_argument_index = AIDX_PREV;
|
||||||
|
} else {
|
||||||
|
_argument_index = Integer.valueOf(spec.substring(0, dollarIndex));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new IllegalFormatException(
|
||||||
|
"Formats that do not accept arguments cannot specify an index."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dollarIndex == (spec.length() - 1)) {
|
||||||
|
return build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if precision is supported, look for the first period and assume that
|
||||||
|
// everything before is the width and everything after is the precision
|
||||||
|
final int dotIndex = spec.indexOf('.');
|
||||||
|
if (dotIndex > -1) {
|
||||||
|
if (precisionSupported(conversion)) {
|
||||||
|
_precision = Integer.valueOf(spec.substring(dotIndex + 1));
|
||||||
|
} else {
|
||||||
|
throw new IllegalFormatException(
|
||||||
|
"Precision is not supported for " + conversion
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now loop over the remaining characters to get the width as well as any
|
||||||
|
// applicable flags. Note: 0 is a valid flag so must be handled carefully
|
||||||
|
final String remaining = spec.substring(
|
||||||
|
Math.max(dollarIndex, 0), dotIndex > -1 ? dotIndex : spec.length()
|
||||||
|
);
|
||||||
|
int flagsEnd = -1;
|
||||||
|
for (int i = 0, n = remaining.length(); i < n && (flagsEnd == -1); i++) {
|
||||||
|
final char c = remaining.charAt(i);
|
||||||
|
switch (c) {
|
||||||
|
case '-':
|
||||||
|
ensureLeftJustifySupported();
|
||||||
|
setFlagTrue(FLAG_LEFT_JUSTIFIED);
|
||||||
|
break;
|
||||||
|
case '#':
|
||||||
|
ensureNumeric(c);
|
||||||
|
setFlagTrue(FLAG_ALTERNATE_FORM);
|
||||||
|
break;
|
||||||
|
case '+':
|
||||||
|
ensureNumeric(c);
|
||||||
|
setFlagTrue(FLAG_ALWAYS_INCLUDES_SIGN);
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
ensureNumeric(c);
|
||||||
|
setFlagTrue(FLAG_LEADING_SPACE_PADDED);
|
||||||
|
break;
|
||||||
|
case ',':
|
||||||
|
ensureNumeric(c);
|
||||||
|
setFlagTrue(FLAG_GROUPING_SEPARATORS);
|
||||||
|
break;
|
||||||
|
case '(':
|
||||||
|
ensureNumeric(c);
|
||||||
|
setFlagTrue(FLAG_NEGATIVES_IN_PARENS);
|
||||||
|
break;
|
||||||
|
case '0':
|
||||||
|
ensureNumeric(c);
|
||||||
|
setFlagTrue(FLAG_LEADING_ZERO_PADDED);
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
case '4':
|
||||||
|
case '5':
|
||||||
|
case '6':
|
||||||
|
case '7':
|
||||||
|
case '8':
|
||||||
|
case '9':
|
||||||
|
flagsEnd = i;
|
||||||
|
_width = Integer.valueOf(remaining.substring(flagsEnd));
|
||||||
|
return build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
private final void ensureLeftJustifySupported() {
|
||||||
|
if (!widthSupported(_conversion)) {
|
||||||
|
throw new IllegalFormatException(
|
||||||
|
"Conversion must support width if specifying left justified."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private final void ensureNumeric(final char c) {
|
||||||
|
if (!isNumeric(_conversion)) {
|
||||||
|
throw new IllegalFormatException(
|
||||||
|
"flag " + c + " only supported on numeric specifiers."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private final void setFlagTrue(final byte flag) {
|
||||||
|
_flags |= flag;
|
||||||
|
}/*
|
||||||
|
final void setFlagFalse(final byte flag) {
|
||||||
|
_flags &= ~flag;
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
15
sgx-jvm/avian/classpath/avian/Function.java
Normal file
15
sgx-jvm/avian/classpath/avian/Function.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public interface Function<A,B> {
|
||||||
|
public B call(A argument) throws Exception;
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class IncompatibleContinuationException extends Exception {
|
||||||
|
public IncompatibleContinuationException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IncompatibleContinuationException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
18
sgx-jvm/avian/classpath/avian/InnerClassReference.java
Normal file
18
sgx-jvm/avian/classpath/avian/InnerClassReference.java
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class InnerClassReference {
|
||||||
|
public byte[] inner;
|
||||||
|
public byte[] outer;
|
||||||
|
public byte[] name;
|
||||||
|
public short flags;
|
||||||
|
}
|
26
sgx-jvm/avian/classpath/avian/Iso88591.java
Normal file
26
sgx-jvm/avian/classpath/avian/Iso88591.java
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
|
||||||
|
public class Iso88591 {
|
||||||
|
|
||||||
|
public static byte[] encode(char[] s16, int offset, int length) {
|
||||||
|
ByteArrayOutputStream buf = new ByteArrayOutputStream();
|
||||||
|
for (int i = offset; i < offset+length; ++i) {
|
||||||
|
// ISO-88591-1/Latin-1 is the same as UTF-16 under 0x100
|
||||||
|
buf.write(s16[i]);
|
||||||
|
}
|
||||||
|
return buf.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
240
sgx-jvm/avian/classpath/avian/LegacyObjectInputStream.java
Normal file
240
sgx-jvm/avian/classpath/avian/LegacyObjectInputStream.java
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
import avian.VMClass;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.io.EOFException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.PushbackReader;
|
||||||
|
import java.io.StreamCorruptedException;
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
|
public class LegacyObjectInputStream extends InputStream {
|
||||||
|
private final InputStream in;
|
||||||
|
private final PushbackReader r;
|
||||||
|
|
||||||
|
public LegacyObjectInputStream(InputStream in) {
|
||||||
|
this.in = in;
|
||||||
|
this.r = new PushbackReader(new InputStreamReader(in));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read() throws IOException {
|
||||||
|
return in.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(byte[] b, int offset, int length) throws IOException {
|
||||||
|
return in.read(b, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object readObject() throws IOException, ClassNotFoundException {
|
||||||
|
return readObject(new HashMap<Integer, Object>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean readBoolean() throws IOException {
|
||||||
|
read('z');
|
||||||
|
return readLongToken() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte readByte() throws IOException {
|
||||||
|
read('b');
|
||||||
|
return (byte) readLongToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
public char readChar() throws IOException {
|
||||||
|
read('c');
|
||||||
|
return (char) readLongToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
public short readShort() throws IOException {
|
||||||
|
read('s');
|
||||||
|
return (short) readLongToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int readInt() throws IOException {
|
||||||
|
read('i');
|
||||||
|
return (int) readLongToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long readLong() throws IOException {
|
||||||
|
read('j');
|
||||||
|
return readLongToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float readFloat() throws IOException {
|
||||||
|
read('f');
|
||||||
|
return (float) readDoubleToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double readDouble() throws IOException {
|
||||||
|
read('d');
|
||||||
|
return readDoubleToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void defaultReadObject() throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void skipSpace() throws IOException {
|
||||||
|
int c;
|
||||||
|
while ((c = r.read()) != -1 && Character.isWhitespace((char) c));
|
||||||
|
if (c != -1) {
|
||||||
|
r.unread(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void read(char v) throws IOException {
|
||||||
|
skipSpace();
|
||||||
|
|
||||||
|
int c = r.read();
|
||||||
|
if (c != v) {
|
||||||
|
if (c == -1) {
|
||||||
|
throw new EOFException();
|
||||||
|
} else {
|
||||||
|
throw new StreamCorruptedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String readStringToken() throws IOException {
|
||||||
|
skipSpace();
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
int c;
|
||||||
|
while ((c = r.read()) != -1 && ! Character.isWhitespace((char) c) && c != ')') {
|
||||||
|
sb.append((char) c);
|
||||||
|
}
|
||||||
|
if (c != -1) {
|
||||||
|
r.unread(c);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private long readLongToken() throws IOException {
|
||||||
|
return Long.parseLong(readStringToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
private double readDoubleToken() throws IOException {
|
||||||
|
return Double.parseDouble(readStringToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object readObject(HashMap<Integer, Object> map)
|
||||||
|
throws IOException, ClassNotFoundException
|
||||||
|
{
|
||||||
|
skipSpace();
|
||||||
|
switch (r.read()) {
|
||||||
|
case 'a':
|
||||||
|
return deserializeArray(map);
|
||||||
|
case 'l':
|
||||||
|
return deserializeObject(map);
|
||||||
|
case 'n':
|
||||||
|
return null;
|
||||||
|
case -1:
|
||||||
|
throw new EOFException();
|
||||||
|
default:
|
||||||
|
throw new StreamCorruptedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object deserialize(HashMap<Integer, Object> map)
|
||||||
|
throws IOException, ClassNotFoundException
|
||||||
|
{
|
||||||
|
skipSpace();
|
||||||
|
switch (r.read()) {
|
||||||
|
case 'a':
|
||||||
|
return deserializeArray(map);
|
||||||
|
case 'l':
|
||||||
|
return deserializeObject(map);
|
||||||
|
case 'r':
|
||||||
|
return map.get((int) readLongToken());
|
||||||
|
case 'n':
|
||||||
|
return null;
|
||||||
|
case 'z':
|
||||||
|
return (readLongToken() != 0);
|
||||||
|
case 'b':
|
||||||
|
return (byte) readLongToken();
|
||||||
|
case 'c':
|
||||||
|
return (char) readLongToken();
|
||||||
|
case 's':
|
||||||
|
return (short) readLongToken();
|
||||||
|
case 'i':
|
||||||
|
return (int) readLongToken();
|
||||||
|
case 'j':
|
||||||
|
return readLongToken();
|
||||||
|
case 'f':
|
||||||
|
return (float) readDoubleToken();
|
||||||
|
case 'd':
|
||||||
|
return readDoubleToken();
|
||||||
|
case -1:
|
||||||
|
throw new EOFException();
|
||||||
|
default:
|
||||||
|
throw new StreamCorruptedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object deserializeArray(HashMap<Integer, Object> map)
|
||||||
|
throws IOException, ClassNotFoundException
|
||||||
|
{
|
||||||
|
read('(');
|
||||||
|
int id = (int) readLongToken();
|
||||||
|
Class<?> c = Class.forName(readStringToken());
|
||||||
|
int length = (int) readLongToken();
|
||||||
|
Class<?> t = c.getComponentType();
|
||||||
|
Object o = Array.newInstance(t, length);
|
||||||
|
|
||||||
|
map.put(id, o);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i) {
|
||||||
|
Array.set(o, i, deserialize(map));
|
||||||
|
}
|
||||||
|
|
||||||
|
read(')');
|
||||||
|
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native Object makeInstance(VMClass c);
|
||||||
|
|
||||||
|
private Object deserializeObject(HashMap<Integer, Object> map)
|
||||||
|
throws IOException, ClassNotFoundException
|
||||||
|
{
|
||||||
|
read('(');
|
||||||
|
int id = (int) readLongToken();
|
||||||
|
Class<?> c = Class.forName(readStringToken());
|
||||||
|
Object o = makeInstance(c.vmClass);
|
||||||
|
|
||||||
|
map.put(id, o);
|
||||||
|
|
||||||
|
for (Field<?> f: c.getAllFields()) {
|
||||||
|
int modifiers = f.getModifiers();
|
||||||
|
if ((modifiers & (Modifier.TRANSIENT | Modifier.STATIC)) == 0) {
|
||||||
|
try {
|
||||||
|
f.set(o, deserialize(map));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
read(')');
|
||||||
|
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
211
sgx-jvm/avian/classpath/avian/LegacyObjectOutputStream.java
Normal file
211
sgx-jvm/avian/classpath/avian/LegacyObjectOutputStream.java
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
import java.util.IdentityHashMap;
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.io.NotSerializableException;
|
||||||
|
|
||||||
|
public class LegacyObjectOutputStream extends OutputStream {
|
||||||
|
private final PrintStream out;
|
||||||
|
|
||||||
|
public LegacyObjectOutputStream(OutputStream out) {
|
||||||
|
this.out = new PrintStream(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeObject(Object o) throws IOException {
|
||||||
|
writeObject(o, new IdentityHashMap(), new int[] {0});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeBoolean(boolean v) {
|
||||||
|
out.print("z");
|
||||||
|
out.print((v ? 1 : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeByte(byte v) {
|
||||||
|
out.print("b");
|
||||||
|
out.print((int) v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeChar(char v) {
|
||||||
|
out.print("c");
|
||||||
|
out.print((int) v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeShort(short v) {
|
||||||
|
out.print("s");
|
||||||
|
out.print((int) v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeInt(int v) {
|
||||||
|
out.print("i");
|
||||||
|
out.print(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeLong(long v) {
|
||||||
|
out.print("j");
|
||||||
|
out.print(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeFloat(float v) {
|
||||||
|
out.print("f");
|
||||||
|
out.print(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeDouble(double v) {
|
||||||
|
out.print("d");
|
||||||
|
out.print(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void defaultWriteObject() throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeObject(Object o, IdentityHashMap<Object, Integer> map,
|
||||||
|
int[] nextId)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
if (o == null) {
|
||||||
|
out.print("n");
|
||||||
|
} else {
|
||||||
|
Integer id = map.get(o);
|
||||||
|
if (id == null) {
|
||||||
|
map.put(o, nextId[0]);
|
||||||
|
|
||||||
|
Class c = o.getClass();
|
||||||
|
if (c.isArray()) {
|
||||||
|
serializeArray(o, map, nextId);
|
||||||
|
} else if (Serializable.class.isAssignableFrom(c)) {
|
||||||
|
serializeObject(o, map, nextId);
|
||||||
|
} else {
|
||||||
|
throw new NotSerializableException(c.getName());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.print("r");
|
||||||
|
out.print(id.intValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void serializeArray(Object o, IdentityHashMap<Object, Integer> map,
|
||||||
|
int[] nextId)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
Class c = o.getClass();
|
||||||
|
Class t = c.getComponentType();
|
||||||
|
int length = Array.getLength(o);
|
||||||
|
|
||||||
|
out.print("a(");
|
||||||
|
out.print(nextId[0]++);
|
||||||
|
out.print(" ");
|
||||||
|
out.print(c.getName());
|
||||||
|
out.print(" ");
|
||||||
|
out.print(length);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i) {
|
||||||
|
out.print(" ");
|
||||||
|
Object v = Array.get(o, i);
|
||||||
|
if (t.equals(boolean.class)) {
|
||||||
|
writeBoolean((Boolean) v);
|
||||||
|
} else if (t.equals(byte.class)) {
|
||||||
|
writeByte((Byte) v);
|
||||||
|
} else if (t.equals(char.class)) {
|
||||||
|
writeChar((Character) v);
|
||||||
|
} else if (t.equals(short.class)) {
|
||||||
|
writeShort((Short) v);
|
||||||
|
} else if (t.equals(int.class)) {
|
||||||
|
writeInt((Integer) v);
|
||||||
|
} else if (t.equals(long.class)) {
|
||||||
|
writeLong((Long) v);
|
||||||
|
} else if (t.equals(float.class)) {
|
||||||
|
writeFloat((Float) v);
|
||||||
|
} else if (t.equals(double.class)) {
|
||||||
|
writeDouble((Double) v);
|
||||||
|
} else {
|
||||||
|
writeObject(v, map, nextId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out.print(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void serializeObject(Object o, IdentityHashMap<Object, Integer> map,
|
||||||
|
int[] nextId)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
Class c = o.getClass();
|
||||||
|
|
||||||
|
out.print("l(");
|
||||||
|
out.print(nextId[0]++);
|
||||||
|
out.print(" ");
|
||||||
|
out.print(c.getName());
|
||||||
|
|
||||||
|
for (Field f: c.getAllFields()) {
|
||||||
|
int modifiers = f.getModifiers();
|
||||||
|
if ((modifiers & (Modifier.TRANSIENT | Modifier.STATIC)) == 0) {
|
||||||
|
out.print(" ");
|
||||||
|
Object v;
|
||||||
|
|
||||||
|
try {
|
||||||
|
v = f.get(o);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
Class t = f.getType();
|
||||||
|
if (t.equals(boolean.class)) {
|
||||||
|
writeBoolean((Boolean) v);
|
||||||
|
} else if (t.equals(byte.class)) {
|
||||||
|
writeByte((Byte) v);
|
||||||
|
} else if (t.equals(char.class)) {
|
||||||
|
writeChar((Character) v);
|
||||||
|
} else if (t.equals(short.class)) {
|
||||||
|
writeShort((Short) v);
|
||||||
|
} else if (t.equals(int.class)) {
|
||||||
|
writeInt((Integer) v);
|
||||||
|
} else if (t.equals(long.class)) {
|
||||||
|
writeLong((Long) v);
|
||||||
|
} else if (t.equals(float.class)) {
|
||||||
|
writeFloat((Float) v);
|
||||||
|
} else if (t.equals(double.class)) {
|
||||||
|
writeDouble((Double) v);
|
||||||
|
} else {
|
||||||
|
writeObject(v, map, nextId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out.print(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
67
sgx-jvm/avian/classpath/avian/Machine.java
Normal file
67
sgx-jvm/avian/classpath/avian/Machine.java
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
import sun.misc.Unsafe;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
public abstract class Machine {
|
||||||
|
|
||||||
|
private static final Unsafe unsafe;
|
||||||
|
|
||||||
|
static {
|
||||||
|
Unsafe u;
|
||||||
|
try {
|
||||||
|
Field f = Unsafe.class.getDeclaredField("theUnsafe");
|
||||||
|
f.setAccessible(true);
|
||||||
|
u = (Unsafe)f.get(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
u = null;
|
||||||
|
}
|
||||||
|
unsafe = u;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static native void dumpHeap(String outputFile);
|
||||||
|
|
||||||
|
public static Unsafe getUnsafe() {
|
||||||
|
return unsafe;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Short version: Don't use this function -- it's evil.
|
||||||
|
*
|
||||||
|
* Long version: This is kind of a poor man's, cross-platform
|
||||||
|
* version of Microsoft's Structured Exception Handling. The idea
|
||||||
|
* is that you can call a native function with the specified
|
||||||
|
* argument such that any OS signals raised (e.g. SIGSEGV, SIGBUS,
|
||||||
|
* SIGFPE, EXC_ACCESS_VIOLATION, etc.) prior to the function
|
||||||
|
* returning are converted into the appropriate Java exception
|
||||||
|
* (e.g. NullPointerException, ArithmeticException, etc.) and thrown
|
||||||
|
* from this method. This may be useful in very specific
|
||||||
|
* circumstances, e.g. to work around a bug in a library that would
|
||||||
|
* otherwise crash your app. On the other hand, you'd be much
|
||||||
|
* better off just fixing the library if possible.
|
||||||
|
*
|
||||||
|
* Caveats: The specified function should return quickly without
|
||||||
|
* blocking, since it will block critical VM features such as
|
||||||
|
* garbage collection. The implementation is equivalent to using
|
||||||
|
* setjmp/longjmp to achieve a non-local return from the signal
|
||||||
|
* handler, meaning C++ destructors and other cleanup code might not
|
||||||
|
* be run if a signal is raised. It might melt your keyboard and
|
||||||
|
* burn your fingertips. Caveat lector.
|
||||||
|
*
|
||||||
|
* @param function a function pointer of type int64_t (*)(int64_t)
|
||||||
|
* @param argument the argument to pass to the function
|
||||||
|
* @return the return value of the function
|
||||||
|
*/
|
||||||
|
public static native long tryNative(long function, long argument);
|
||||||
|
|
||||||
|
}
|
17
sgx-jvm/avian/classpath/avian/MethodAddendum.java
Normal file
17
sgx-jvm/avian/classpath/avian/MethodAddendum.java
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class MethodAddendum extends Addendum {
|
||||||
|
public Object exceptionTable;
|
||||||
|
public Object annotationDefault;
|
||||||
|
public Object parameterAnnotationTable;
|
||||||
|
}
|
5
sgx-jvm/avian/classpath/avian/Pair.java
Normal file
5
sgx-jvm/avian/classpath/avian/Pair.java
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package avian;
|
||||||
|
|
||||||
|
abstract class Pair {
|
||||||
|
// VM-visible fields in types.def
|
||||||
|
}
|
594
sgx-jvm/avian/classpath/avian/PersistentSet.java
Normal file
594
sgx-jvm/avian/classpath/avian/PersistentSet.java
Normal file
@ -0,0 +1,594 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
public class PersistentSet <T> implements Iterable <T> {
|
||||||
|
private static final Node NullNode = new Node(null);
|
||||||
|
|
||||||
|
static {
|
||||||
|
NullNode.left = NullNode;
|
||||||
|
NullNode.right = NullNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Node<T> root;
|
||||||
|
private final Comparator<T> comparator;
|
||||||
|
private final int size;
|
||||||
|
|
||||||
|
public PersistentSet() {
|
||||||
|
this(NullNode, new Comparator<T>() {
|
||||||
|
public int compare(T a, T b) {
|
||||||
|
return ((Comparable<T>) a).compareTo(b);
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentSet(Comparator<T> comparator) {
|
||||||
|
this(NullNode, comparator, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PersistentSet(Node<T> root, Comparator<T> comparator, int size) {
|
||||||
|
this.root = root;
|
||||||
|
this.comparator = comparator;
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("{");
|
||||||
|
for (java.util.Iterator it = iterator(); it.hasNext();) {
|
||||||
|
sb.append(it.next());
|
||||||
|
if (it.hasNext()) {
|
||||||
|
sb.append(",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append("}");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Comparator<T> comparator() {
|
||||||
|
return comparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentSet<T> add(T value) {
|
||||||
|
return add(value, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentSet<T> add(T value, boolean replaceExisting) {
|
||||||
|
Path<T> p = find(value);
|
||||||
|
if (! p.fresh) {
|
||||||
|
if (replaceExisting) {
|
||||||
|
return p.replaceWith(value);
|
||||||
|
} else {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return add(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PersistentSet<T> add(Path<T> p) {
|
||||||
|
if (! p.fresh) throw new IllegalArgumentException();
|
||||||
|
|
||||||
|
Node<T> new_ = p.node;
|
||||||
|
Node<T> newRoot = p.root.root;
|
||||||
|
Cell<Node<T>> ancestors = p.ancestors;
|
||||||
|
|
||||||
|
// rebalance
|
||||||
|
new_.red = true;
|
||||||
|
while (ancestors != null && ancestors.value.red) {
|
||||||
|
if (ancestors.value == ancestors.next.value.left) {
|
||||||
|
if (ancestors.next.value.right.red) {
|
||||||
|
ancestors.value.red = false;
|
||||||
|
ancestors.next.value.right = new Node(ancestors.next.value.right);
|
||||||
|
ancestors.next.value.right.red = false;
|
||||||
|
ancestors.next.value.red = true;
|
||||||
|
new_ = ancestors.next.value;
|
||||||
|
ancestors = ancestors.next.next;
|
||||||
|
} else {
|
||||||
|
if (new_ == ancestors.value.right) {
|
||||||
|
new_ = ancestors.value;
|
||||||
|
ancestors = ancestors.next;
|
||||||
|
|
||||||
|
Node<T> n = leftRotate(new_);
|
||||||
|
if (ancestors.value.right == new_) {
|
||||||
|
ancestors.value.right = n;
|
||||||
|
} else {
|
||||||
|
ancestors.value.left = n;
|
||||||
|
}
|
||||||
|
ancestors = new Cell(n, ancestors);
|
||||||
|
}
|
||||||
|
ancestors.value.red = false;
|
||||||
|
ancestors.next.value.red = true;
|
||||||
|
|
||||||
|
Node<T> n = rightRotate(ancestors.next.value);
|
||||||
|
if (ancestors.next.next == null) {
|
||||||
|
newRoot = n;
|
||||||
|
} else if (ancestors.next.next.value.right == ancestors.next.value) {
|
||||||
|
ancestors.next.next.value.right = n;
|
||||||
|
} else {
|
||||||
|
ancestors.next.next.value.left = n;
|
||||||
|
}
|
||||||
|
// done
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ancestors.next.value.left.red) {
|
||||||
|
ancestors.value.red = false;
|
||||||
|
ancestors.next.value.left = new Node(ancestors.next.value.left);
|
||||||
|
ancestors.next.value.left.red = false;
|
||||||
|
ancestors.next.value.red = true;
|
||||||
|
new_ = ancestors.next.value;
|
||||||
|
ancestors = ancestors.next.next;
|
||||||
|
} else {
|
||||||
|
if (new_ == ancestors.value.left) {
|
||||||
|
new_ = ancestors.value;
|
||||||
|
ancestors = ancestors.next;
|
||||||
|
|
||||||
|
Node<T> n = rightRotate(new_);
|
||||||
|
if (ancestors.value.right == new_) {
|
||||||
|
ancestors.value.right = n;
|
||||||
|
} else {
|
||||||
|
ancestors.value.left = n;
|
||||||
|
}
|
||||||
|
ancestors = new Cell(n, ancestors);
|
||||||
|
}
|
||||||
|
ancestors.value.red = false;
|
||||||
|
ancestors.next.value.red = true;
|
||||||
|
|
||||||
|
Node<T> n = leftRotate(ancestors.next.value);
|
||||||
|
if (ancestors.next.next == null) {
|
||||||
|
newRoot = n;
|
||||||
|
} else if (ancestors.next.next.value.right == ancestors.next.value) {
|
||||||
|
ancestors.next.next.value.right = n;
|
||||||
|
} else {
|
||||||
|
ancestors.next.next.value.left = n;
|
||||||
|
}
|
||||||
|
// done
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newRoot.red = false;
|
||||||
|
|
||||||
|
return new PersistentSet(newRoot, comparator, size + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> Node<T> leftRotate(Node<T> n) {
|
||||||
|
Node<T> child = new Node(n.right);
|
||||||
|
n.right = child.left;
|
||||||
|
child.left = n;
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> Node<T> rightRotate(Node<T> n) {
|
||||||
|
Node<T> child = new Node(n.left);
|
||||||
|
n.left = child.right;
|
||||||
|
child.right = n;
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentSet<T> remove(T value) {
|
||||||
|
Path<T> p = find(value);
|
||||||
|
if (! p.fresh) {
|
||||||
|
return remove(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PersistentSet<T> remove(Path<T> p) {
|
||||||
|
if (size == 1) {
|
||||||
|
if (p.node != root) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
return new PersistentSet(NullNode, comparator, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node<T> new_ = p.node;
|
||||||
|
Node<T> newRoot = p.root.root;
|
||||||
|
Cell<Node<T>> ancestors = p.ancestors;
|
||||||
|
|
||||||
|
Node<T> dead;
|
||||||
|
if (new_.left == NullNode || new_.right == NullNode) {
|
||||||
|
dead = new_;
|
||||||
|
} else {
|
||||||
|
Cell<Node<T>> path = successor(new_, ancestors);
|
||||||
|
dead = path.value;
|
||||||
|
ancestors = path.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node<T> child;
|
||||||
|
if (dead.left != NullNode) {
|
||||||
|
child = new Node(dead.left);
|
||||||
|
} else if (dead.right != NullNode) {
|
||||||
|
child = new Node(dead.right);
|
||||||
|
} else {
|
||||||
|
child = NullNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ancestors == null) {
|
||||||
|
child.red = false;
|
||||||
|
return new PersistentSet(child, comparator, 1);
|
||||||
|
} else if (dead == ancestors.value.left) {
|
||||||
|
ancestors.value.left = child;
|
||||||
|
} else {
|
||||||
|
ancestors.value.right = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dead != new_) {
|
||||||
|
new_.value = dead.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! dead.red) {
|
||||||
|
// rebalance
|
||||||
|
while (ancestors != null && ! child.red) {
|
||||||
|
if (child == ancestors.value.left) {
|
||||||
|
Node<T> sibling = ancestors.value.right
|
||||||
|
= new Node(ancestors.value.right);
|
||||||
|
if (sibling.red) {
|
||||||
|
sibling.red = false;
|
||||||
|
ancestors.value.red = true;
|
||||||
|
|
||||||
|
Node<T> n = leftRotate(ancestors.value);
|
||||||
|
if (ancestors.next == null) {
|
||||||
|
newRoot = n;
|
||||||
|
} else if (ancestors.next.value.right == ancestors.value) {
|
||||||
|
ancestors.next.value.right = n;
|
||||||
|
} else {
|
||||||
|
ancestors.next.value.left = n;
|
||||||
|
}
|
||||||
|
ancestors.next = new Cell(n, ancestors.next);
|
||||||
|
|
||||||
|
sibling = ancestors.value.right = new Node(ancestors.value.right);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! (sibling.left.red || sibling.right.red)) {
|
||||||
|
sibling.red = true;
|
||||||
|
child = ancestors.value;
|
||||||
|
ancestors = ancestors.next;
|
||||||
|
} else {
|
||||||
|
if (! sibling.right.red) {
|
||||||
|
sibling.left = new Node(sibling.left);
|
||||||
|
sibling.left.red = false;
|
||||||
|
|
||||||
|
sibling.red = true;
|
||||||
|
sibling = ancestors.value.right = rightRotate(sibling);
|
||||||
|
}
|
||||||
|
|
||||||
|
sibling.red = ancestors.value.red;
|
||||||
|
ancestors.value.red = false;
|
||||||
|
|
||||||
|
sibling.right = new Node(sibling.right);
|
||||||
|
sibling.right.red = false;
|
||||||
|
|
||||||
|
Node<T> n = leftRotate(ancestors.value);
|
||||||
|
if (ancestors.next == null) {
|
||||||
|
newRoot = n;
|
||||||
|
} else if (ancestors.next.value.right == ancestors.value) {
|
||||||
|
ancestors.next.value.right = n;
|
||||||
|
} else {
|
||||||
|
ancestors.next.value.left = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
child = newRoot;
|
||||||
|
ancestors = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Node<T> sibling = ancestors.value.left
|
||||||
|
= new Node(ancestors.value.left);
|
||||||
|
if (sibling.red) {
|
||||||
|
sibling.red = false;
|
||||||
|
ancestors.value.red = true;
|
||||||
|
|
||||||
|
Node<T> n = rightRotate(ancestors.value);
|
||||||
|
if (ancestors.next == null) {
|
||||||
|
newRoot = n;
|
||||||
|
} else if (ancestors.next.value.left == ancestors.value) {
|
||||||
|
ancestors.next.value.left = n;
|
||||||
|
} else {
|
||||||
|
ancestors.next.value.right = n;
|
||||||
|
}
|
||||||
|
ancestors.next = new Cell(n, ancestors.next);
|
||||||
|
|
||||||
|
sibling = ancestors.value.left = new Node(ancestors.value.left);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! (sibling.right.red || sibling.left.red)) {
|
||||||
|
sibling.red = true;
|
||||||
|
child = ancestors.value;
|
||||||
|
ancestors = ancestors.next;
|
||||||
|
} else {
|
||||||
|
if (! sibling.left.red) {
|
||||||
|
sibling.right = new Node(sibling.right);
|
||||||
|
sibling.right.red = false;
|
||||||
|
|
||||||
|
sibling.red = true;
|
||||||
|
sibling = ancestors.value.left = leftRotate(sibling);
|
||||||
|
}
|
||||||
|
|
||||||
|
sibling.red = ancestors.value.red;
|
||||||
|
ancestors.value.red = false;
|
||||||
|
|
||||||
|
sibling.left = new Node(sibling.left);
|
||||||
|
sibling.left.red = false;
|
||||||
|
|
||||||
|
Node<T> n = rightRotate(ancestors.value);
|
||||||
|
if (ancestors.next == null) {
|
||||||
|
newRoot = n;
|
||||||
|
} else if (ancestors.next.value.left == ancestors.value) {
|
||||||
|
ancestors.next.value.left = n;
|
||||||
|
} else {
|
||||||
|
ancestors.next.value.right = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
child = newRoot;
|
||||||
|
ancestors = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
child.red = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PersistentSet(newRoot, comparator, size - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> Cell<Node<T>> minimum(Node<T> n,
|
||||||
|
Cell<Node<T>> ancestors)
|
||||||
|
{
|
||||||
|
while (n.left != NullNode) {
|
||||||
|
n.left = new Node(n.left);
|
||||||
|
ancestors = new Cell(n, ancestors);
|
||||||
|
n = n.left;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Cell(n, ancestors);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> Cell<Node<T>> maximum(Node<T> n,
|
||||||
|
Cell<Node<T>> ancestors)
|
||||||
|
{
|
||||||
|
while (n.right != NullNode) {
|
||||||
|
n.right = new Node(n.right);
|
||||||
|
ancestors = new Cell(n, ancestors);
|
||||||
|
n = n.right;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Cell(n, ancestors);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> Cell<Node<T>> successor(Node<T> n,
|
||||||
|
Cell<Node<T>> ancestors)
|
||||||
|
{
|
||||||
|
if (n.right != NullNode) {
|
||||||
|
n.right = new Node(n.right);
|
||||||
|
return minimum(n.right, new Cell(n, ancestors));
|
||||||
|
}
|
||||||
|
|
||||||
|
while (ancestors != null && n == ancestors.value.right) {
|
||||||
|
n = ancestors.value;
|
||||||
|
ancestors = ancestors.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ancestors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> Cell<Node<T>> predecessor(Node<T> n,
|
||||||
|
Cell<Node<T>> ancestors)
|
||||||
|
{
|
||||||
|
if (n.left != NullNode) {
|
||||||
|
n.left = new Node(n.left);
|
||||||
|
return maximum(n.left, new Cell(n, ancestors));
|
||||||
|
}
|
||||||
|
|
||||||
|
while (ancestors != null && n == ancestors.value.left) {
|
||||||
|
n = ancestors.value;
|
||||||
|
ancestors = ancestors.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ancestors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path<T> find(T value) {
|
||||||
|
Node<T> newRoot = new Node(root);
|
||||||
|
Cell<Node<T>> ancestors = null;
|
||||||
|
|
||||||
|
Node<T> old = root;
|
||||||
|
Node<T> new_ = newRoot;
|
||||||
|
while (old != NullNode) {
|
||||||
|
ancestors = new Cell(new_, ancestors);
|
||||||
|
|
||||||
|
int difference = comparator.compare(value, old.value);
|
||||||
|
if (difference < 0) {
|
||||||
|
old = old.left;
|
||||||
|
new_ = new_.left = new Node(old);
|
||||||
|
} else if (difference > 0) {
|
||||||
|
old = old.right;
|
||||||
|
new_ = new_.right = new Node(old);
|
||||||
|
} else {
|
||||||
|
return new Path(false, new_,
|
||||||
|
new PersistentSet(newRoot, comparator, size),
|
||||||
|
ancestors.next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new_.value = value;
|
||||||
|
return new Path(true, new_,
|
||||||
|
new PersistentSet(newRoot, comparator, size),
|
||||||
|
ancestors);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path<T> first() {
|
||||||
|
if (root == NullNode) return null;
|
||||||
|
|
||||||
|
Node<T> newRoot = new Node(root);
|
||||||
|
Cell<Node<T>> ancestors = null;
|
||||||
|
|
||||||
|
Node<T> old = root;
|
||||||
|
Node<T> new_ = newRoot;
|
||||||
|
while (old.left != NullNode) {
|
||||||
|
ancestors = new Cell(new_, ancestors);
|
||||||
|
|
||||||
|
old = old.left;
|
||||||
|
new_ = new_.left = new Node(old);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Path(true, new_,
|
||||||
|
new PersistentSet(newRoot, comparator, size),
|
||||||
|
ancestors);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path<T> last() {
|
||||||
|
if (root == NullNode) return null;
|
||||||
|
|
||||||
|
Node<T> newRoot = new Node(root);
|
||||||
|
Cell<Node<T>> ancestors = null;
|
||||||
|
|
||||||
|
Node<T> old = root;
|
||||||
|
Node<T> new_ = newRoot;
|
||||||
|
while (old.right != NullNode) {
|
||||||
|
ancestors = new Cell(new_, ancestors);
|
||||||
|
|
||||||
|
old = old.right;
|
||||||
|
new_ = new_.right = new Node(old);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Path(true, new_,
|
||||||
|
new PersistentSet(newRoot, comparator, size),
|
||||||
|
ancestors);
|
||||||
|
}
|
||||||
|
|
||||||
|
public java.util.Iterator<T> iterator() {
|
||||||
|
return new Iterator(first());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Path<T> successor(Path<T> p) {
|
||||||
|
Cell<Node<T>> s = successor(p.node, p.ancestors);
|
||||||
|
if (s == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return new Path(false, s.value, p.root, s.next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Path<T> predecessor(Path<T> p) {
|
||||||
|
Cell<Node<T>> s = predecessor(p.node, p.ancestors);
|
||||||
|
if (s == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return new Path(false, s.value, p.root, s.next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Node <T> {
|
||||||
|
public T value;
|
||||||
|
public Node left;
|
||||||
|
public Node right;
|
||||||
|
public boolean red;
|
||||||
|
|
||||||
|
public Node(Node<T> basis) {
|
||||||
|
if (basis != null) {
|
||||||
|
value = basis.value;
|
||||||
|
left = basis.left;
|
||||||
|
right = basis.right;
|
||||||
|
red = basis.red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Path <T> {
|
||||||
|
private final boolean fresh;
|
||||||
|
private final Node<T> node;
|
||||||
|
private final PersistentSet<T> root;
|
||||||
|
private final Cell<Node<T>> ancestors;
|
||||||
|
|
||||||
|
public Path(boolean fresh, Node<T> node, PersistentSet<T> root,
|
||||||
|
Cell<Node<T>> ancestors)
|
||||||
|
{
|
||||||
|
this.fresh = fresh;
|
||||||
|
this.node = node;
|
||||||
|
this.root = root;
|
||||||
|
this.ancestors = ancestors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T value() {
|
||||||
|
return node.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean fresh() {
|
||||||
|
return fresh;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentSet<T> root() {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path<T> successor() {
|
||||||
|
return root.successor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path<T> predecessor() {
|
||||||
|
return root.predecessor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentSet<T> remove() {
|
||||||
|
if (fresh) throw new IllegalStateException();
|
||||||
|
|
||||||
|
return root.remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentSet<T> add() {
|
||||||
|
if (! fresh) throw new IllegalStateException();
|
||||||
|
|
||||||
|
return root.add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentSet<T> replaceWith(T value) {
|
||||||
|
if (fresh) throw new IllegalStateException();
|
||||||
|
if (root.comparator.compare(node.value, value) != 0)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
|
||||||
|
node.value = value;
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Iterator <T> implements java.util.Iterator <T> {
|
||||||
|
private PersistentSet.Path<T> path;
|
||||||
|
|
||||||
|
private Iterator(PersistentSet.Path<T> path) {
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Iterator(Iterator<T> start) {
|
||||||
|
path = start.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasNext() {
|
||||||
|
return path != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T next() {
|
||||||
|
PersistentSet.Path<T> p = path;
|
||||||
|
path = path.successor();
|
||||||
|
return p.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
sgx-jvm/avian/classpath/avian/Singleton.java
Normal file
19
sgx-jvm/avian/classpath/avian/Singleton.java
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public abstract class Singleton {
|
||||||
|
public static native int getInt(Object singleton, int offset);
|
||||||
|
public static native long getLong(Object singleton, int offset);
|
||||||
|
public static native Object getObject(Object singleton, int offset);
|
||||||
|
|
||||||
|
// Fields in types.def
|
||||||
|
}
|
80
sgx-jvm/avian/classpath/avian/Stream.java
Normal file
80
sgx-jvm/avian/classpath/avian/Stream.java
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.EOFException;
|
||||||
|
|
||||||
|
public abstract class Stream {
|
||||||
|
public static void write1(OutputStream out, int v) throws IOException {
|
||||||
|
out.write(v & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int read1(InputStream in) throws IOException {
|
||||||
|
return in.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void write2(OutputStream out, int v) throws IOException {
|
||||||
|
out.write((v >>> 8) & 0xFF);
|
||||||
|
out.write((v ) & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int read2(InputStream in) throws IOException {
|
||||||
|
int b1 = in.read();
|
||||||
|
int b2 = in.read();
|
||||||
|
if (b2 == -1) throw new EOFException();
|
||||||
|
return ((b1 << 8) | (b2 & 0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void write4(OutputStream out, int v) throws IOException {
|
||||||
|
out.write((v >>> 24) & 0xFF);
|
||||||
|
out.write((v >>> 16) & 0xFF);
|
||||||
|
out.write((v >>> 8) & 0xFF);
|
||||||
|
out.write((v ) & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int read4(InputStream in) throws IOException {
|
||||||
|
int b1 = in.read();
|
||||||
|
int b2 = in.read();
|
||||||
|
int b3 = in.read();
|
||||||
|
int b4 = in.read();
|
||||||
|
if (b4 == -1) throw new EOFException();
|
||||||
|
return ((b1 << 24) | (b2 << 16) | (b3 << 8) | (b4));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void write8(OutputStream out, long v) throws IOException {
|
||||||
|
write4(out, (int) (v >>> 32) & 0xFFFFFFFF);
|
||||||
|
write4(out, (int) (v ) & 0xFFFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long read8(InputStream in) throws IOException {
|
||||||
|
long b1 = in.read();
|
||||||
|
long b2 = in.read();
|
||||||
|
long b3 = in.read();
|
||||||
|
long b4 = in.read();
|
||||||
|
long b5 = in.read();
|
||||||
|
long b6 = in.read();
|
||||||
|
long b7 = in.read();
|
||||||
|
long b8 = in.read();
|
||||||
|
if (b8 == -1) throw new EOFException();
|
||||||
|
return ((b1 << 56) | (b2 << 48) | (b3 << 40) | (b4 << 32) |
|
||||||
|
(b5 << 24) | (b6 << 16) | (b7 << 8) | (b8));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void set4(byte[] array, int offset, int v) {
|
||||||
|
array[offset ] = (byte) ((v >>> 24) & 0xFF);
|
||||||
|
array[offset + 1] = (byte) ((v >>> 16) & 0xFF);
|
||||||
|
array[offset + 2] = (byte) ((v >>> 8) & 0xFF);
|
||||||
|
array[offset + 3] = (byte) ((v ) & 0xFF);
|
||||||
|
}
|
||||||
|
}
|
176
sgx-jvm/avian/classpath/avian/SystemClassLoader.java
Normal file
176
sgx-jvm/avian/classpath/avian/SystemClassLoader.java
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
public class SystemClassLoader extends ClassLoader {
|
||||||
|
public static native ClassLoader appLoader();
|
||||||
|
|
||||||
|
private native VMClass findVMClass(String name)
|
||||||
|
throws ClassNotFoundException;
|
||||||
|
|
||||||
|
protected Class findClass(String name) throws ClassNotFoundException {
|
||||||
|
return getClass(findVMClass(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static native Class getClass(VMClass vmClass);
|
||||||
|
|
||||||
|
public static native VMClass vmClass(Class jClass);
|
||||||
|
|
||||||
|
private native VMClass findLoadedVMClass(String name);
|
||||||
|
|
||||||
|
protected Class reallyFindLoadedClass(String name){
|
||||||
|
VMClass c = findLoadedVMClass(name);
|
||||||
|
return c == null ? null : getClass(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Class loadClass(String name, boolean resolve)
|
||||||
|
throws ClassNotFoundException
|
||||||
|
{
|
||||||
|
Class c = findLoadedClass(name);
|
||||||
|
if (c == null) {
|
||||||
|
ClassLoader parent = getParent();
|
||||||
|
if (parent != null) {
|
||||||
|
try {
|
||||||
|
c = parent.loadClass(name);
|
||||||
|
} catch (ClassNotFoundException ok) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == null) {
|
||||||
|
c = findClass(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resolve) {
|
||||||
|
resolveClass(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
private native String resourceURLPrefix(String name);
|
||||||
|
|
||||||
|
protected URL findResource(String name) {
|
||||||
|
String prefix = resourceURLPrefix(name);
|
||||||
|
if (prefix != null) {
|
||||||
|
try {
|
||||||
|
return new URL(prefix + name);
|
||||||
|
} catch (MalformedURLException ignored) { }
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Package getPackage(String name) {
|
||||||
|
Package p = super.getPackage(name);
|
||||||
|
if (p == null) {
|
||||||
|
String source = getPackageSource(name);
|
||||||
|
if (source != null) {
|
||||||
|
// todo: load attributes from JAR manifest
|
||||||
|
definePackage(name, null, null, null, null, null, null, null);
|
||||||
|
} else {
|
||||||
|
definePackage(name, null, null, null, null, null, null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.getPackage(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static native String getPackageSource(String name);
|
||||||
|
|
||||||
|
// OpenJDK's java.lang.ClassLoader.getResource makes use of
|
||||||
|
// sun.misc.Launcher to load bootstrap resources, which is not
|
||||||
|
// 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.
|
||||||
|
public URL getResource(String path) {
|
||||||
|
URL url = null;
|
||||||
|
ClassLoader parent = getParent();
|
||||||
|
if (parent != null) {
|
||||||
|
url = parent.getResource(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url == null) {
|
||||||
|
url = findResource(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
// As above, we override this method to avoid inappropriate behavior
|
||||||
|
// in OpenJDK's java.lang.ClassLoader.getResources.
|
||||||
|
public Enumeration<URL> getResources(String name) throws IOException {
|
||||||
|
Collection<URL> urls = new ArrayList<URL>(5);
|
||||||
|
|
||||||
|
ClassLoader parent = getParent();
|
||||||
|
if (parent != null) {
|
||||||
|
for (Enumeration<URL> e = parent.getResources(name);
|
||||||
|
e.hasMoreElements();)
|
||||||
|
{
|
||||||
|
urls.add(e.nextElement());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Enumeration<URL> urls2 = findResources(name);
|
||||||
|
while (urls2.hasMoreElements()) {
|
||||||
|
urls.add(urls2.nextElement());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.enumeration(urls);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ResourceEnumeration implements Enumeration<URL> {
|
||||||
|
private long[] finderElementPtrPtr;
|
||||||
|
private String name, urlPrefix;
|
||||||
|
|
||||||
|
public ResourceEnumeration(String name) {
|
||||||
|
this.name = name;
|
||||||
|
finderElementPtrPtr = new long[1];
|
||||||
|
urlPrefix = nextResourceURLPrefix();
|
||||||
|
}
|
||||||
|
|
||||||
|
private native String nextResourceURLPrefix(SystemClassLoader loader,
|
||||||
|
String name, long[] finderElementPtrPtr);
|
||||||
|
|
||||||
|
private String nextResourceURLPrefix() {
|
||||||
|
return nextResourceURLPrefix(SystemClassLoader.this, name,
|
||||||
|
finderElementPtrPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasMoreElements() {
|
||||||
|
return urlPrefix != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public URL nextElement() {
|
||||||
|
if (urlPrefix == null) throw new NoSuchElementException();
|
||||||
|
URL result;
|
||||||
|
try {
|
||||||
|
result = new URL(urlPrefix + name);
|
||||||
|
} catch (MalformedURLException ignored) {
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
if (finderElementPtrPtr[0] == 0l) urlPrefix = null;
|
||||||
|
else urlPrefix = nextResourceURLPrefix();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Enumeration<URL> findResources(String name) {
|
||||||
|
return new ResourceEnumeration(name);
|
||||||
|
}
|
||||||
|
}
|
71
sgx-jvm/avian/classpath/avian/Traces.java
Normal file
71
sgx-jvm/avian/classpath/avian/Traces.java
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.ServerSocketChannel;
|
||||||
|
import java.nio.channels.SocketChannel;
|
||||||
|
|
||||||
|
public class Traces {
|
||||||
|
private static final String Newline = System.getProperty("line.separator");
|
||||||
|
|
||||||
|
private static String traceAllThreads() {
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
|
||||||
|
Thread[] threads = new Thread[Thread.activeCount()];
|
||||||
|
|
||||||
|
int count = Thread.enumerate(threads);
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
traceThread(threads[i], buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String traceThread(Thread thread) {
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
|
||||||
|
traceThread(thread, buffer);
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void traceThread(Thread thread, StringBuilder buffer) {
|
||||||
|
buffer.append(thread).append(Newline);
|
||||||
|
for (StackTraceElement e: thread.getStackTrace()) {
|
||||||
|
buffer.append("\tat ").append(e).append(Newline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void startTraceListener(final String host, final int port) {
|
||||||
|
Thread t = new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
ServerSocketChannel server = ServerSocketChannel.open();
|
||||||
|
server.socket().bind(new InetSocketAddress(host, port));
|
||||||
|
while (true) {
|
||||||
|
SocketChannel c = server.accept();
|
||||||
|
try {
|
||||||
|
c.write(ByteBuffer.wrap(traceAllThreads().getBytes()));
|
||||||
|
} finally {
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
t.setDaemon(true);
|
||||||
|
t.start();
|
||||||
|
}
|
||||||
|
}
|
118
sgx-jvm/avian/classpath/avian/Utf8.java
Normal file
118
sgx-jvm/avian/classpath/avian/Utf8.java
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
|
||||||
|
public class Utf8 {
|
||||||
|
public static boolean test(Object data) {
|
||||||
|
if (!(data instanceof byte[])) return false;
|
||||||
|
byte[] b = (byte[])data;
|
||||||
|
for (int i = 0; i < b.length; ++i) {
|
||||||
|
if (((int)b[i] & 0x080) != 0) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] encode(char[] s16, int offset, int length) {
|
||||||
|
ByteArrayOutputStream buf = new ByteArrayOutputStream();
|
||||||
|
for (int i = offset; i < offset+length; ++i) {
|
||||||
|
char c = s16[i];
|
||||||
|
if (c == '\u0000') { // null char
|
||||||
|
buf.write(0);
|
||||||
|
buf.write(0);
|
||||||
|
} else if (c < 0x080) { // 1 byte char
|
||||||
|
buf.write(c);
|
||||||
|
} else if (c < 0x0800) { // 2 byte char
|
||||||
|
buf.write(0x0c0 | (c >>> 6));
|
||||||
|
buf.write(0x080 | (c & 0x03f));
|
||||||
|
} else { // 3 byte char
|
||||||
|
buf.write(0x0e0 | ((c >>> 12) & 0x0f));
|
||||||
|
buf.write(0x080 | ((c >>> 6) & 0x03f));
|
||||||
|
buf.write(0x080 | (c & 0x03f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object decode(byte[] s8, int offset, int length) {
|
||||||
|
Object buf = new byte[length];
|
||||||
|
boolean isMultiByte = false;
|
||||||
|
int i=offset, j=0;
|
||||||
|
while (i < offset+length) {
|
||||||
|
int x = s8[i++];
|
||||||
|
if ((x & 0x080) == 0x0) { // 1 byte char
|
||||||
|
if (x == 0) { // 2 byte null char
|
||||||
|
if (i == offset + length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
++ i;
|
||||||
|
}
|
||||||
|
cram(buf, j++, x);
|
||||||
|
} else if ((x & 0x0e0) == 0x0c0) { // 2 byte char
|
||||||
|
if (i == offset + length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isMultiByte) {
|
||||||
|
buf = widen(buf, j, length-1);
|
||||||
|
isMultiByte = true;
|
||||||
|
}
|
||||||
|
int y = s8[i++];
|
||||||
|
cram(buf, j++, ((x & 0x1f) << 6) | (y & 0x3f));
|
||||||
|
} else if ((x & 0x0f0) == 0x0e0) { // 3 byte char
|
||||||
|
if (i + 1 >= offset + length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isMultiByte) {
|
||||||
|
buf = widen(buf, j, length-2);
|
||||||
|
isMultiByte = true;
|
||||||
|
}
|
||||||
|
int y = s8[i++]; int z = s8[i++];
|
||||||
|
cram(buf, j++, ((x & 0xf) << 12) | ((y & 0x3f) << 6) | (z & 0x3f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return trim(buf, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static char[] decode16(byte[] s8, int offset, int length) {
|
||||||
|
Object decoded = decode(s8, offset, length);
|
||||||
|
if (decoded == null) {
|
||||||
|
return null;
|
||||||
|
} else if (decoded instanceof char[]) {
|
||||||
|
return (char[])decoded;
|
||||||
|
} else {
|
||||||
|
return (char[])widen(decoded, length, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void cram(Object data, int index, int val) {
|
||||||
|
if (data instanceof byte[]) ((byte[])data)[index] = (byte)val;
|
||||||
|
else ((char[])data)[index] = (char)val;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object widen(Object data, int length, int capacity) {
|
||||||
|
byte[] src = (byte[])data;
|
||||||
|
char[] result = new char[capacity];
|
||||||
|
for (int i = 0; i < length; ++i) result[i] = (char)((int)src[i] & 0x0ff);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object trim(Object data, int length) {
|
||||||
|
if (data instanceof byte[]) return data;
|
||||||
|
if (((char[])data).length == length) return data;
|
||||||
|
char[] result = new char[length];
|
||||||
|
System.arraycopy(data, 0, result, 0, length);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
42
sgx-jvm/avian/classpath/avian/VMClass.java
Normal file
42
sgx-jvm/avian/classpath/avian/VMClass.java
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class VMClass {
|
||||||
|
public short flags;
|
||||||
|
public short vmFlags;
|
||||||
|
public short fixedSize;
|
||||||
|
public byte arrayElementSize;
|
||||||
|
public byte arrayDimensions;
|
||||||
|
public VMClass arrayElementClass;
|
||||||
|
public int runtimeDataIndex;
|
||||||
|
public int[] objectMask;
|
||||||
|
public byte[] name;
|
||||||
|
public byte[] sourceFile;
|
||||||
|
public VMClass super_;
|
||||||
|
public Object[] interfaceTable;
|
||||||
|
public VMMethod[] virtualTable;
|
||||||
|
public VMField[] fieldTable;
|
||||||
|
/**
|
||||||
|
* Methods declared in this class, plus any abstract virtual methods
|
||||||
|
* inherited from implemented or extended interfaces. If addendum
|
||||||
|
* is non-null and addendum.declaredMethodCount is non-negative,
|
||||||
|
* then the first addendum.declaredMethodCount methods are declared
|
||||||
|
* methods, while the rest are abstract virtual methods. If
|
||||||
|
* addendum is null or addendum.declaredMethodCount is negative, all
|
||||||
|
* are declared methods.
|
||||||
|
*/
|
||||||
|
public VMMethod[] methodTable;
|
||||||
|
public ClassAddendum addendum;
|
||||||
|
public Singleton staticTable;
|
||||||
|
public ClassLoader loader;
|
||||||
|
public byte[] source;
|
||||||
|
}
|
23
sgx-jvm/avian/classpath/avian/VMField.java
Normal file
23
sgx-jvm/avian/classpath/avian/VMField.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class VMField {
|
||||||
|
public byte vmFlags;
|
||||||
|
public byte code;
|
||||||
|
public short flags;
|
||||||
|
public short offset;
|
||||||
|
public int nativeID;
|
||||||
|
public byte[] name;
|
||||||
|
public byte[] spec;
|
||||||
|
public FieldAddendum addendum;
|
||||||
|
public VMClass class_;
|
||||||
|
}
|
31
sgx-jvm/avian/classpath/avian/VMMethod.java
Normal file
31
sgx-jvm/avian/classpath/avian/VMMethod.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class VMMethod {
|
||||||
|
public byte vmFlags;
|
||||||
|
public byte returnCode;
|
||||||
|
public byte parameterCount;
|
||||||
|
public byte parameterFootprint;
|
||||||
|
public short flags;
|
||||||
|
public short offset;
|
||||||
|
public int nativeID;
|
||||||
|
public int runtimeDataIndex;
|
||||||
|
public byte[] name;
|
||||||
|
public byte[] spec;
|
||||||
|
public MethodAddendum addendum;
|
||||||
|
public VMClass class_;
|
||||||
|
public Code code;
|
||||||
|
|
||||||
|
public boolean hasAnnotations() {
|
||||||
|
return addendum != null && addendum.annotationTable != null;
|
||||||
|
}
|
||||||
|
}
|
111
sgx-jvm/avian/classpath/avian/avianvmresource/Handler.java
Normal file
111
sgx-jvm/avian/classpath/avian/avianvmresource/Handler.java
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/* 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.avianvmresource;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLStreamHandler;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class Handler extends URLStreamHandler {
|
||||||
|
protected URLConnection openConnection(URL url) {
|
||||||
|
return new ResourceConnection(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ResourceConnection extends URLConnection {
|
||||||
|
public ResourceConnection(URL url) {
|
||||||
|
super(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getContentLength() {
|
||||||
|
return ResourceInputStream.getContentLength(url.getFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream getInputStream() throws IOException {
|
||||||
|
return new ResourceInputStream(url.getFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connect() {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ResourceInputStream extends InputStream {
|
||||||
|
private long peer;
|
||||||
|
private int position;
|
||||||
|
|
||||||
|
public ResourceInputStream(String path) throws IOException {
|
||||||
|
peer = open(path);
|
||||||
|
if (peer == 0) {
|
||||||
|
throw new FileNotFoundException(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native int getContentLength(String path);
|
||||||
|
|
||||||
|
private static native long open(String path) throws IOException;
|
||||||
|
|
||||||
|
private static native int read(long peer, int position) throws IOException;
|
||||||
|
|
||||||
|
private static native int read(long peer, int position,
|
||||||
|
byte[] b, int offset, int length)
|
||||||
|
throws IOException;
|
||||||
|
|
||||||
|
public static native void close(long peer) throws IOException;
|
||||||
|
|
||||||
|
public static native int available(long peer, int position);
|
||||||
|
|
||||||
|
public int available() {
|
||||||
|
return available(peer, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read() throws IOException {
|
||||||
|
if (peer != 0) {
|
||||||
|
int c = read(peer, position);
|
||||||
|
if (c >= 0) {
|
||||||
|
++ position;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
} else {
|
||||||
|
throw new IOException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(byte[] b, int offset, int length) throws IOException {
|
||||||
|
if (peer != 0) {
|
||||||
|
if (b == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset < 0 || offset + length > b.length) {
|
||||||
|
throw new ArrayIndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
|
||||||
|
int c = read(peer, position, b, offset, length);
|
||||||
|
if (c >= 0) {
|
||||||
|
position += c;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
} else {
|
||||||
|
throw new IOException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
if (peer != 0) {
|
||||||
|
close(peer);
|
||||||
|
peer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
44
sgx-jvm/avian/classpath/avian/file/Handler.java
Normal file
44
sgx-jvm/avian/classpath/avian/file/Handler.java
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/* 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.file;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLStreamHandler;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class Handler extends URLStreamHandler {
|
||||||
|
protected URLConnection openConnection(URL url) {
|
||||||
|
return new FileURLConnection(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class FileURLConnection extends URLConnection {
|
||||||
|
public FileURLConnection(URL url) {
|
||||||
|
super(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getContentLength() {
|
||||||
|
return (int) new File(url.getFile()).length();
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream getInputStream() throws IOException {
|
||||||
|
return new FileInputStream(new File(url.getFile()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connect() {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
120
sgx-jvm/avian/classpath/avian/http/Handler.java
Normal file
120
sgx-jvm/avian/classpath/avian/http/Handler.java
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/* 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.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class Handler extends URLStreamHandler
|
||||||
|
{
|
||||||
|
public URLConnection openConnection(URL url) throws IOException
|
||||||
|
{
|
||||||
|
return new HttpURLConnection(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
class HttpURLConnection extends URLConnection
|
||||||
|
{
|
||||||
|
Socket socket;
|
||||||
|
private BufferedWriter writer;
|
||||||
|
private InputStream bin;
|
||||||
|
private Map<String,String> header = new HashMap<String, 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)
|
||||||
|
{
|
||||||
|
header.put(line.substring(0, i), line.substring(i + 1) .trim());
|
||||||
|
}
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
84
sgx-jvm/avian/classpath/avian/jar/Handler.java
Normal file
84
sgx-jvm/avian/classpath/avian/jar/Handler.java
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/* 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.jar;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URLStreamHandler;
|
||||||
|
import java.net.JarURLConnection;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
|
import java.util.jar.JarEntry;
|
||||||
|
|
||||||
|
public class Handler extends URLStreamHandler {
|
||||||
|
protected URLConnection openConnection(URL url) {
|
||||||
|
return new MyJarURLConnection(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void parseURL(URL url, String s, int start, int end)
|
||||||
|
throws MalformedURLException
|
||||||
|
{
|
||||||
|
// skip "jar:"
|
||||||
|
s = s.toString().substring(4);
|
||||||
|
int index = s.indexOf("!/");
|
||||||
|
if (index < 0) {
|
||||||
|
throw new MalformedURLException();
|
||||||
|
}
|
||||||
|
|
||||||
|
URL file = new URL(s.substring(0, index));
|
||||||
|
if (! "file".equals(file.getProtocol())) {
|
||||||
|
throw new RuntimeException
|
||||||
|
("protocol " + file.getProtocol() + " not yet supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
url.set("jar", null, -1, s, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MyJarURLConnection extends JarURLConnection {
|
||||||
|
private final JarFile file;
|
||||||
|
private final JarEntry entry;
|
||||||
|
|
||||||
|
public MyJarURLConnection(URL url) {
|
||||||
|
super(url);
|
||||||
|
|
||||||
|
String s = url.getFile();
|
||||||
|
int index = s.indexOf("!/");
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.file = new JarFile(new URL(s.substring(0, index)).getFile());
|
||||||
|
this.entry = this.file.getJarEntry(s.substring(index + 2));
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public JarFile getJarFile() throws IOException {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getContentLength() {
|
||||||
|
return (int)entry.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream getInputStream() throws IOException {
|
||||||
|
return file.getInputStream(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connect() {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package dalvik.system;
|
||||||
|
|
||||||
|
public class BaseDexClassLoader extends ClassLoader {
|
||||||
|
public native String getLdLibraryPath();
|
||||||
|
}
|
1015
sgx-jvm/avian/classpath/java-io.cpp
Normal file
1015
sgx-jvm/avian/classpath/java-io.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1253
sgx-jvm/avian/classpath/java-lang.cpp
Normal file
1253
sgx-jvm/avian/classpath/java-lang.cpp
Normal file
File diff suppressed because it is too large
Load Diff
145
sgx-jvm/avian/classpath/java-net.cpp
Normal file
145
sgx-jvm/avian/classpath/java-net.cpp
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
/* 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
|
1102
sgx-jvm/avian/classpath/java-nio.cpp
Normal file
1102
sgx-jvm/avian/classpath/java-nio.cpp
Normal file
File diff suppressed because it is too large
Load Diff
172
sgx-jvm/avian/classpath/java-util-zip.cpp
Normal file
172
sgx-jvm/avian/classpath/java-util-zip.cpp
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
/* 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. */
|
||||||
|
|
||||||
|
#include "stdlib.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "avian/zlib-custom.h"
|
||||||
|
|
||||||
|
#include "jni.h"
|
||||||
|
#include "jni-util.h"
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jlong JNICALL
|
||||||
|
Java_java_util_zip_Inflater_make(JNIEnv* e, jclass, jboolean nowrap)
|
||||||
|
{
|
||||||
|
z_stream* s = static_cast<z_stream*>(malloc(sizeof(z_stream)));
|
||||||
|
if (s == 0) {
|
||||||
|
throwNew(e, "java/lang/OutOfMemoryError", 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(s, 0, sizeof(z_stream));
|
||||||
|
|
||||||
|
int r = inflateInit2(s, (nowrap ? -15 : 15));
|
||||||
|
if (r != Z_OK) {
|
||||||
|
free(s);
|
||||||
|
throwNew(e, "java/lang/RuntimeException", zError(r));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<jlong>(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Java_java_util_zip_Inflater_dispose(JNIEnv*, jclass, jlong peer)
|
||||||
|
{
|
||||||
|
z_stream* s = reinterpret_cast<z_stream*>(peer);
|
||||||
|
inflateEnd(s);
|
||||||
|
free(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Java_java_util_zip_Inflater_inflate(JNIEnv* e,
|
||||||
|
jclass,
|
||||||
|
jlong peer,
|
||||||
|
jbyteArray input,
|
||||||
|
jint inputOffset,
|
||||||
|
jint inputLength,
|
||||||
|
jbyteArray output,
|
||||||
|
jint outputOffset,
|
||||||
|
jint outputLength,
|
||||||
|
jintArray results)
|
||||||
|
{
|
||||||
|
z_stream* s = reinterpret_cast<z_stream*>(peer);
|
||||||
|
|
||||||
|
jbyte* in = static_cast<jbyte*>(malloc(inputLength));
|
||||||
|
if (in == 0) {
|
||||||
|
throwNew(e, "java/lang/OutOfMemoryError", 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
jbyte* out = static_cast<jbyte*>(malloc(outputLength));
|
||||||
|
if (out == 0) {
|
||||||
|
free(in);
|
||||||
|
throwNew(e, "java/lang/OutOfMemoryError", 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e->GetByteArrayRegion(input, inputOffset, inputLength, in);
|
||||||
|
|
||||||
|
s->next_in = reinterpret_cast<Bytef*>(in);
|
||||||
|
s->avail_in = inputLength;
|
||||||
|
s->next_out = reinterpret_cast<Bytef*>(out);
|
||||||
|
s->avail_out = outputLength;
|
||||||
|
|
||||||
|
int r = inflate(s, Z_SYNC_FLUSH);
|
||||||
|
jint resultArray[3] = {r,
|
||||||
|
static_cast<jint>(inputLength - s->avail_in),
|
||||||
|
static_cast<jint>(outputLength - s->avail_out)};
|
||||||
|
|
||||||
|
free(in);
|
||||||
|
|
||||||
|
e->SetByteArrayRegion(output, outputOffset, resultArray[2], out);
|
||||||
|
free(out);
|
||||||
|
|
||||||
|
e->SetIntArrayRegion(results, 0, 3, resultArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jlong JNICALL
|
||||||
|
Java_java_util_zip_Deflater_make(JNIEnv* e,
|
||||||
|
jclass,
|
||||||
|
jboolean nowrap,
|
||||||
|
jint level)
|
||||||
|
{
|
||||||
|
z_stream* s = static_cast<z_stream*>(malloc(sizeof(z_stream)));
|
||||||
|
if (s == 0) {
|
||||||
|
throwNew(e, "java/lang/OutOfMemoryError", 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(s, 0, sizeof(z_stream));
|
||||||
|
|
||||||
|
int r = deflateInit2(s, level, (nowrap ? -15 : 15));
|
||||||
|
if (r != Z_OK) {
|
||||||
|
free(s);
|
||||||
|
throwNew(e, "java/lang/RuntimeException", zError(r));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<jlong>(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Java_java_util_zip_Deflater_dispose(JNIEnv*, jclass, jlong peer)
|
||||||
|
{
|
||||||
|
z_stream* s = reinterpret_cast<z_stream*>(peer);
|
||||||
|
deflateEnd(s);
|
||||||
|
free(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Java_java_util_zip_Deflater_deflate(JNIEnv* e,
|
||||||
|
jclass,
|
||||||
|
jlong peer,
|
||||||
|
jbyteArray input,
|
||||||
|
jint inputOffset,
|
||||||
|
jint inputLength,
|
||||||
|
jbyteArray output,
|
||||||
|
jint outputOffset,
|
||||||
|
jint outputLength,
|
||||||
|
jboolean finish,
|
||||||
|
jintArray results)
|
||||||
|
{
|
||||||
|
z_stream* s = reinterpret_cast<z_stream*>(peer);
|
||||||
|
|
||||||
|
jbyte* in = static_cast<jbyte*>(malloc(inputLength));
|
||||||
|
if (in == 0) {
|
||||||
|
throwNew(e, "java/lang/OutOfMemoryError", 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
jbyte* out = static_cast<jbyte*>(malloc(outputLength));
|
||||||
|
if (out == 0) {
|
||||||
|
free(in);
|
||||||
|
throwNew(e, "java/lang/OutOfMemoryError", 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e->GetByteArrayRegion(input, inputOffset, inputLength, in);
|
||||||
|
|
||||||
|
s->next_in = reinterpret_cast<Bytef*>(in);
|
||||||
|
s->avail_in = inputLength;
|
||||||
|
s->next_out = reinterpret_cast<Bytef*>(out);
|
||||||
|
s->avail_out = outputLength;
|
||||||
|
|
||||||
|
int r = deflate(s, finish ? Z_FINISH : Z_NO_FLUSH);
|
||||||
|
jint resultArray[3] = {r,
|
||||||
|
static_cast<jint>(inputLength - s->avail_in),
|
||||||
|
static_cast<jint>(outputLength - s->avail_out)};
|
||||||
|
|
||||||
|
free(in);
|
||||||
|
|
||||||
|
e->SetByteArrayRegion(output, outputOffset, resultArray[2], out);
|
||||||
|
free(out);
|
||||||
|
|
||||||
|
e->SetIntArrayRegion(results, 0, 3, resultArray);
|
||||||
|
}
|
58
sgx-jvm/avian/classpath/java-util.cpp
Normal file
58
sgx-jvm/avian/classpath/java-util.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/* 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. */
|
||||||
|
|
||||||
|
#include "time.h"
|
||||||
|
#include "jni.h"
|
||||||
|
#include "jni-util.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
#if (!defined PLATFORM_WINDOWS) || (defined _MSC_VER)
|
||||||
|
|
||||||
|
void removeNewline(char* s)
|
||||||
|
{
|
||||||
|
for (; s; ++s) {
|
||||||
|
if (*s == '\n') {
|
||||||
|
*s = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jstring JNICALL
|
||||||
|
Java_java_util_Date_toString(JNIEnv* e, jclass c UNUSED, jlong when)
|
||||||
|
{
|
||||||
|
const unsigned BufferSize UNUSED = 27;
|
||||||
|
|
||||||
|
time_t time = when / 1000;
|
||||||
|
|
||||||
|
#ifdef PLATFORM_WINDOWS
|
||||||
|
e->MonitorEnter(c);
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
char buffer[BufferSize];
|
||||||
|
ctime_s(buffer, BufferSize, &time);
|
||||||
|
removeNewline(buffer);
|
||||||
|
#else
|
||||||
|
char* buffer = ctime(&time);
|
||||||
|
#endif
|
||||||
|
jstring r = e->NewStringUTF(buffer);
|
||||||
|
e->MonitorExit(c);
|
||||||
|
return r;
|
||||||
|
#else
|
||||||
|
char buffer[BufferSize];
|
||||||
|
ctime_r(&time, buffer);
|
||||||
|
removeNewline(buffer);
|
||||||
|
return e->NewStringUTF(buffer);
|
||||||
|
#endif
|
||||||
|
}
|
88
sgx-jvm/avian/classpath/java/io/BufferedInputStream.java
Normal file
88
sgx-jvm/avian/classpath/java/io/BufferedInputStream.java
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/* 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.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class BufferedInputStream extends InputStream {
|
||||||
|
private final InputStream in;
|
||||||
|
private final byte[] buffer;
|
||||||
|
private int position;
|
||||||
|
private int limit;
|
||||||
|
|
||||||
|
public BufferedInputStream(InputStream in, int size) {
|
||||||
|
this.in = in;
|
||||||
|
this.buffer = new byte[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
public BufferedInputStream(InputStream in) {
|
||||||
|
this(in, 4096);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int fill() throws IOException {
|
||||||
|
position = 0;
|
||||||
|
limit = in.read(buffer);
|
||||||
|
|
||||||
|
return limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read() throws IOException {
|
||||||
|
if (position >= limit && fill() == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer[position++] & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(byte[] b, int offset, int length) throws IOException {
|
||||||
|
int count = 0;
|
||||||
|
if (position >= limit && fill() == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (position < limit) {
|
||||||
|
int remaining = limit - position;
|
||||||
|
if (remaining > length) {
|
||||||
|
remaining = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.arraycopy(buffer, position, b, offset, remaining);
|
||||||
|
|
||||||
|
count += remaining;
|
||||||
|
position += remaining;
|
||||||
|
offset += remaining;
|
||||||
|
length -= remaining;
|
||||||
|
}
|
||||||
|
while (length > 0 && in.available() > 0)
|
||||||
|
{
|
||||||
|
int c = in.read(b, offset, length);
|
||||||
|
if (c == -1) {
|
||||||
|
if (count == 0) {
|
||||||
|
count = -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
offset += c;
|
||||||
|
count += c;
|
||||||
|
length -= c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int available() throws IOException {
|
||||||
|
return in.available() + (limit - position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
61
sgx-jvm/avian/classpath/java/io/BufferedOutputStream.java
Normal file
61
sgx-jvm/avian/classpath/java/io/BufferedOutputStream.java
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class BufferedOutputStream extends OutputStream {
|
||||||
|
private final OutputStream out;
|
||||||
|
private final byte[] buffer;
|
||||||
|
private int position;
|
||||||
|
|
||||||
|
public BufferedOutputStream(OutputStream out, int size) {
|
||||||
|
this.out = out;
|
||||||
|
this.buffer = new byte[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
public BufferedOutputStream(OutputStream out) {
|
||||||
|
this(out, 4096);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drain() throws IOException {
|
||||||
|
if (position > 0) {
|
||||||
|
out.write(buffer, 0, position);
|
||||||
|
position = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(int c) throws IOException {
|
||||||
|
if (position >= buffer.length) {
|
||||||
|
drain();
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[position++] = (byte) (c & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(byte[] b, int offset, int length) throws IOException {
|
||||||
|
if (length > buffer.length - position) {
|
||||||
|
drain();
|
||||||
|
out.write(b, offset, length);
|
||||||
|
} else {
|
||||||
|
System.arraycopy(b, offset, buffer, position, length);
|
||||||
|
position += length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flush() throws IOException {
|
||||||
|
drain();
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
flush();
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
}
|
101
sgx-jvm/avian/classpath/java/io/BufferedReader.java
Normal file
101
sgx-jvm/avian/classpath/java/io/BufferedReader.java
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class BufferedReader extends Reader {
|
||||||
|
private final Reader in;
|
||||||
|
private final char[] buffer;
|
||||||
|
private int position;
|
||||||
|
private int limit;
|
||||||
|
|
||||||
|
public BufferedReader(Reader in, int bufferSize) {
|
||||||
|
this.in = in;
|
||||||
|
this.buffer = new char[bufferSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
public BufferedReader(Reader in) {
|
||||||
|
this(in, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fill() throws IOException {
|
||||||
|
position = 0;
|
||||||
|
limit = in.read(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String readLine() throws IOException {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
while (true) {
|
||||||
|
if (position >= limit) {
|
||||||
|
fill();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position >= limit) {
|
||||||
|
return sb.length() == 0 ? null : sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = position; i < limit; ++i) {
|
||||||
|
if(buffer[i] == '\r') {
|
||||||
|
sb.append(buffer, position, i - position);
|
||||||
|
position = i + 1;
|
||||||
|
if(i+1 < limit && buffer[i+1] == '\n') {
|
||||||
|
position = i + 2;
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
} else if (buffer[i] == '\n') {
|
||||||
|
sb.append(buffer, position, i - position);
|
||||||
|
position = i + 1;
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append(buffer, position, limit-position);
|
||||||
|
position = limit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(char[] b, int offset, int length) throws IOException {
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
if (position >= limit && length < buffer.length) {
|
||||||
|
fill();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position < limit) {
|
||||||
|
int remaining = limit - position;
|
||||||
|
if (remaining > length) {
|
||||||
|
remaining = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.arraycopy(buffer, position, b, offset, remaining);
|
||||||
|
|
||||||
|
count += remaining;
|
||||||
|
position += remaining;
|
||||||
|
offset += remaining;
|
||||||
|
length -= remaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length > 0) {
|
||||||
|
int c = in.read(b, offset, length);
|
||||||
|
if (c == -1) {
|
||||||
|
if (count == 0) {
|
||||||
|
count = -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
count += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
}
|
53
sgx-jvm/avian/classpath/java/io/BufferedWriter.java
Normal file
53
sgx-jvm/avian/classpath/java/io/BufferedWriter.java
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class BufferedWriter extends Writer {
|
||||||
|
private final Writer out;
|
||||||
|
private final char[] buffer;
|
||||||
|
private int position;
|
||||||
|
|
||||||
|
public BufferedWriter(Writer out, int size) {
|
||||||
|
this.out = out;
|
||||||
|
this.buffer = new char[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
public BufferedWriter(Writer out) {
|
||||||
|
this(out, 4096);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drain() throws IOException {
|
||||||
|
if (position > 0) {
|
||||||
|
out.write(buffer, 0, position);
|
||||||
|
position = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(char[] b, int offset, int length) throws IOException {
|
||||||
|
if (length > buffer.length - position) {
|
||||||
|
drain();
|
||||||
|
out.write(b, offset, length);
|
||||||
|
} else {
|
||||||
|
System.arraycopy(b, offset, buffer, position, length);
|
||||||
|
position += length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flush() throws IOException {
|
||||||
|
drain();
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
flush();
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
}
|
55
sgx-jvm/avian/classpath/java/io/ByteArrayInputStream.java
Normal file
55
sgx-jvm/avian/classpath/java/io/ByteArrayInputStream.java
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class ByteArrayInputStream extends InputStream {
|
||||||
|
private final byte[] array;
|
||||||
|
private int position;
|
||||||
|
private final int limit;
|
||||||
|
|
||||||
|
public ByteArrayInputStream(byte[] array, int offset, int length) {
|
||||||
|
this.array = array;
|
||||||
|
position = offset;
|
||||||
|
this.limit = offset + length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteArrayInputStream(byte[] array) {
|
||||||
|
this(array, 0, array.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read() {
|
||||||
|
if (position < limit) {
|
||||||
|
return array[position++] & 0xff;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(byte[] buffer, int offset, int bufferLength) {
|
||||||
|
if (bufferLength == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (position >= limit) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int remaining = limit-position;
|
||||||
|
if (remaining < bufferLength) {
|
||||||
|
bufferLength = remaining;
|
||||||
|
}
|
||||||
|
System.arraycopy(array, position, buffer, offset, bufferLength);
|
||||||
|
position += bufferLength;
|
||||||
|
return bufferLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int available() {
|
||||||
|
return limit - position;
|
||||||
|
}
|
||||||
|
}
|
148
sgx-jvm/avian/classpath/java/io/ByteArrayOutputStream.java
Normal file
148
sgx-jvm/avian/classpath/java/io/ByteArrayOutputStream.java
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class ByteArrayOutputStream extends OutputStream {
|
||||||
|
private static final int BufferSize = 32;
|
||||||
|
|
||||||
|
private Cell firstCell;
|
||||||
|
private Cell curCell;
|
||||||
|
private int length;
|
||||||
|
private byte[] buffer;
|
||||||
|
private int position;
|
||||||
|
|
||||||
|
public ByteArrayOutputStream(int capacity) { }
|
||||||
|
|
||||||
|
public ByteArrayOutputStream() {
|
||||||
|
this(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
firstCell = null;
|
||||||
|
curCell = null;
|
||||||
|
length = 0;
|
||||||
|
buffer = null;
|
||||||
|
position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(int c) {
|
||||||
|
if (buffer == null) {
|
||||||
|
buffer = new byte[BufferSize];
|
||||||
|
} else if (position >= buffer.length) {
|
||||||
|
flushBuffer();
|
||||||
|
buffer = new byte[BufferSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[position++] = (byte) (c & 0xFF);
|
||||||
|
++ length;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] copy(byte[] b, int offset, int length) {
|
||||||
|
byte[] array = new byte[length];
|
||||||
|
System.arraycopy(b, offset, array, 0, length);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(byte[] b, int offset, int length) {
|
||||||
|
if (b == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset < 0 || offset + length > b.length) {
|
||||||
|
throw new ArrayIndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length == 0) return;
|
||||||
|
|
||||||
|
if (buffer != null && length <= buffer.length - position) {
|
||||||
|
System.arraycopy(b, offset, buffer, position, length);
|
||||||
|
position += length;
|
||||||
|
} else {
|
||||||
|
flushBuffer();
|
||||||
|
chainCell( new Cell(copy(b, offset, length), 0, length) );
|
||||||
|
}
|
||||||
|
|
||||||
|
this.length += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void chainCell(Cell cell){
|
||||||
|
if (curCell == null){
|
||||||
|
firstCell = cell;
|
||||||
|
curCell = cell;
|
||||||
|
}else{
|
||||||
|
curCell.next = cell;
|
||||||
|
curCell = cell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void flushBuffer() {
|
||||||
|
if (position > 0) {
|
||||||
|
byte[] b = buffer;
|
||||||
|
int p = position;
|
||||||
|
buffer = null;
|
||||||
|
position = 0;
|
||||||
|
|
||||||
|
chainCell( new Cell(b, 0, p) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] toByteArray() {
|
||||||
|
flushBuffer();
|
||||||
|
|
||||||
|
byte[] array = new byte[length];
|
||||||
|
int pos = 0;
|
||||||
|
for (Cell c = firstCell; c != null; c = c.next) {
|
||||||
|
System.arraycopy(c.array, c.offset, array, pos, c.length);
|
||||||
|
pos += c.length;
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void writeTo(OutputStream out) throws IOException {
|
||||||
|
if (length==0) return;
|
||||||
|
|
||||||
|
if (out == null){
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
|
||||||
|
flushBuffer();
|
||||||
|
|
||||||
|
for (Cell c = firstCell; c != null; c = c.next) {
|
||||||
|
out.write(c.array, c.offset, c.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new String(toByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString(String encoding) throws UnsupportedEncodingException {
|
||||||
|
return new String(toByteArray(), encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Cell {
|
||||||
|
public byte[] array;
|
||||||
|
public int offset;
|
||||||
|
public int length;
|
||||||
|
public Cell next = null;
|
||||||
|
|
||||||
|
public Cell(byte[] array, int offset, int length) {
|
||||||
|
this.array = array;
|
||||||
|
this.offset = offset;
|
||||||
|
this.length = length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
sgx-jvm/avian/classpath/java/io/Closeable.java
Normal file
16
sgx-jvm/avian/classpath/java/io/Closeable.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public interface Closeable extends AutoCloseable {
|
||||||
|
void close()
|
||||||
|
throws IOException;
|
||||||
|
}
|
29
sgx-jvm/avian/classpath/java/io/DataInput.java
Normal file
29
sgx-jvm/avian/classpath/java/io/DataInput.java
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public interface DataInput {
|
||||||
|
boolean readBoolean() throws IOException;
|
||||||
|
byte readByte() throws IOException;
|
||||||
|
char readChar() throws IOException;
|
||||||
|
double readDouble() throws IOException;
|
||||||
|
float readFloat() throws IOException;
|
||||||
|
void readFully(byte[] b) throws IOException;
|
||||||
|
void readFully(byte[] b, int off, int len) throws IOException;
|
||||||
|
int readInt() throws IOException;
|
||||||
|
String readLine() throws IOException;
|
||||||
|
long readLong() throws IOException;
|
||||||
|
short readShort() throws IOException;
|
||||||
|
int readUnsignedByte() throws IOException;
|
||||||
|
int readUnsignedShort() throws IOException;
|
||||||
|
String readUTF() throws IOException;
|
||||||
|
int skipBytes(int n) throws IOException;
|
||||||
|
}
|
132
sgx-jvm/avian/classpath/java/io/DataInputStream.java
Normal file
132
sgx-jvm/avian/classpath/java/io/DataInputStream.java
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class DataInputStream extends InputStream implements DataInput {
|
||||||
|
private InputStream in;
|
||||||
|
|
||||||
|
public DataInputStream(InputStream in) {
|
||||||
|
this.in = in;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(byte[] buffer) throws IOException {
|
||||||
|
return in.read(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(byte[] buffer, int offset, int length) throws IOException {
|
||||||
|
return in.read(buffer, 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 int read() throws IOException {
|
||||||
|
return in.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int read0() throws IOException {
|
||||||
|
int b = in.read();
|
||||||
|
if (b < 0) {
|
||||||
|
throw new EOFException();
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean readBoolean() throws IOException {
|
||||||
|
return read0() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte readByte() throws IOException {
|
||||||
|
return (byte)read0();
|
||||||
|
}
|
||||||
|
|
||||||
|
public short readShort() throws IOException {
|
||||||
|
return (short)((read0() << 8) | read0());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int readInt() throws IOException {
|
||||||
|
return ((read0() << 24) | (read0() << 16) | (read0() << 8) | read0());
|
||||||
|
}
|
||||||
|
|
||||||
|
public float readFloat() throws IOException {
|
||||||
|
return Float.floatToIntBits(readInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
public double readDouble() throws IOException {
|
||||||
|
return Double.doubleToLongBits(readLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
public long readLong() throws IOException {
|
||||||
|
return ((readInt() & 0xffffffffl) << 32) | (readInt() & 0xffffffffl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public char readChar() throws IOException {
|
||||||
|
return (char)readShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int readUnsignedByte() throws IOException {
|
||||||
|
return readByte() & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int readUnsignedShort() throws IOException {
|
||||||
|
return readShort() & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String readUTF() throws IOException {
|
||||||
|
int length = readUnsignedShort();
|
||||||
|
byte[] bytes = new byte[length];
|
||||||
|
readFully(bytes);
|
||||||
|
return new String(bytes, "UTF-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
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 int skipBytes(int n) throws IOException {
|
||||||
|
for (int count = 0; count < n; ++count) {
|
||||||
|
if (read() < 0) {;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
28
sgx-jvm/avian/classpath/java/io/DataOutput.java
Normal file
28
sgx-jvm/avian/classpath/java/io/DataOutput.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public interface DataOutput {
|
||||||
|
void write(byte[] b) throws IOException;
|
||||||
|
void write(byte[] b, int off, int len) throws IOException;
|
||||||
|
void write(int b) throws IOException;
|
||||||
|
void writeBoolean(boolean v) throws IOException;
|
||||||
|
void writeByte(int v) throws IOException;
|
||||||
|
void writeBytes(String s) throws IOException;
|
||||||
|
void writeChar(int v) throws IOException;
|
||||||
|
void writeChars(String s) throws IOException;
|
||||||
|
void writeDouble(double v) throws IOException;
|
||||||
|
void writeFloat(float v) throws IOException;
|
||||||
|
void writeInt(int v) throws IOException;
|
||||||
|
void writeLong(long v) throws IOException;
|
||||||
|
void writeShort(int v) throws IOException;
|
||||||
|
void writeUTF(String s) throws IOException;
|
||||||
|
}
|
99
sgx-jvm/avian/classpath/java/io/DataOutputStream.java
Normal file
99
sgx-jvm/avian/classpath/java/io/DataOutputStream.java
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class DataOutputStream extends OutputStream implements DataOutput {
|
||||||
|
private OutputStream out;
|
||||||
|
|
||||||
|
public DataOutputStream(OutputStream out) {
|
||||||
|
this.out = out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flush() throws IOException {
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(byte[] buffer) throws IOException {
|
||||||
|
out.write(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(byte[] buffer, int offset, int length) throws IOException {
|
||||||
|
out.write(buffer, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(int b) throws IOException {
|
||||||
|
out.write(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeBoolean(boolean b) throws IOException {
|
||||||
|
writeByte(b ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeByte(int b) throws IOException {
|
||||||
|
out.write(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeShort(int s) throws IOException {
|
||||||
|
write((byte)(s >> 8));
|
||||||
|
write((byte)s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeInt(int i) throws IOException {
|
||||||
|
write((byte)(i >> 24));
|
||||||
|
write((byte)(i >> 16));
|
||||||
|
write((byte)(i >> 8));
|
||||||
|
write((byte)i);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeFloat(float f) throws IOException {
|
||||||
|
writeInt(Float.floatToIntBits(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeDouble(double d) throws IOException {
|
||||||
|
writeLong(Double.doubleToLongBits(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeLong(long l) throws IOException {
|
||||||
|
write((byte)(l >> 56));
|
||||||
|
write((byte)(l >> 48));
|
||||||
|
write((byte)(l >> 40));
|
||||||
|
write((byte)(l >> 32));
|
||||||
|
write((byte)(l >> 24));
|
||||||
|
write((byte)(l >> 16));
|
||||||
|
write((byte)(l >> 8));
|
||||||
|
write((byte)l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeChar(int ch) throws IOException {
|
||||||
|
write((byte)(ch >> 8));
|
||||||
|
write((byte)ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeChars(String s) throws IOException {
|
||||||
|
for (char ch : s.toCharArray()) {
|
||||||
|
writeChar(ch & 0xffff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeBytes(String s) throws IOException {
|
||||||
|
out.write(s.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeUTF(String s) throws IOException {
|
||||||
|
byte[] bytes = s.getBytes("UTF-8");
|
||||||
|
writeShort((short)bytes.length);
|
||||||
|
out.write(bytes);
|
||||||
|
}
|
||||||
|
}
|
21
sgx-jvm/avian/classpath/java/io/EOFException.java
Normal file
21
sgx-jvm/avian/classpath/java/io/EOFException.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class EOFException extends IOException {
|
||||||
|
public EOFException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EOFException() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
}
|
16
sgx-jvm/avian/classpath/java/io/Externalizable.java
Normal file
16
sgx-jvm/avian/classpath/java/io/Externalizable.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public interface Externalizable {
|
||||||
|
public void readExternal(ObjectInput in);
|
||||||
|
public void writeExternal(ObjectOutput out);
|
||||||
|
}
|
335
sgx-jvm/avian/classpath/java/io/File.java
Normal file
335
sgx-jvm/avian/classpath/java/io/File.java
Normal file
@ -0,0 +1,335 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class File implements Serializable {
|
||||||
|
private static final String FileSeparator
|
||||||
|
= System.getProperty("file.separator");
|
||||||
|
|
||||||
|
private static final boolean IsWindows
|
||||||
|
= System.getProperty("os.name").equals("Windows");
|
||||||
|
|
||||||
|
public static final String separator = FileSeparator;
|
||||||
|
|
||||||
|
public static final char separatorChar = FileSeparator.charAt(0);
|
||||||
|
|
||||||
|
private static final String PathSeparator
|
||||||
|
= System.getProperty("path.separator");
|
||||||
|
|
||||||
|
public static final String pathSeparator = PathSeparator;
|
||||||
|
|
||||||
|
public static final char pathSeparatorChar = PathSeparator.charAt(0);
|
||||||
|
|
||||||
|
// static {
|
||||||
|
// System.loadLibrary("natives");
|
||||||
|
// }
|
||||||
|
|
||||||
|
private final String path;
|
||||||
|
|
||||||
|
public File(String path) {
|
||||||
|
if (path == null) throw new NullPointerException();
|
||||||
|
this.path = normalize(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public File(String parent, String child) {
|
||||||
|
this(parent + FileSeparator + child);
|
||||||
|
}
|
||||||
|
|
||||||
|
public File(File parent, String child) {
|
||||||
|
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.endsWith(FileSeparator)) {
|
||||||
|
p = p.substring(0, p.length() - 1);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String normalize(String path) {
|
||||||
|
if(IsWindows
|
||||||
|
&& path.length() > 2
|
||||||
|
&& path.charAt(0) == '/'
|
||||||
|
&& path.charAt(2) == ':')
|
||||||
|
{
|
||||||
|
// remove a leading slash on Windows
|
||||||
|
path = path.substring(1);
|
||||||
|
}
|
||||||
|
return stripSeparators
|
||||||
|
("\\".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() {
|
||||||
|
return isDirectory(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native boolean isFile(String path);
|
||||||
|
|
||||||
|
public boolean isFile() {
|
||||||
|
return isFile(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAbsolute() {
|
||||||
|
return path.equals(toAbsolutePath(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native boolean canRead(String path);
|
||||||
|
|
||||||
|
public boolean canRead() {
|
||||||
|
return canRead(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native boolean canWrite(String path);
|
||||||
|
|
||||||
|
public boolean canWrite() {
|
||||||
|
return canWrite(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native boolean canExecute(String path);
|
||||||
|
|
||||||
|
public boolean canExecute() {
|
||||||
|
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) {
|
||||||
|
return path.substring(index + 1);
|
||||||
|
} else {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParent() {
|
||||||
|
int index = path.lastIndexOf(FileSeparator);
|
||||||
|
if (index >= 0) {
|
||||||
|
return normalize(path.substring(0, index));
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getParentFile() {
|
||||||
|
String s = getParent();
|
||||||
|
return (s == null ? null : new File(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native String toCanonicalPath(String path);
|
||||||
|
|
||||||
|
public String getCanonicalPath() {
|
||||||
|
return toCanonicalPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getCanonicalFile() {
|
||||||
|
return new File(getCanonicalPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native String toAbsolutePath(String path);
|
||||||
|
|
||||||
|
public String getAbsolutePath() {
|
||||||
|
return toAbsolutePath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getAbsoluteFile() {
|
||||||
|
return new File(getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native long length(String path);
|
||||||
|
|
||||||
|
public long length() {
|
||||||
|
return length(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native boolean exists(String path);
|
||||||
|
|
||||||
|
public boolean exists() {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public File[] listFiles(FilenameFilter filter) {
|
||||||
|
String[] list = list(filter);
|
||||||
|
if (list != null) {
|
||||||
|
File[] result = new File[list.length];
|
||||||
|
for (int i = 0; i < list.length; ++i) {
|
||||||
|
result[i] = new File(this, list[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] list() {
|
||||||
|
return list(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] list(FilenameFilter filter) {
|
||||||
|
long handle = 0;
|
||||||
|
try {
|
||||||
|
handle = openDir(path);
|
||||||
|
if (handle != 0) {
|
||||||
|
Pair list = null;
|
||||||
|
int count = 0;
|
||||||
|
for (String s = readDir(handle); s != null; s = readDir(handle)) {
|
||||||
|
if (filter == null || filter.accept(this, s)) {
|
||||||
|
list = new Pair(s, list);
|
||||||
|
++ count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] result = new String[count];
|
||||||
|
for (int i = count - 1; i >= 0; --i) {
|
||||||
|
result[i] = list.value;
|
||||||
|
list = list.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (handle != 0) {
|
||||||
|
closeDir(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public long lastModified() {
|
||||||
|
return lastModified(path);
|
||||||
|
}
|
||||||
|
private static native long openDir(String path);
|
||||||
|
|
||||||
|
private static native long lastModified(String path);
|
||||||
|
|
||||||
|
private static native String readDir(long handle);
|
||||||
|
|
||||||
|
private static native void closeDir(long handle);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static class Pair {
|
||||||
|
public final String value;
|
||||||
|
public final Pair next;
|
||||||
|
|
||||||
|
public Pair(String value, Pair next) {
|
||||||
|
this.value = value;
|
||||||
|
this.next = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
27
sgx-jvm/avian/classpath/java/io/FileDescriptor.java
Normal file
27
sgx-jvm/avian/classpath/java/io/FileDescriptor.java
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class FileDescriptor {
|
||||||
|
public static final FileDescriptor in = new FileDescriptor(0);
|
||||||
|
public static final FileDescriptor out = new FileDescriptor(1);
|
||||||
|
public static final FileDescriptor err = new FileDescriptor(2);
|
||||||
|
|
||||||
|
final int value;
|
||||||
|
|
||||||
|
public FileDescriptor(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileDescriptor() {
|
||||||
|
this(-1);
|
||||||
|
}
|
||||||
|
}
|
77
sgx-jvm/avian/classpath/java/io/FileInputStream.java
Normal file
77
sgx-jvm/avian/classpath/java/io/FileInputStream.java
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class FileInputStream extends InputStream {
|
||||||
|
// static {
|
||||||
|
// System.loadLibrary("natives");
|
||||||
|
// }
|
||||||
|
|
||||||
|
private int fd;
|
||||||
|
private int remaining;
|
||||||
|
|
||||||
|
public FileInputStream(FileDescriptor fd) {
|
||||||
|
this.fd = fd.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileInputStream(String path) throws IOException {
|
||||||
|
fd = open(path);
|
||||||
|
remaining = (int) new File(path).length();
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileInputStream(File file) throws IOException {
|
||||||
|
this(file.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int available() throws IOException {
|
||||||
|
return remaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native int open(String path) throws IOException;
|
||||||
|
|
||||||
|
private static native int read(int fd) throws IOException;
|
||||||
|
|
||||||
|
private static native int read(int fd, byte[] b, int offset, int length)
|
||||||
|
throws IOException;
|
||||||
|
|
||||||
|
public static native void close(int fd) throws IOException;
|
||||||
|
|
||||||
|
public int read() throws IOException {
|
||||||
|
int c = read(fd);
|
||||||
|
if (c >= 0 && remaining > 0) {
|
||||||
|
-- remaining;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(byte[] b, int offset, int length) throws IOException {
|
||||||
|
if (b == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset < 0 || offset + length > b.length) {
|
||||||
|
throw new ArrayIndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
|
||||||
|
int c = read(fd, b, offset, length);
|
||||||
|
if (c > 0 && remaining > 0) {
|
||||||
|
remaining -= c;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
if (fd != -1) {
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
sgx-jvm/avian/classpath/java/io/FileNotFoundException.java
Normal file
21
sgx-jvm/avian/classpath/java/io/FileNotFoundException.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class FileNotFoundException extends IOException {
|
||||||
|
public FileNotFoundException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileNotFoundException() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
}
|
68
sgx-jvm/avian/classpath/java/io/FileOutputStream.java
Normal file
68
sgx-jvm/avian/classpath/java/io/FileOutputStream.java
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class FileOutputStream extends OutputStream {
|
||||||
|
// static {
|
||||||
|
// System.loadLibrary("natives");
|
||||||
|
// }
|
||||||
|
|
||||||
|
private int fd;
|
||||||
|
|
||||||
|
public FileOutputStream(FileDescriptor fd) {
|
||||||
|
this.fd = fd.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileOutputStream(String path) throws IOException {
|
||||||
|
this(path, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileOutputStream(String path, boolean append) throws IOException {
|
||||||
|
fd = open(path, append);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public FileOutputStream(File file) throws IOException {
|
||||||
|
this(file.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native int open(String path, boolean append) throws IOException;
|
||||||
|
|
||||||
|
private static native void write(int fd, int c) throws IOException;
|
||||||
|
|
||||||
|
private static native void write(int fd, byte[] b, int offset, int length)
|
||||||
|
throws IOException;
|
||||||
|
|
||||||
|
private static native void close(int fd) throws IOException;
|
||||||
|
|
||||||
|
public void write(int c) throws IOException {
|
||||||
|
write(fd, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(byte[] b, int offset, int length) throws IOException {
|
||||||
|
if (b == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset < 0 || offset + length > b.length) {
|
||||||
|
throw new ArrayIndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
|
||||||
|
write(fd, b, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
if (fd != -1) {
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
sgx-jvm/avian/classpath/java/io/FileReader.java
Normal file
39
sgx-jvm/avian/classpath/java/io/FileReader.java
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class FileReader extends Reader {
|
||||||
|
private final Reader in;
|
||||||
|
|
||||||
|
public FileReader(FileInputStream in) {
|
||||||
|
this.in = new InputStreamReader(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileReader(FileDescriptor fd) {
|
||||||
|
this(new FileInputStream(fd));
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileReader(String path) throws IOException {
|
||||||
|
this(new FileInputStream(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileReader(File file) throws IOException {
|
||||||
|
this(new FileInputStream(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(char[] b, int offset, int length) throws IOException {
|
||||||
|
return in.read(b, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
}
|
43
sgx-jvm/avian/classpath/java/io/FileWriter.java
Normal file
43
sgx-jvm/avian/classpath/java/io/FileWriter.java
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class FileWriter extends Writer {
|
||||||
|
private final Writer out;
|
||||||
|
|
||||||
|
private FileWriter(FileOutputStream out) {
|
||||||
|
this.out = new OutputStreamWriter(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileWriter(FileDescriptor fd) {
|
||||||
|
this(new FileOutputStream(fd));
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileWriter(String path) throws IOException {
|
||||||
|
this(new FileOutputStream(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileWriter(File file) throws IOException {
|
||||||
|
this(new FileOutputStream(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(char[] 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();
|
||||||
|
}
|
||||||
|
}
|
17
sgx-jvm/avian/classpath/java/io/FilenameFilter.java
Normal file
17
sgx-jvm/avian/classpath/java/io/FilenameFilter.java
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public interface FilenameFilter {
|
||||||
|
|
||||||
|
boolean accept(File dir, String name);
|
||||||
|
|
||||||
|
}
|
35
sgx-jvm/avian/classpath/java/io/FilterInputStream.java
Normal file
35
sgx-jvm/avian/classpath/java/io/FilterInputStream.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class FilterInputStream extends InputStream {
|
||||||
|
protected InputStream in;
|
||||||
|
|
||||||
|
public FilterInputStream(InputStream in) {
|
||||||
|
this.in = in;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(byte[] b) throws IOException {
|
||||||
|
return in.read(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(byte[] b, int off, int len) throws IOException {
|
||||||
|
return in.read(b, off, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read() throws IOException {
|
||||||
|
return in.read();
|
||||||
|
}
|
||||||
|
}
|
40
sgx-jvm/avian/classpath/java/io/FilterOutputStream.java
Normal file
40
sgx-jvm/avian/classpath/java/io/FilterOutputStream.java
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class FilterOutputStream extends OutputStream {
|
||||||
|
protected OutputStream out;
|
||||||
|
|
||||||
|
public FilterOutputStream(OutputStream out) {
|
||||||
|
this.out = out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flush() throws IOException {
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(byte[] b) throws IOException {
|
||||||
|
out.write(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(byte[] b, int off, int len) throws IOException {
|
||||||
|
out.write(b, off, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(int b) throws IOException {
|
||||||
|
out.write(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
51
sgx-jvm/avian/classpath/java/io/FilterReader.java
Normal file
51
sgx-jvm/avian/classpath/java/io/FilterReader.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public abstract class FilterReader extends Reader {
|
||||||
|
protected Reader in;
|
||||||
|
|
||||||
|
protected FilterReader(Reader in) {
|
||||||
|
this.in = in;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read() throws IOException {
|
||||||
|
return in.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(char[] buffer, int offset, int length) throws IOException {
|
||||||
|
return in.read(buffer, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean ready() throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long skip(long n) throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean markSupported() {
|
||||||
|
return in.markSupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mark(int readAheadLimit) throws IOException {
|
||||||
|
in.mark(readAheadLimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() throws IOException {
|
||||||
|
in.reset();
|
||||||
|
}
|
||||||
|
}
|
16
sgx-jvm/avian/classpath/java/io/Flushable.java
Normal file
16
sgx-jvm/avian/classpath/java/io/Flushable.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public interface Flushable {
|
||||||
|
void flush()
|
||||||
|
throws IOException;
|
||||||
|
}
|
29
sgx-jvm/avian/classpath/java/io/IOException.java
Normal file
29
sgx-jvm/avian/classpath/java/io/IOException.java
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class IOException extends Exception {
|
||||||
|
public IOException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IOException(String message) {
|
||||||
|
this(message, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IOException(Throwable cause) {
|
||||||
|
this(null, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IOException() {
|
||||||
|
this(null, null);
|
||||||
|
}
|
||||||
|
}
|
67
sgx-jvm/avian/classpath/java/io/InputStream.java
Normal file
67
sgx-jvm/avian/classpath/java/io/InputStream.java
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public abstract class InputStream implements Closeable {
|
||||||
|
public abstract int read() throws IOException;
|
||||||
|
|
||||||
|
public int read(byte[] buffer) throws IOException {
|
||||||
|
return read(buffer, 0, buffer.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(byte[] buffer, int offset, int length) throws IOException {
|
||||||
|
for (int i = 0; i < length; ++i) {
|
||||||
|
int c = read();
|
||||||
|
if (c == -1) {
|
||||||
|
if (i == 0) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buffer[offset + i] = (byte) (c & 0xFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long skip(long count) throws IOException {
|
||||||
|
final long Max = 8 * 1024;
|
||||||
|
int size = (int) (count < Max ? count : Max);
|
||||||
|
byte[] buffer = new byte[size];
|
||||||
|
long remaining = count;
|
||||||
|
int c;
|
||||||
|
while ((c = read(buffer, 0, (int) (size < remaining ? size : remaining)))
|
||||||
|
>= 0
|
||||||
|
&& remaining > 0) {
|
||||||
|
remaining -= c;
|
||||||
|
}
|
||||||
|
return count - remaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int available() throws IOException {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mark(int limit) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() throws IOException {
|
||||||
|
throw new IOException("mark/reset not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean markSupported() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException { }
|
||||||
|
}
|
92
sgx-jvm/avian/classpath/java/io/InputStreamReader.java
Normal file
92
sgx-jvm/avian/classpath/java/io/InputStreamReader.java
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/* 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 avian.Utf8;
|
||||||
|
|
||||||
|
public class InputStreamReader extends Reader {
|
||||||
|
private static final int MultibytePadding = 4;
|
||||||
|
|
||||||
|
private final InputStream in;
|
||||||
|
|
||||||
|
public InputStreamReader(InputStream in) {
|
||||||
|
this.in = in;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStreamReader(InputStream in, String encoding)
|
||||||
|
throws UnsupportedEncodingException
|
||||||
|
{
|
||||||
|
this(in);
|
||||||
|
|
||||||
|
if (! encoding.equals("UTF-8")) {
|
||||||
|
throw new UnsupportedEncodingException(encoding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(char[] b, int offset, int length) throws IOException {
|
||||||
|
if (length == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] buffer = new byte[length + MultibytePadding];
|
||||||
|
int bufferLength = length;
|
||||||
|
int bufferOffset = 0;
|
||||||
|
while (true) {
|
||||||
|
int c = in.read(buffer, bufferOffset, bufferLength);
|
||||||
|
|
||||||
|
if (c <= 0) {
|
||||||
|
if (bufferOffset > 0) {
|
||||||
|
// if we've reached the end of the stream while trying to
|
||||||
|
// read a multibyte character, we still need to return any
|
||||||
|
// competely-decoded characters, plus \ufffd to indicate an
|
||||||
|
// unknown character
|
||||||
|
c = 1;
|
||||||
|
while (bufferOffset > 0) {
|
||||||
|
char[] buffer16 = Utf8.decode16(buffer, 0, bufferOffset);
|
||||||
|
|
||||||
|
if (buffer16 != null) {
|
||||||
|
System.arraycopy(buffer16, 0, b, offset, buffer16.length);
|
||||||
|
|
||||||
|
c = buffer16.length + 1;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
-- bufferOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b[offset + c - 1] = '\ufffd';
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
bufferOffset += c;
|
||||||
|
|
||||||
|
char[] buffer16 = Utf8.decode16(buffer, 0, bufferOffset);
|
||||||
|
|
||||||
|
if (buffer16 != null) {
|
||||||
|
bufferOffset = 0;
|
||||||
|
|
||||||
|
System.arraycopy(buffer16, 0, b, offset, buffer16.length);
|
||||||
|
|
||||||
|
return buffer16.length;
|
||||||
|
} else {
|
||||||
|
// the buffer ended in an incomplete multibyte character, so
|
||||||
|
// we try to read a another byte at a time until it's complete
|
||||||
|
bufferLength = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
}
|
41
sgx-jvm/avian/classpath/java/io/LineNumberReader.java
Normal file
41
sgx-jvm/avian/classpath/java/io/LineNumberReader.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class LineNumberReader extends BufferedReader {
|
||||||
|
private int line;
|
||||||
|
|
||||||
|
public LineNumberReader(Reader in, int bufferSize) {
|
||||||
|
super(in, bufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LineNumberReader(Reader in) {
|
||||||
|
super(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLineNumber() {
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLineNumber(int v) {
|
||||||
|
line = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(char[] b, int offset, int length) throws IOException {
|
||||||
|
int c = super.read(b, offset, length);
|
||||||
|
for (int i = 0; i < c; ++i) {
|
||||||
|
if (b[i] == '\n') {
|
||||||
|
++ line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class NotSerializableException extends ObjectStreamException {
|
||||||
|
public NotSerializableException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotSerializableException() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
}
|
21
sgx-jvm/avian/classpath/java/io/ObjectInput.java
Normal file
21
sgx-jvm/avian/classpath/java/io/ObjectInput.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public interface ObjectInput {
|
||||||
|
public int available();
|
||||||
|
public void close();
|
||||||
|
public void read();
|
||||||
|
public void read(byte[] b);
|
||||||
|
public void read(byte[] b, int off, int len);
|
||||||
|
public Object readObject();
|
||||||
|
public long skip(long n);
|
||||||
|
}
|
443
sgx-jvm/avian/classpath/java/io/ObjectInputStream.java
Normal file
443
sgx-jvm/avian/classpath/java/io/ObjectInputStream.java
Normal file
@ -0,0 +1,443 @@
|
|||||||
|
/* 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);
|
||||||
|
}
|
20
sgx-jvm/avian/classpath/java/io/ObjectOutput.java
Normal file
20
sgx-jvm/avian/classpath/java/io/ObjectOutput.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public interface ObjectOutput {
|
||||||
|
public void close();
|
||||||
|
public void flush();
|
||||||
|
public void write(byte[] b);
|
||||||
|
public void write(byte[] b, int off, int len);
|
||||||
|
public void write(int b);
|
||||||
|
public void writeObject(Object obj);
|
||||||
|
}
|
337
sgx-jvm/avian/classpath/java/io/ObjectOutputStream.java
Normal file
337
sgx-jvm/avian/classpath/java/io/ObjectOutputStream.java
Normal file
@ -0,0 +1,337 @@
|
|||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
sgx-jvm/avian/classpath/java/io/ObjectStreamException.java
Normal file
21
sgx-jvm/avian/classpath/java/io/ObjectStreamException.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class ObjectStreamException extends IOException {
|
||||||
|
public ObjectStreamException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectStreamException() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
}
|
29
sgx-jvm/avian/classpath/java/io/OutputStream.java
Normal file
29
sgx-jvm/avian/classpath/java/io/OutputStream.java
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public abstract class OutputStream implements Closeable, Flushable {
|
||||||
|
public abstract void write(int c) throws IOException;
|
||||||
|
|
||||||
|
public void write(byte[] buffer) throws IOException {
|
||||||
|
write(buffer, 0, buffer.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(byte[] buffer, int offset, int length) throws IOException {
|
||||||
|
for (int i = 0; i < length; ++i) {
|
||||||
|
write(buffer[offset + i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flush() throws IOException { }
|
||||||
|
|
||||||
|
public void close() throws IOException { }
|
||||||
|
}
|
33
sgx-jvm/avian/classpath/java/io/OutputStreamWriter.java
Normal file
33
sgx-jvm/avian/classpath/java/io/OutputStreamWriter.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/* 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 avian.Utf8;
|
||||||
|
|
||||||
|
public class OutputStreamWriter extends Writer {
|
||||||
|
private final OutputStream out;
|
||||||
|
|
||||||
|
public OutputStreamWriter(OutputStream out) {
|
||||||
|
this.out = out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(char[] b, int offset, int length) throws IOException {
|
||||||
|
out.write(Utf8.encode(b, offset, length));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flush() throws IOException {
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
}
|
170
sgx-jvm/avian/classpath/java/io/PrintStream.java
Normal file
170
sgx-jvm/avian/classpath/java/io/PrintStream.java
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class PrintStream extends OutputStream {
|
||||||
|
private final OutputStream out;
|
||||||
|
private final boolean autoFlush;
|
||||||
|
|
||||||
|
private static class Static {
|
||||||
|
private static final byte[] newline
|
||||||
|
= System.getProperty("line.separator").getBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrintStream(OutputStream out, boolean autoFlush) {
|
||||||
|
this.out = out;
|
||||||
|
this.autoFlush = autoFlush;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrintStream(OutputStream out, boolean autoFlush, String encoding)
|
||||||
|
throws UnsupportedEncodingException
|
||||||
|
{
|
||||||
|
this.out = out;
|
||||||
|
this.autoFlush = autoFlush;
|
||||||
|
|
||||||
|
if (! (encoding.equals("UTF-8") || encoding.equals("ISO-8859-1"))) {
|
||||||
|
throw new UnsupportedEncodingException(encoding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrintStream(OutputStream out) {
|
||||||
|
this(out, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void print(String s) {
|
||||||
|
try {
|
||||||
|
out.write(s.getBytes());
|
||||||
|
if (autoFlush) flush();
|
||||||
|
} catch (IOException e) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(Object o) {
|
||||||
|
print(String.valueOf(o));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(boolean v) {
|
||||||
|
print(String.valueOf(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(char c) {
|
||||||
|
print(String.valueOf(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(int v) {
|
||||||
|
print(String.valueOf(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(long v) {
|
||||||
|
print(String.valueOf(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(float v) {
|
||||||
|
print(String.valueOf(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(double v) {
|
||||||
|
print(String.valueOf(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(char[] s) {
|
||||||
|
print(String.valueOf(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized PrintStream printf(java.util.Locale locale, String format, Object... args) {
|
||||||
|
// should this be cached in an instance variable??
|
||||||
|
final java.util.Formatter formatter = new java.util.Formatter(this);
|
||||||
|
formatter.format(locale, format, args);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized PrintStream printf(String format, Object... args) {
|
||||||
|
final java.util.Formatter formatter = new java.util.Formatter(this);
|
||||||
|
formatter.format(format, args);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrintStream format(String format, Object... args) {
|
||||||
|
return printf(format, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrintStream format(java.util.Locale locale, String format, Object... args) {
|
||||||
|
return printf(locale, format, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void println(String s) {
|
||||||
|
try {
|
||||||
|
out.write(s.getBytes());
|
||||||
|
out.write(Static.newline);
|
||||||
|
if (autoFlush) flush();
|
||||||
|
} catch (IOException e) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void println() {
|
||||||
|
try {
|
||||||
|
out.write(Static.newline);
|
||||||
|
if (autoFlush) flush();
|
||||||
|
} catch (IOException e) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void println(Object o) {
|
||||||
|
println(String.valueOf(o));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void println(boolean v) {
|
||||||
|
println(String.valueOf(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void println(char c) {
|
||||||
|
println(String.valueOf(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void println(int v) {
|
||||||
|
println(String.valueOf(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void println(long v) {
|
||||||
|
println(String.valueOf(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void println(float v) {
|
||||||
|
println(String.valueOf(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void println(double v) {
|
||||||
|
println(String.valueOf(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void println(char[] s) {
|
||||||
|
println(String.valueOf(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(int c) throws IOException {
|
||||||
|
out.write(c);
|
||||||
|
if (autoFlush && c == '\n') flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(byte[] buffer, int offset, int length) throws IOException {
|
||||||
|
out.write(buffer, offset, length);
|
||||||
|
if (autoFlush) flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flush() {
|
||||||
|
try {
|
||||||
|
out.flush();
|
||||||
|
} catch (IOException e) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
try {
|
||||||
|
out.close();
|
||||||
|
} catch (IOException e) { }
|
||||||
|
}
|
||||||
|
}
|
90
sgx-jvm/avian/classpath/java/io/PrintWriter.java
Normal file
90
sgx-jvm/avian/classpath/java/io/PrintWriter.java
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class PrintWriter extends Writer {
|
||||||
|
private static final char[] newline
|
||||||
|
= System.getProperty("line.separator").toCharArray();
|
||||||
|
|
||||||
|
private final Writer out;
|
||||||
|
private final boolean autoFlush;
|
||||||
|
|
||||||
|
public PrintWriter(Writer out, boolean autoFlush) {
|
||||||
|
this.out = out;
|
||||||
|
this.autoFlush = autoFlush;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrintWriter(Writer out) {
|
||||||
|
this(out, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrintWriter(OutputStream out, boolean autoFlush) {
|
||||||
|
this(new OutputStreamWriter(out), autoFlush);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrintWriter(OutputStream out) {
|
||||||
|
this(out, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void print(String s) {
|
||||||
|
try {
|
||||||
|
out.write(s.toCharArray());
|
||||||
|
} catch (IOException e) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(Object o) {
|
||||||
|
print(o.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(char c) {
|
||||||
|
print(String.valueOf(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void println(String s) {
|
||||||
|
try {
|
||||||
|
out.write(s.toCharArray());
|
||||||
|
out.write(newline);
|
||||||
|
if (autoFlush) flush();
|
||||||
|
} catch (IOException e) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void println() {
|
||||||
|
try {
|
||||||
|
out.write(newline);
|
||||||
|
if (autoFlush) flush();
|
||||||
|
} catch (IOException e) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void println(Object o) {
|
||||||
|
println(o.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void println(char c) {
|
||||||
|
println(String.valueOf(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(char[] buffer, int offset, int length) throws IOException {
|
||||||
|
out.write(buffer, offset, length);
|
||||||
|
if (autoFlush) flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flush() {
|
||||||
|
try {
|
||||||
|
out.flush();
|
||||||
|
} catch (IOException e) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
try {
|
||||||
|
out.close();
|
||||||
|
} catch (IOException e) { }
|
||||||
|
}
|
||||||
|
}
|
74
sgx-jvm/avian/classpath/java/io/PushbackReader.java
Normal file
74
sgx-jvm/avian/classpath/java/io/PushbackReader.java
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class PushbackReader extends Reader {
|
||||||
|
private final Reader in;
|
||||||
|
private char savedChar;
|
||||||
|
private boolean hasSavedChar;
|
||||||
|
|
||||||
|
public PushbackReader(Reader in, int bufferSize) {
|
||||||
|
if (bufferSize > 1) {
|
||||||
|
throw new IllegalArgumentException(bufferSize + " > 1");
|
||||||
|
}
|
||||||
|
this.in = in;
|
||||||
|
this.hasSavedChar = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PushbackReader(Reader in) {
|
||||||
|
this(in, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(char[] b, int offset, int length) throws IOException {
|
||||||
|
int count = 0;
|
||||||
|
if (hasSavedChar && length > 0) {
|
||||||
|
length--;
|
||||||
|
b[offset++] = savedChar;
|
||||||
|
hasSavedChar = false;
|
||||||
|
count = 1;
|
||||||
|
}
|
||||||
|
if (length > 0) {
|
||||||
|
int c = in.read(b, offset, length);
|
||||||
|
if (c == -1) {
|
||||||
|
if (count == 0) {
|
||||||
|
count = -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
count += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unread(char[] b, int offset, int length) throws IOException {
|
||||||
|
if (length != 1) {
|
||||||
|
throw new IOException("Can only push back 1 char, not " + length);
|
||||||
|
} else if (hasSavedChar) {
|
||||||
|
throw new IOException("Already have a saved char");
|
||||||
|
} else {
|
||||||
|
hasSavedChar = true;
|
||||||
|
savedChar = b[offset];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unread(char[] b) throws IOException {
|
||||||
|
unread(b, 0, b.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unread(int c) throws IOException {
|
||||||
|
unread(new char[] { (char) c });
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
}
|
282
sgx-jvm/avian/classpath/java/io/RandomAccessFile.java
Normal file
282
sgx-jvm/avian/classpath/java/io/RandomAccessFile.java
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
/* 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.lang.IllegalArgumentException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
|
|
||||||
|
public class RandomAccessFile implements DataInput, Closeable {
|
||||||
|
|
||||||
|
private long peer;
|
||||||
|
private File file;
|
||||||
|
private long position = 0;
|
||||||
|
private long length;
|
||||||
|
private boolean allowWrite;
|
||||||
|
|
||||||
|
public RandomAccessFile(String name, String mode)
|
||||||
|
throws FileNotFoundException
|
||||||
|
{
|
||||||
|
this(new File(name), mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RandomAccessFile(File file, String mode)
|
||||||
|
throws FileNotFoundException
|
||||||
|
{
|
||||||
|
if (file == null) throw new NullPointerException();
|
||||||
|
if (mode.equals("rw")) allowWrite = true;
|
||||||
|
else if (! mode.equals("r")) throw new IllegalArgumentException();
|
||||||
|
this.file = file;
|
||||||
|
open();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void open() throws FileNotFoundException {
|
||||||
|
long[] result = new long[2];
|
||||||
|
open(file.getPath(), allowWrite, result);
|
||||||
|
peer = result[0];
|
||||||
|
length = result[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native void open(String name, boolean allowWrite, long[] result)
|
||||||
|
throws FileNotFoundException;
|
||||||
|
|
||||||
|
private void refresh() throws IOException {
|
||||||
|
if (file.length() != length) {
|
||||||
|
close();
|
||||||
|
open();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public long length() throws IOException {
|
||||||
|
refresh();
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getFilePointer() throws IOException {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void seek(long position) throws IOException {
|
||||||
|
if (position < 0 || (!allowWrite && position > length())) throw new IOException();
|
||||||
|
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int skipBytes(int count) throws IOException {
|
||||||
|
if (position + count > length()) throw new IOException();
|
||||||
|
this.position = position + count;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(byte b[], int off, int len) throws IOException {
|
||||||
|
if(b == null)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
if (peer == 0)
|
||||||
|
throw new IOException();
|
||||||
|
if(len == 0)
|
||||||
|
return 0;
|
||||||
|
if (position + len > this.length)
|
||||||
|
throw new EOFException();
|
||||||
|
if (off < 0 || off + len > b.length)
|
||||||
|
throw new ArrayIndexOutOfBoundsException();
|
||||||
|
int bytesRead = readBytes(peer, position, b, off, len);
|
||||||
|
position += bytesRead;
|
||||||
|
return bytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(byte b[]) throws IOException {
|
||||||
|
if(b == null)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
if (peer == 0)
|
||||||
|
throw new IOException();
|
||||||
|
if(b.length == 0)
|
||||||
|
return 0;
|
||||||
|
if (position + b.length > this.length)
|
||||||
|
throw new EOFException();
|
||||||
|
int bytesRead = readBytes(peer, position, b, 0, b.length);
|
||||||
|
position += bytesRead;
|
||||||
|
return bytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readFully(byte b[], int off, int len) throws IOException {
|
||||||
|
if (b == null)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
if (peer == 0)
|
||||||
|
throw new IOException();
|
||||||
|
if(len == 0)
|
||||||
|
return;
|
||||||
|
if (position + len > this.length)
|
||||||
|
throw new EOFException();
|
||||||
|
if (off < 0 || off + len > b.length)
|
||||||
|
throw new ArrayIndexOutOfBoundsException();
|
||||||
|
int n = 0;
|
||||||
|
do {
|
||||||
|
int count = readBytes(peer, position, b, off + n, len - n);
|
||||||
|
position += count;
|
||||||
|
if (count == 0)
|
||||||
|
throw new EOFException();
|
||||||
|
n += count;
|
||||||
|
} while (n < len);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readFully(byte b[]) throws IOException {
|
||||||
|
readFully(b, 0, b.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native int readBytes(long peer, long position, byte[] buffer,
|
||||||
|
int offset, int length);
|
||||||
|
|
||||||
|
public boolean readBoolean() throws IOException {
|
||||||
|
return readByte() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read() throws IOException {
|
||||||
|
try {
|
||||||
|
return readByte() & 0xff;
|
||||||
|
} catch (final EOFException e) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte readByte() throws IOException {
|
||||||
|
final byte[] buffer = new byte[1];
|
||||||
|
readFully(buffer);
|
||||||
|
return buffer[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public short readShort() throws IOException {
|
||||||
|
final byte[] buffer = new byte[2];
|
||||||
|
readFully(buffer);
|
||||||
|
return (short)((buffer[0] << 8) | buffer[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int readInt() throws IOException {
|
||||||
|
byte[] buf = new byte[4];
|
||||||
|
readFully(buf);
|
||||||
|
return ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float readFloat() throws IOException {
|
||||||
|
return Float.floatToIntBits(readInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
public double readDouble() throws IOException {
|
||||||
|
return Double.doubleToLongBits(readLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
public long readLong() throws IOException {
|
||||||
|
return ((readInt() & 0xffffffffl) << 32) | (readInt() & 0xffffffffl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public char readChar() throws IOException {
|
||||||
|
return (char)readShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int readUnsignedByte() throws IOException {
|
||||||
|
return readByte() & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int readUnsignedShort() throws IOException {
|
||||||
|
return readShort() & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String readUTF() throws IOException {
|
||||||
|
int length = readUnsignedShort();
|
||||||
|
byte[] bytes = new byte[length];
|
||||||
|
readFully(bytes);
|
||||||
|
return new String(bytes, "UTF-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
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 write(int b) throws IOException {
|
||||||
|
int count = writeBytes(peer, position, new byte[] { (byte)b }, 0, 1);
|
||||||
|
if (count > 0) position += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native int writeBytes(long peer, long position, byte[] buffer,
|
||||||
|
int offset, int length);
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
if (peer != 0) {
|
||||||
|
close(peer);
|
||||||
|
peer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
58
sgx-jvm/avian/classpath/java/io/Reader.java
Normal file
58
sgx-jvm/avian/classpath/java/io/Reader.java
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/* 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.nio.CharBuffer;
|
||||||
|
|
||||||
|
public abstract class Reader implements Closeable, Readable {
|
||||||
|
public int read(CharBuffer buffer) throws IOException {
|
||||||
|
int c = read(buffer.array(),
|
||||||
|
buffer.arrayOffset() + buffer.position(),
|
||||||
|
buffer.remaining());
|
||||||
|
|
||||||
|
if (c > 0) {
|
||||||
|
buffer.position(buffer.position() + c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read() throws IOException {
|
||||||
|
char[] buffer = new char[1];
|
||||||
|
int c = read(buffer);
|
||||||
|
if (c <= 0) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return (int) buffer[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(char[] buffer) throws IOException {
|
||||||
|
return read(buffer, 0, buffer.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract int read(char[] buffer, int offset, int length)
|
||||||
|
throws IOException;
|
||||||
|
|
||||||
|
public boolean markSupported() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mark(int readAheadLimit) throws IOException {
|
||||||
|
throw new IOException("mark not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() throws IOException {
|
||||||
|
throw new IOException("reset not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void close() throws IOException;
|
||||||
|
}
|
13
sgx-jvm/avian/classpath/java/io/Serializable.java
Normal file
13
sgx-jvm/avian/classpath/java/io/Serializable.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public interface Serializable { }
|
@ -0,0 +1,21 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class StreamCorruptedException extends IOException {
|
||||||
|
public StreamCorruptedException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamCorruptedException() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
}
|
34
sgx-jvm/avian/classpath/java/io/StringReader.java
Normal file
34
sgx-jvm/avian/classpath/java/io/StringReader.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class StringReader extends Reader {
|
||||||
|
private final String in;
|
||||||
|
private int position = 0;
|
||||||
|
|
||||||
|
public StringReader(String in) {
|
||||||
|
this.in = in;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(char[] b, int offset, int length) throws IOException {
|
||||||
|
if (length > in.length() - position) {
|
||||||
|
length = in.length() - position;
|
||||||
|
if (length <= 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in.getChars(position, position+length, b, offset);
|
||||||
|
position += length;
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException { }
|
||||||
|
}
|
31
sgx-jvm/avian/classpath/java/io/StringWriter.java
Normal file
31
sgx-jvm/avian/classpath/java/io/StringWriter.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class StringWriter extends Writer {
|
||||||
|
private final StringBuffer out = new StringBuffer();
|
||||||
|
|
||||||
|
public void write(char[] b, int offset, int length) throws IOException {
|
||||||
|
out.append(b, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flush() throws IOException { }
|
||||||
|
|
||||||
|
public void close() throws IOException { }
|
||||||
|
|
||||||
|
public StringBuffer getBuffer() {
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
21
sgx-jvm/avian/classpath/java/io/UTFDataFormatException.java
Normal file
21
sgx-jvm/avian/classpath/java/io/UTFDataFormatException.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
public class UTFDataFormatException extends IOException {
|
||||||
|
public UTFDataFormatException(String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UTFDataFormatException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user