blob: f3a0e742036aedd0c43fac97b1cfa49665503777 [file] [log] [blame]
/*
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.jimage;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import sun.misc.JavaNioAccess;
import sun.misc.SharedSecrets;
public final class ImageNativeSubstrate implements ImageSubstrate {
static {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
@Override
public Void run() {
System.loadLibrary("jimage");
return null;
}
});
}
private static final JavaNioAccess NIOACCESS =
SharedSecrets.getJavaNioAccess();
private final long id;
private final long indexAddress;
private final long dataAddress;
static native long openImage(String imagePath, boolean bigEndian);
static native void closeImage(long id);
static native long getIndexAddress(long id);
static native long getDataAddress(long id);
static native boolean readCompressed(long id, long offset,
ByteBuffer compressedBuffer, long compressedSize,
ByteBuffer uncompressedBuffer, long uncompressedSize);
static native boolean read(long id, long offset,
ByteBuffer uncompressedBuffer, long uncompressedSize);
static native byte[] getStringBytes(long id, int offset);
static native long[] getAttributes(long id, int offset);
static native long[] findAttributes(long id, byte[] path);
static native int[] attributeOffsets(long id);
public static native long JIMAGE_Open(String path) throws IOException;
public static native void JIMAGE_Close(long jimageHandle);
public static native long JIMAGE_FindResource(long jimageHandle,
String moduleName, String Version, String path,
long[] size);
public static native long JIMAGE_GetResource(long jimageHandle,
long locationHandle, byte[] buffer, long size);
// Get an array of names that match; return the count found upto array size
public static native int JIMAGE_Resources(long jimageHandle,
String[] outputNames);
// Return the module name for the package
public static native String JIMAGE_PackageToModule(long imageHandle,
String packageName);
static ByteBuffer newDirectByteBuffer(long address, long capacity) {
assert capacity < Integer.MAX_VALUE;
return NIOACCESS.newDirectByteBuffer(address, (int)capacity, null);
}
private ImageNativeSubstrate(long id) {
this.id = id;
this.indexAddress = getIndexAddress(id);
this.dataAddress = getDataAddress(id);
}
static ImageSubstrate openImage(String imagePath, ByteOrder byteOrder)
throws IOException {
long id = openImage(imagePath, byteOrder == ByteOrder.BIG_ENDIAN);
if (id == 0) {
throw new IOException("Image not found \"" + imagePath + "\"");
}
return new ImageNativeSubstrate(id);
}
@Override
public void close() {
closeImage(id);
}
@Override
public ByteBuffer getIndexBuffer(long offset, long size) {
return newDirectByteBuffer(indexAddress + offset, size);
}
@Override
public ByteBuffer getDataBuffer(long offset, long size) {
return dataAddress != 0 ?
newDirectByteBuffer(dataAddress + offset, size) : null;
}
@Override
public boolean supportsDataBuffer() {
return dataAddress != 0;
}
@Override
public boolean read(long offset,
ByteBuffer compressedBuffer, long compressedSize,
ByteBuffer uncompressedBuffer, long uncompressedSize) {
return readCompressed(id, offset,
compressedBuffer, compressedSize,
uncompressedBuffer, uncompressedSize);
}
@Override
public boolean read(long offset,
ByteBuffer uncompressedBuffer, long uncompressedSize) {
return read(id, offset, uncompressedBuffer, uncompressedSize);
}
@Override
public byte[] getStringBytes(int offset) {
byte[] ret = getStringBytes(id, offset);
if (ret == null) {
throw new OutOfMemoryError("Error accessing array at offset "
+ offset);
}
return ret;
}
@Override
public long[] getAttributes(int offset) {
return getAttributes(id, offset);
}
@Override
public ImageLocation findLocation(UTF8String name, ImageStringsReader strings) {
long[] attributes = findAttributes(id, name.getBytes());
return attributes != null ? new ImageLocation(attributes, strings) : null;
}
@Override
public int[] attributeOffsets() {
return attributeOffsets(id);
}
}