1 /*
  2  * Copyright (c) 2014, 2016, 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 
 26 package jdk.internal.jimage;
 27 
 28 import java.nio.ByteBuffer;
 29 import java.nio.IntBuffer;
 30 import java.util.Objects;
 31 
 32 /**
 33  * @implNote This class needs to maintain JDK 8 source compatibility.
 34  *
 35  * It is used internally in the JDK to implement jimage/jrtfs access,
 36  * but also compiled and delivered as part of the jrtfs.jar to support access
 37  * to the jimage file provided by the shipped JDK by tools running on JDK 8.
 38  */
 39 public final class ImageHeader {
 40     public static final int MAGIC = 0xCAFEDADA;
 41     public static final int MAJOR_VERSION = 1;
 42     public static final int MINOR_VERSION = 0;
 43     private static final int HEADER_SLOTS = 7;
 44 
 45     private final int magic;
 46     private final int majorVersion;
 47     private final int minorVersion;
 48     private final int flags;
 49     private final int resourceCount;
 50     private final int tableLength;
 51     private final int locationsSize;
 52     private final int stringsSize;
 53 
 54     public ImageHeader(int resourceCount, int tableCount,
 55             int locationsSize, int stringsSize) {
 56         this(MAGIC, MAJOR_VERSION, MINOR_VERSION, 0, resourceCount,
 57                 tableCount, locationsSize, stringsSize);
 58     }
 59 
 60     public ImageHeader(int magic, int majorVersion, int minorVersion,
 61                 int flags, int resourceCount,
 62                 int tableLength, int locationsSize, int stringsSize)
 63     {
 64         this.magic = magic;
 65         this.majorVersion = majorVersion;
 66         this.minorVersion = minorVersion;
 67         this.flags = flags;
 68         this.resourceCount = resourceCount;
 69         this.tableLength = tableLength;
 70         this.locationsSize = locationsSize;
 71         this.stringsSize = stringsSize;
 72     }
 73 
 74     public static int getHeaderSize() {
 75        return HEADER_SLOTS * 4;
 76     }
 77 
 78     static ImageHeader readFrom(IntBuffer buffer) {
 79         Objects.requireNonNull(buffer);
 80 
 81         if (buffer.capacity() != HEADER_SLOTS) {
 82             throw new InternalError(
 83                 "jimage header not the correct size: " + buffer.capacity());
 84         }
 85 
 86         int magic = buffer.get(0);
 87         int version = buffer.get(1);
 88         int majorVersion = version >>> 16;
 89         int minorVersion = version & 0xFFFF;
 90         int flags = buffer.get(2);
 91         int resourceCount = buffer.get(3);
 92         int tableLength = buffer.get(4);
 93         int locationsSize = buffer.get(5);
 94         int stringsSize = buffer.get(6);
 95 
 96         return new ImageHeader(magic, majorVersion, minorVersion, flags,
 97             resourceCount, tableLength, locationsSize, stringsSize);
 98     }
 99 
100     public void writeTo(ImageStream stream) {
101         Objects.requireNonNull(stream);
102         stream.ensure(getHeaderSize());
103         writeTo(stream.getBuffer());
104     }
105 
106     public void writeTo(ByteBuffer buffer) {
107         Objects.requireNonNull(buffer);
108         buffer.putInt(magic);
109         buffer.putInt(majorVersion << 16 | minorVersion);
110         buffer.putInt(flags);
111         buffer.putInt(resourceCount);
112         buffer.putInt(tableLength);
113         buffer.putInt(locationsSize);
114         buffer.putInt(stringsSize);
115     }
116 
117     public int getMagic() {
118         return magic;
119     }
120 
121     public int getMajorVersion() {
122         return majorVersion;
123     }
124 
125     public int getMinorVersion() {
126         return minorVersion;
127     }
128 
129     public int getFlags() {
130         return flags;
131     }
132 
133     public int getResourceCount() {
134         return resourceCount;
135     }
136 
137     public int getTableLength() {
138         return tableLength;
139     }
140 
141     public int getRedirectSize() {
142         return tableLength * 4;
143     }
144 
145     public int getOffsetsSize() {
146         return tableLength * 4;
147     }
148 
149     public int getLocationsSize() {
150         return locationsSize;
151     }
152 
153     public int getStringsSize() {
154         return stringsSize;
155     }
156 
157     public int getIndexSize() {
158         return getHeaderSize() +
159                getRedirectSize() +
160                getOffsetsSize() +
161                getLocationsSize() +
162                getStringsSize();
163     }
164 
165     int getRedirectOffset() {
166         return getHeaderSize();
167     }
168 
169     int getOffsetsOffset() {
170         return getRedirectOffset() +
171                getRedirectSize();
172     }
173 
174     int getLocationsOffset() {
175         return getOffsetsOffset() +
176                getOffsetsSize();
177     }
178 
179     int getStringsOffset() {
180         return getLocationsOffset() +
181                getLocationsSize();
182     }
183 }