/**
   * {@inheritDoc}
   *
   * @throws ClassCastException if entry is not an instance of ZipArchiveEntry
   * @throws Zip64RequiredException if the entry's uncompressed or compressed size is known to
   *     exceed 4 GByte and {@link #setUseZip64} is {@link Zip64Mode#Never}.
   */
  @Override
  public void putArchiveEntry(ArchiveEntry archiveEntry) throws IOException {
    if (finished) {
      throw new IOException("Stream has already been finished");
    }

    if (entry != null) {
      closeArchiveEntry();
    }

    entry = new CurrentEntry((ZipArchiveEntry) archiveEntry);
    entries.add(entry.entry);

    setDefaults(entry.entry);

    final Zip64Mode effectiveMode = getEffectiveZip64Mode(entry.entry);
    validateSizeInformation(effectiveMode);

    if (shouldAddZip64Extra(entry.entry, effectiveMode)) {

      Zip64ExtendedInformationExtraField z64 = getZip64Extra(entry.entry);

      // just a placeholder, real data will be in data
      // descriptor or inserted later via RandomAccessFile
      ZipEightByteInteger size = ZipEightByteInteger.ZERO;
      if (entry.entry.getMethod() == STORED && entry.entry.getSize() != ArchiveEntry.SIZE_UNKNOWN) {
        // actually, we already know the sizes
        size = new ZipEightByteInteger(entry.entry.getSize());
      }
      z64.setSize(size);
      z64.setCompressedSize(size);
      entry.entry.setExtra();
    }

    if (entry.entry.getMethod() == DEFLATED && hasCompressionLevelChanged) {
      def.setLevel(level);
      hasCompressionLevelChanged = false;
    }
    writeLocalFileHeader(entry.entry);
  }