/*
 * Copyright (c) 2015, 2016, 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.decompressor;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Objects;
import jdk.internal.jimage.decompressor.ResourceDecompressor.StringsProvider;

A resource header for compressed resource. This class is handled internally, you don't have to add header to the resource, headers are added automatically for compressed resources.
Implementation Note:This class needs to maintain JDK 8 source compatibility. It is used internally in the JDK to implement jimage/jrtfs access, but also compiled and delivered as part of the jrtfs.jar to support access to the jimage file provided by the shipped JDK by tools running on JDK 8.
/** * * A resource header for compressed resource. This class is handled internally, * you don't have to add header to the resource, headers are added automatically * for compressed resources. * * @implNote This class needs to maintain JDK 8 source compatibility. * * It is used internally in the JDK to implement jimage/jrtfs access, * but also compiled and delivered as part of the jrtfs.jar to support access * to the jimage file provided by the shipped JDK by tools running on JDK 8. */
public final class CompressedResourceHeader { private static final int SIZE = 29; public static final int MAGIC = 0xCAFEFAFA; private final long uncompressedSize; private final long compressedSize; private final int decompressorNameOffset; private final int contentOffset; private final boolean isTerminal; public CompressedResourceHeader(long compressedSize, long uncompressedSize, int decompressorNameOffset, int contentOffset, boolean isTerminal) { this.compressedSize = compressedSize; this.uncompressedSize = uncompressedSize; this.decompressorNameOffset = decompressorNameOffset; this.contentOffset = contentOffset; this.isTerminal = isTerminal; } public boolean isTerminal() { return isTerminal; } public int getDecompressorNameOffset() { return decompressorNameOffset; } public int getContentOffset() { return contentOffset; } public String getStoredContent(StringsProvider provider) { Objects.requireNonNull(provider); if(contentOffset == -1) { return null; } return provider.getString(contentOffset); } public long getUncompressedSize() { return uncompressedSize; } public long getResourceSize() { return compressedSize; } public byte[] getBytes(ByteOrder order) { Objects.requireNonNull(order); ByteBuffer buffer = ByteBuffer.allocate(SIZE); buffer.order(order); buffer.putInt(MAGIC); buffer.putLong(compressedSize); buffer.putLong(uncompressedSize); buffer.putInt(decompressorNameOffset); buffer.putInt(contentOffset); buffer.put(isTerminal ? (byte)1 : (byte)0); return buffer.array(); } public static int getSize() { return SIZE; } public static CompressedResourceHeader readFromResource(ByteOrder order, byte[] resource) { Objects.requireNonNull(order); Objects.requireNonNull(resource); if (resource.length < getSize()) { return null; } ByteBuffer buffer = ByteBuffer.wrap(resource, 0, SIZE); buffer.order(order); int magic = buffer.getInt(); if(magic != MAGIC) { return null; } long size = buffer.getLong(); long uncompressedSize = buffer.getLong(); int decompressorNameOffset = buffer.getInt(); int contentIndex = buffer.getInt(); byte isTerminal = buffer.get(); return new CompressedResourceHeader(size, uncompressedSize, decompressorNameOffset, contentIndex, isTerminal == 1); } }