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

org.robolectric.res.android.ZipFileRO Maven / Gradle / Ivy

package org.robolectric.res.android;

import static org.robolectric.res.android.Asset.toIntExact;
import static org.robolectric.res.android.Errors.NAME_NOT_FOUND;
import static org.robolectric.res.android.Errors.NO_ERROR;
import static org.robolectric.res.android.Util.ALOGW;
import static org.robolectric.res.android.Util.isTruthy;

import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class ZipFileRO {

  static final int kCompressStored = 0;
  static final int kCompressDeflated = 8;

  final ZipArchiveHandle mHandle;
  final String mFileName;

  ZipFileRO(ZipArchiveHandle handle, String fileName) {
    this.mHandle = handle;
    this.mFileName = fileName;
  }

  static class ZipEntryRO {
    ZipEntry entry;
    String name;
    long dataOffset;
    Object cookie;

    ZipEntryRO() {}

    //    ~ZipEntryRO() {
    @Override
    protected void finalize() {
      //      EndIteration(cookie);
    }

    //    private:
    //    ZipEntryRO(final ZipEntryRO& other);
    //    ZipEntryRO& operator=(final ZipEntryRO& other);
  }
  ;

  //  ~ZipFileRO() {
  @Override
  protected void finalize() {
    CloseArchive();
    //    free(mFileName);
  }

  static int OpenArchive(String zipFileName, Ref mHandle) {
    try {
      File file = new File(zipFileName);
      // TODO: consider moving away from ZipFile. By using ZipFile and guessDataOffsets, the zip
      // central directory is being read twice
      ZipFile zipFile = new ZipFile(file);
      mHandle.set(
          new ZipArchiveHandle(zipFile, FileMap.guessDataOffsets(file, (int) file.length())));
      return NO_ERROR;
    } catch (IOException e) {
      return NAME_NOT_FOUND;
    }
  }

  private static void CloseArchive() {
    throw new UnsupportedOperationException();
  }

  private static String ErrorCodeString(int error) {
    return "error " + error;
  }

  static int FindEntry(ZipArchiveHandle mHandle, String name, Ref zipEntryRef) {
    ZipEntry entry = mHandle.zipFile.getEntry(name);
    zipEntryRef.set(entry);
    if (entry == null) {
      return NAME_NOT_FOUND;
    }
    return NO_ERROR;
  }

  /*
   * Open the specified file read-only.  We memory-map the entire thing and
   * close the file before returning.
   */
  /* static */
  static ZipFileRO open(final String zipFileName) {
    final Ref handle = new Ref<>(null);
    final int error = OpenArchive(zipFileName, handle);
    if (isTruthy(error)) {
      ALOGW("Error opening archive %s: %s", zipFileName, ErrorCodeString(error));
      CloseArchive();
      return null;
    }

    return new ZipFileRO(handle.get(), zipFileName);
  }

  // /* static */ ZipFileRO* ZipFileRO::openFd(int fd, String debugFileName,
  //     boolean assume_ownership)
  // {
  //   ZipArchiveHandle handle;
  //   int error = OpenArchiveFd(fd, debugFileName, &handle, assume_ownership);
  //   if (error) {
  //     ALOGW("Error opening archive fd %d %s: %s", fd, debugFileName, ErrorCodeString(error));
  //     CloseArchive(handle);
  //     return NULL;
  //   }
  //
  //   return new ZipFileRO(handle, strdup(debugFileName));
  // }

  org.robolectric.res.android.ZipFileRO.ZipEntryRO findEntryByName(final String entryName) {
    ZipEntryRO data = new ZipEntryRO();
    data.name = String(entryName);

    if (mHandle.dataOffsets.get(entryName) == null) {
      return null;
    }
    data.dataOffset = mHandle.dataOffsets.get(entryName);

    final Ref zipEntryRef = new Ref<>(data.entry);
    final int error = FindEntry(mHandle, data.name, zipEntryRef);
    if (isTruthy(error)) {
      return null;
    }

    data.entry = zipEntryRef.get();
    return data;
  }

  /*
   * Get the useful fields from the zip entry.
   *
   * Returns "false" if the offsets to the fields or the contents of the fields
   * appear to be bogus.
   */
  boolean getEntryInfo(
      org.robolectric.res.android.ZipFileRO.ZipEntryRO entry,
      Ref pMethod,
      final Ref pUncompLen,
      Ref pCompLen,
      Ref pOffset,
      final Ref pModWhen,
      Ref pCrc32) {
    final ZipEntryRO zipEntry = /*reinterpret_cast*/ entry;
    final ZipEntry ze = zipEntry.entry;

    if (pMethod != null) {
      pMethod.set((short) ze.getMethod());
    }
    if (pUncompLen != null) {
      pUncompLen.set(ze.getSize()); // uncompressed_length
    }
    if (pCompLen != null) {
      pCompLen.set(ze.getCompressedSize());
    }
    if (pOffset != null) {
      throw new UnsupportedOperationException("Figure out offset");
      //        pOffset = ze.offset;
    }
    if (pModWhen != null) {
      // todo pModWhen.set(ze.getLastModifiedTime().toMillis());
    }
    if (pCrc32 != null) {
      pCrc32.set(ze.getCrc());
    }

    return true;
  }

  boolean startIteration(Ref> cookie) {
    return startIteration(cookie, null, null);
  }

  boolean startIteration(
      /* void** */ Ref> cookie,
      final String prefix,
      final String suffix) {
    cookie.set(this.mHandle.zipFile.entries());
    //    ZipEntryRO* ze = new ZipEntryRO;
    //    String pe(prefix ? prefix : "");
    //    String se(suffix ? suffix : "");
    //    int error = StartIteration(mHandle, &(ze.cookie),
    //    prefix ? &pe : null,
    //      suffix ? &se : null);
    //    if (error) {
    //      ALOGW("Could not start iteration over %s: %s", mFileName, ErrorCodeString(error));
    //      delete ze;
    //      return false;
    //    }
    //
    //    *cookie = ze;
    return true;
  }

  org.robolectric.res.android.ZipFileRO.ZipEntryRO nextEntry(
      /*void* */ Enumeration cookie) {
    if (!cookie.hasMoreElements()) {
      return null;
    }
    ZipEntryRO zipEntryRO = new ZipEntryRO();
    zipEntryRO.entry = cookie.nextElement();
    return zipEntryRO;
    //    ZipEntryRO ze = /*reinterpret_cast*/(ZipEntryRO) cookie;
    //    int error = Next(ze.cookie, &(ze.entry), &(ze.name));
    //    if (error) {
    //      if (error != -1) {
    //        ALOGW("Error iteration over %s: %s", mFileName, ErrorCodeString(error));
    //      }
    //      return null;
    //    }
    //
    //    return &(ze.entry);
  }

  void endIteration(/*void**/ Object cookie) {
    //    delete reinterpret_cast(cookie);
  }

  void releaseEntry(org.robolectric.res.android.ZipFileRO.ZipEntryRO entry) {
    //    delete reinterpret_cast(entry);
  }

  /*
   * Copy the entry's filename to the buffer.
   */
  int getEntryFileName(org.robolectric.res.android.ZipFileRO.ZipEntryRO entry, Ref buffer) {
    buffer.set(entry.entry.getName());

    //    final ZipEntryRO* zipEntry = reinterpret_cast(entry);
    //    final uint16_t requiredSize = zipEntry.name.name_length + 1;
    //
    //    if (bufLen < requiredSize) {
    //      ALOGW("Buffer too short, requires %d bytes for entry name", requiredSize);
    //      return requiredSize;
    //    }
    //
    //    memcpy(buffer, zipEntry.name.name, requiredSize - 1);
    //    buffer[requiredSize - 1] = '\0';
    //
    return 0;
  }

  /*
   * Create a new FileMap object that spans the data in "entry".
   */
  /*FileMap*/ ZipFileRO(org.robolectric.res.android.ZipFileRO.ZipEntryRO entry) {
    throw new UnsupportedOperationException("Implememnt me");

    //    final ZipEntryRO *zipEntry = reinterpret_cast(entry);
    //    final ZipEntry& ze = zipEntry.entry;
    //    int fd = GetFileDescriptor(mHandle);
    //    size_t actualLen = 0;
    //
    //    if (ze.method == kCompressStored) {
    //      actualLen = ze.uncompressed_length;
    //    } else {
    //      actualLen = ze.compressed_length;
    //    }
    //
    //    FileMap* newMap = new FileMap();
    //    if (!newMap.create(mFileName, fd, ze.offset, actualLen, true)) {
    //      delete newMap;
    //      return null;
    //    }
    //
    //    return newMap;
  }

  /*
   * Create a new FileMap object that spans the data in "entry".
   */
  FileMap createEntryFileMap(ZipEntryRO entry) {
    // final _ZipEntryRO *zipEntry = reinterpret_cast<_ZipEntryRO*>(entry);
    // const ZipEntry& ze = zipEntry->entry;
    // int fd = GetFileDescriptor(mHandle);

    FileMap newMap = new FileMap();
    if (!newMap.createFromZip(
        mFileName,
        mHandle.zipFile,
        entry.entry,
        entry.dataOffset,
        toIntExact(entry.entry.getCompressedSize()),
        true)) {
      // delete newMap;
      return null;
    }

    return newMap;
  }

  /*
   * Uncompress an entry, in its entirety, into the provided output buffer.
   *
   * This doesn't verify the data's CRC, which might be useful for
   * uncompressed data.  The caller should be able to manage it.
   */
  boolean uncompressEntry(
      org.robolectric.res.android.ZipFileRO.ZipEntryRO entry, Object buffer, int size) {
    throw new UnsupportedOperationException("Implememnt me");
    //    ZipEntryRO *zipEntry = reinterpret_cast(entry);
    //    final int error = ExtractToMemory(mHandle, &(zipEntry.entry),
    //    (uint8_t*) buffer, size);
    //    if (error) {
    //      ALOGW("ExtractToMemory failed with %s", ErrorCodeString(error));
    //      return false;
    //    }
    //
    //    return true;
  }

  /*
   * Uncompress an entry, in its entirety, to an open file descriptor.
   *
   * This doesn't verify the data's CRC, but probably should.
   */
  boolean uncompressEntry(org.robolectric.res.android.ZipFileRO.ZipEntryRO entry, int fd) {
    throw new UnsupportedOperationException("Implememnt me");
    //    ZipEntryRO *zipEntry = reinterpret_cast(entry);
    //    final int error = ExtractEntryToFile(mHandle, &(zipEntry.entry), fd);
    //    if (error) {
    //      ALOGW("ExtractToMemory failed with %s", ErrorCodeString(error));
    //      return false;
    //    }
    //
    //    return true;
  }

  static String String(String string) {
    return string;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy