1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package jdk.internal.jimage;
  26 
  27 import java.io.IOException;
  28 import java.nio.ByteBuffer;
  29 import java.nio.ByteOrder;
  30 import sun.misc.JavaNioAccess;
  31 import sun.misc.SharedSecrets;
  32 
  33 final class ImageNativeSubstrate implements ImageSubstrate {
  34     private static final JavaNioAccess NIOACCESS =
  35             SharedSecrets.getJavaNioAccess();
  36 
  37     private final long id;
  38     private final long indexAddress;
  39     private final long dataAddress;
  40 
  41     native static long openImage(String imagePath, boolean bigEndian);
  42     native static void closeImage(long id);
  43     native static long getIndexAddress(long id);
  44     native static long getDataAddress(long id);
  45     native static boolean readCompressed(long id, long offset,
  46             ByteBuffer compressedBuffer, long compressedSize,
  47             ByteBuffer uncompressedBuffer, long uncompressedSize);
  48     native static boolean read(long id, long offset,
  49             ByteBuffer uncompressedBuffer, long uncompressedSize);
  50     native static byte[] getStringBytes(long id, int offset);
  51     native static long[] getAttributes(long id, int offset);
  52     native static long[] findAttributes(long id, byte[] path);
  53     native static int[] attributeOffsets(long id);
  54 
  55     static ByteBuffer newDirectByteBuffer(long address, long capacity) {
  56         assert capacity < Integer.MAX_VALUE;
  57         return NIOACCESS.newDirectByteBuffer(address, (int)capacity, null);
  58     }
  59 
  60     private ImageNativeSubstrate(long id) {
  61         this.id = id;
  62         this.indexAddress = getIndexAddress(id);
  63         this.dataAddress = getDataAddress(id);
  64     }
  65 
  66     static ImageSubstrate openImage(String imagePath, ByteOrder byteOrder)
  67             throws IOException {
  68         long id = openImage(imagePath, byteOrder == ByteOrder.BIG_ENDIAN);
  69 
  70         if (id == 0) {
  71              throw new IOException("Image not found \"" + imagePath + "\"");
  72         }
  73 
  74         return new ImageNativeSubstrate(id);
  75     }
  76 
  77     @Override
  78     public void close() {
  79         closeImage(id);
  80     }
  81 
  82     @Override
  83     public ByteBuffer getIndexBuffer(long offset, long size) {
  84         return newDirectByteBuffer(indexAddress + offset, size);
  85     }
  86 
  87     @Override
  88     public ByteBuffer getDataBuffer(long offset, long size) {
  89         return dataAddress != 0 ?
  90                 newDirectByteBuffer(dataAddress + offset, size) : null;
  91     }
  92 
  93     @Override
  94     public boolean supportsDataBuffer() {
  95         return dataAddress != 0;
  96     }
  97 
  98     @Override
  99     public boolean read(long offset,
 100                  ByteBuffer compressedBuffer, long compressedSize,
 101                  ByteBuffer uncompressedBuffer, long uncompressedSize) {
 102         return readCompressed(id, offset,
 103                     compressedBuffer, compressedSize,
 104                     uncompressedBuffer, uncompressedSize);
 105     }
 106 
 107     @Override
 108     public boolean read(long offset,
 109                  ByteBuffer uncompressedBuffer, long uncompressedSize) {
 110         return read(id, offset, uncompressedBuffer, uncompressedSize);
 111     }
 112 
 113     @Override
 114     public byte[] getStringBytes(int offset) {
 115         return getStringBytes(id, offset);
 116     }
 117 
 118     @Override
 119     public long[] getAttributes(int offset) {
 120         return getAttributes(id, offset);
 121     }
 122 
 123     @Override
 124     public ImageLocation findLocation(UTF8String name, ImageStringsReader strings) {
 125         long[] attributes = findAttributes(id, name.getBytes());
 126 
 127         return attributes != null ? new ImageLocation(attributes, strings) : null;
 128     }
 129 
 130     @Override
 131     public int[] attributeOffsets() {
 132         return attributeOffsets(id);
 133     }
 134 }