1 /* 2 * Copyright (c) 2015, 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.decompressor; 26 27 import java.nio.ByteBuffer; 28 import java.nio.ByteOrder; 29 import java.util.Objects; 30 import jdk.internal.jimage.decompressor.ResourceDecompressor.StringsProvider; 31 32 /** 33 * 34 * A resource header for compressed resource. This class is handled internally, 35 * you don't have to add header to the resource, headers are added automatically 36 * for compressed resources. 37 */ 38 public final class CompressedResourceHeader { 39 40 private static final int SIZE = 21; 41 public static final int MAGIC = 0xCAFEFAFA; 42 private final int uncompressedSize; 43 private final int compressedSize; 44 private final int decompressorNameOffset; 45 private final int contentOffset; 46 private final boolean isTerminal; 47 48 public CompressedResourceHeader(int compressedSize, 49 int uncompressedSize, int decompressorNameOffset, int contentOffset, 50 boolean isTerminal) { 51 this.compressedSize = compressedSize; 52 this.uncompressedSize = uncompressedSize; 53 this.decompressorNameOffset = decompressorNameOffset; 54 this.contentOffset = contentOffset; 55 this.isTerminal = isTerminal; 56 } 57 58 public boolean isTerminal() { 59 return isTerminal; 60 } 61 62 public int getDecompressorNameOffset() { 63 return decompressorNameOffset; 64 } 65 66 public int getContentOffset() { 67 return contentOffset; 68 } 69 70 public String getStoredContent(StringsProvider provider) { 71 Objects.nonNull(provider); 72 if(contentOffset == -1) { 73 return null; 74 } 75 return provider.getString(contentOffset); 76 } 77 78 public int getUncompressedSize() { 79 return uncompressedSize; 80 } 81 82 public int getResourceSize() { 83 return compressedSize; 84 } 85 86 public byte[] getBytes(ByteOrder order) { 87 Objects.requireNonNull(order); 88 ByteBuffer buffer = ByteBuffer.allocate(SIZE); 89 buffer.order(order); 90 buffer.putInt(MAGIC); 91 buffer.putInt(compressedSize); 92 buffer.putInt(uncompressedSize); 93 buffer.putInt(decompressorNameOffset); 94 buffer.putInt(contentOffset); 95 buffer.put(isTerminal ? (byte)1 : (byte)0); 96 return buffer.array(); 97 } 98 99 public static int getSize() { 100 return SIZE; 101 } 102 103 public static CompressedResourceHeader readFromResource(ByteOrder order, 104 byte[] resource) { 105 Objects.requireNonNull(order); 106 Objects.requireNonNull(resource); 107 if (resource.length < getSize()) { 108 return null; 109 } 110 ByteBuffer buffer = ByteBuffer.wrap(resource, 0, SIZE); 111 buffer.order(order); 112 int magic = buffer.getInt(); 113 if(magic != MAGIC) { 114 return null; 115 } 116 int size = buffer.getInt(); 117 int uncompressedSize = buffer.getInt(); 118 int decompressorNameOffset = buffer.getInt(); 119 int contentIndex = buffer.getInt(); 120 byte isTerminal = buffer.get(); 121 return new CompressedResourceHeader(size, uncompressedSize, 122 decompressorNameOffset, contentIndex, isTerminal == 1); 123 } 124 }