All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.schlichtherle.util.zip.ExtraField Maven / Gradle / Ivy

/*
 * Copyright (C) 2007-2010 Schlichtherle IT Services
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package de.schlichtherle.util.zip;

import java.util.HashMap;
import java.util.Map;

/**
 * Abstract base class for an Extra Field in a Local or Central Header of a
 * ZIP archive.
 * It defines the common properties of all Extra Fields and how to
 * serialize/deserialize them to/from byte arrays.
 * 

* This class is not thread-safe. * * @author Christian Schlichtherle * @version $Id: ExtraField.java 5e709f50671d 2010/11/05 11:52:07 christian $ * @since TrueZIP 6.7 */ abstract class ExtraField { /** The Header ID of a ZIP64 Extended Information Extra Field. */ public static final int ZIP64_HEADER_ID = 0x0001; private static final Map registry = new HashMap(); /** * Registers a concrete implementation of this abstract base class for * use with the static factory method {@link #create}. * * @param c The implementation class of this abstract base class. * @throws IllegalArgumentException If {@code c} is {@code null}, * cannot get instantiated, is not a subclass of * {@code ExtraField} or its Header ID is out of range. * A more descriptive exception may be associated to it as its * cause. * @see #create */ public static void register(final Class c) { final ExtraField ef; try { ef = (ExtraField) c.newInstance(); } catch (Exception ex) { throw new IllegalArgumentException(ex); } final int headerID = ef.getHeaderID(); UShort.check(headerID, "Header ID out of range", null); // TODO: For JSE 5: registry.put(Integer.valueOf(headerID), c); registry.put(new Integer(headerID), c); } /** * A static factory method which creates a new Extra Field based on the * given Header ID. * The returned Extra Field still requires proper initialization, for * example by calling {@link #readFrom}. * * @param headerID An unsigned short integer (two bytes) which indicates * the type of the returned Extra Field. * @return A new Extra Field - never {@code null}! * @throws IllegalArgumentException If {@code headerID} is out of * range. * @see #register */ public static ExtraField create(final int headerID) { UShort.check(headerID, "Header ID out of range", null); // TODO: For JSE 5: final Class c = (Class) registry.get(Integer.valueOf(headerID)); final Class c = (Class) registry.get(new Integer(headerID)); final ExtraField ef; try { ef = c != null ? (ExtraField) c.newInstance() : new DefaultExtraField(headerID); } catch (Exception cannotHappen) { final AssertionError ae = new AssertionError("register(Class) should have checked the instantiatability of " + c); ae.initCause(cannotHappen); throw ae; } assert headerID == ef.getHeaderID(); return ef; } /** * Returns the Header ID (type) of this Extra Field. * The Header ID is an unsigned short integer (two bytes) * which must be constant during the life cycle of this object. */ public abstract int getHeaderID(); /** * Returns the Data Size of this Extra Field. * The Data Size is an unsigned short integer (two bytes) * which indicates the length of the Data Block in bytes and does not * include its own size in this Extra Field. * This property may be initialized by calling {@link #readFrom}. * * @return The size of the Data Block in bytes * or {@code 0} if unknown. * @see #getDataBlock */ abstract int getDataSize(); /** * Returns a protective copy of the Data Block. * {@code null} is never returned. * * @see #getDataSize */ final byte[] getDataBlock() { final int size = getDataSize(); UShort.check(size); if (size == 0) return ZIP.EMPTY; final byte[] data = new byte[size]; writeTo(data, 0); return data; } /** * Initializes this Extra Field by deserializing a Data Block of * {@code size} bytes from the * byte array {@code data} at the zero based offset {@code off}. * Upon return, this Extra Field shall not access {@code data} * subsequently and {@link #getDataSize} must equal {@code size}. * * @param data The byte array to read the Data Block from. * @param off The zero based offset in the byte array where the first byte * of the Data Block is read from. * @param size The length of the Data Block in bytes. * @throws IndexOutOfBoundsException If the byte array * {@code data} does not hold at least {@code size} * bytes at the zero based offset {@code off}. * @throws RuntimeException If {@code size} is illegal or the * deserialized Data Block contains illegal data. * @see #getDataSize */ abstract void readFrom(byte[] data, int off, int size); /** * Serializes a Data Block of {@link #getDataSize} bytes to the * byte array {@code data} at the zero based offset {@code off}. * Upon return, this Extra Field shall not access {@code data} * subsequently. * * @param data The byte array to write the Data Block to. * @param off The zero based offset in the byte array where the first byte * of the Data Block is written to. * @throws IndexOutOfBoundsException If the byte array * {@code data} does not hold at least {@link #getDataSize} * bytes at the zero based offset {@code off}. * @see #getDataSize */ abstract void writeTo(byte[] data, int off); }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy