private void setSizesAndOffsetFromZip64Extra(
     final ZipEntry ze, final OffsetEntry offset, final int diskStart) throws IOException {
   final Zip64ExtendedInformationExtraField z64 =
       (Zip64ExtendedInformationExtraField)
           ze.getExtraField(Zip64ExtendedInformationExtraField.HEADER_ID);
   if (z64 != null) {
     final boolean hasUncompressedSize = ze.getSize() == 4294967295L;
     final boolean hasCompressedSize = ze.getCompressedSize() == 4294967295L;
     final boolean hasRelativeHeaderOffset = offset.headerOffset == 4294967295L;
     z64.reparseCentralDirectoryData(
         hasUncompressedSize, hasCompressedSize, hasRelativeHeaderOffset, diskStart == 65535);
     if (hasUncompressedSize) {
       ze.setSize(z64.getSize().getLongValue());
     } else if (hasCompressedSize) {
       z64.setSize(new ZipEightByteInteger(ze.getSize()));
     }
     if (hasCompressedSize) {
       ze.setCompressedSize(z64.getCompressedSize().getLongValue());
     } else if (hasUncompressedSize) {
       z64.setCompressedSize(new ZipEightByteInteger(ze.getCompressedSize()));
     }
     if (hasRelativeHeaderOffset) {
       offset.headerOffset = z64.getRelativeHeaderOffset().getLongValue();
     }
   }
 }
  /**
   * {@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);
  }
 /**
  * If the entry needs Zip64 extra information inside the central directory then configure its
  * data.
  */
 private void handleZip64Extra(ZipArchiveEntry ze, long lfhOffset, boolean needsZip64Extra) {
   if (needsZip64Extra) {
     Zip64ExtendedInformationExtraField z64 = getZip64Extra(ze);
     if (ze.getCompressedSize() >= ZIP64_MAGIC || ze.getSize() >= ZIP64_MAGIC) {
       z64.setCompressedSize(new ZipEightByteInteger(ze.getCompressedSize()));
       z64.setSize(new ZipEightByteInteger(ze.getSize()));
     } else {
       // reset value that may have been set for LFH
       z64.setCompressedSize(null);
       z64.setSize(null);
     }
     if (lfhOffset >= ZIP64_MAGIC) {
       z64.setRelativeHeaderOffset(new ZipEightByteInteger(lfhOffset));
     }
     ze.setExtra();
   }
 }