/** * Removes the Extra Field with the given Header ID. * * @param headerId The requested Header ID. * @return The Extra Field with the given Header ID or {@code null} * if no such Extra Field exists. * @throws IllegalArgumentException If {@code headerID} is not in * the range of {@code 0} to {@link UShort#MAX_VALUE} * ({@value de.schlichtherle.truezip.zip.UShort#MAX_VALUE}). */ @Nullable ExtraField remove(final int headerId) { assert UShort.check(headerId); final ExtraField ef = extra.remove(headerId); assert null == ef || ef.getHeaderId() == headerId; return ef; }
/** * Returns the Extra Field with the given Header ID or {@code null} * if no such Extra Field exists. * * @param headerId The requested Header ID. * @return The Extra Field with the given Header ID or {@code null} * if no such Extra Field exists. * @throws IllegalArgumentException If {@code headerID} is not in * the range of {@code 0} to {@link UShort#MAX_VALUE} * ({@value de.schlichtherle.truezip.zip.UShort#MAX_VALUE}). */ @CheckForNull ExtraField get(final int headerId) { assert UShort.check(headerId); final ExtraField ef = extra.get(headerId); assert null == ef || ef.getHeaderId() == headerId; return ef; }
/** * Stores the given Extra Field in this collection. * * @param ef The Extra Field to store in this collection. * @return The Extra Field previously associated with the Header ID of * of the given Extra Field or {@code null} if no such * Extra Field existed. * @throws NullPointerException If {@code ef} is {@code null}. * @throws IllegalArgumentException If the Header ID of the given Extra * Field is not in the range of {@code 0} to * {@link UShort#MAX_VALUE} * ({@value de.schlichtherle.truezip.zip.UShort#MAX_VALUE}). */ ExtraField add(final ExtraField ef) { final int headerId = ef.getHeaderId(); assert UShort.check(headerId); return extra.put(headerId, ef); }
/** * 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} 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 */ static void register(final Class<? extends ExtraField> c) { final ExtraField ef; try { ef = (ExtraField) c.newInstance(); } catch (NullPointerException ex) { throw ex; } catch (Exception ex) { throw new IllegalArgumentException(ex); } final int headerId = ef.getHeaderId(); assert UShort.check(headerId); registry.put(headerId, c); }
/** * A static contrstructor 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 * @see #register */ static ExtraField create(final int headerId) { assert UShort.check(headerId); final Class<? extends ExtraField> c = registry.get(headerId); final ExtraField ef; try { ef = null != c ? (ExtraField) c.newInstance() : new DefaultExtraField(headerId); } catch (Exception cannotHappen) { throw new AssertionError(cannotHappen); } assert headerId == ef.getHeaderId(); return ef; }
/** * Serializes a list of Extra Fields of {@link #getExtraLength} bytes to the * byte array {@code data} at the zero based offset {@code off}. * Upon return, this collection shall not access {@code data} * subsequently. * * @param data The byte array to write the list of Extra Fields to. * @param off The zero based offset in the byte array where the first byte * of the list of Extra Fields is written to. * @throws IndexOutOfBoundsException If the byte array * {@code data} does not hold at least {@link #getExtraLength} * bytes at the zero based offset {@code off}. * @see #getExtraLength */ void writeTo(final byte[] data, int off) throws IndexOutOfBoundsException { for (final ExtraField ef : extra.values()) { writeShort(ef.getHeaderId(), data, off); off += 2; writeShort(ef.getDataSize(), data, off); off += 2; ef.writeTo(data, off); off += ef.getDataSize(); } } }
@Test public void testCreate() { ExtraField ef; ExtraField.register(NullExtraField.class); ef = ExtraField.create(0x0000); assertTrue(ef instanceof NullExtraField); assertEquals(0x0000, ef.getHeaderId()); ef = ExtraField.create(0x0001); //assertTrue(ef instanceof Zip64ExtraField); assertTrue(ef instanceof DefaultExtraField); assertEquals(0x0001, ef.getHeaderId()); ef = ExtraField.create(0x0002); assertTrue(ef instanceof DefaultExtraField); assertEquals(0x0002, ef.getHeaderId()); ef = ExtraField.create(UShort.MAX_VALUE); assertTrue(ef instanceof DefaultExtraField); assertEquals(UShort.MAX_VALUE, ef.getHeaderId()); try { ef = ExtraField.create(UShort.MIN_VALUE - 1); fail(); } catch (IllegalArgumentException expected) { } try { ef = ExtraField.create(UShort.MAX_VALUE + 1); fail(); } catch (IllegalArgumentException expected) { } }