/**
  * reads the content of a group of existing files in a zipped block
  *
  * @param domain The namespace used to identify the application domain (1st level directory) to
  *     use
  * @param paths The paths relative to the domain for the files to be read
  * @param offset The offset in the file to start reading from
  * @param len The length of the block in bytes in zipped form
  * @return The contents of the file in zipped form together with the description of the files
  */
 public MultiFileBlock readFromStreamZipped(String[] paths, long offset, int len) {
   MultiFileBlock block = null;
   try {
     if (_isLocal) {
       int startFileIndex =
           Util.getStartFileIndex(
               _rootFile.getCanonicalPath() + File.separatorChar, paths, offset);
       long startFileOffset =
           Util.getStartFileOffset(
               _rootFile.getCanonicalPath() + File.separatorChar, paths, offset);
       int i = startFileIndex;
       long j = startFileOffset;
       // int bufSize=0;
       int totalBufSize = 0;
       int readResult = 0;
       ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
       GZIPOutputStream zOut = new GZIPOutputStream(bOut, len);
       block = new MultiFileBlock();
       while (totalBufSize < len && i < paths.length) {
         File tmpFile = new File(_rootFile.getCanonicalPath() + File.separatorChar + paths[i]);
         if (tmpFile.isFile() && tmpFile.exists()) {
           RandomAccessFile in = new RandomAccessFile(tmpFile, "r");
           byte[] tmpBuf = new byte[len - totalBufSize];
           in.seek(j);
           while (totalBufSize < len && in.getFilePointer() < in.length()) {
             readResult = in.read(tmpBuf);
             if (readResult != -1) {
               zOut.write(tmpBuf, 0, readResult);
               // bufSize = bOut.size();
               totalBufSize += readResult;
             } else {
               break;
             }
           }
           BlockFileDescriptor des = new BlockFileDescriptor(_domain, paths[i], in.length());
           block.addBlockFileDescriptor(des);
           in.close();
           i++;
           j = 0;
         } else {
           return null;
         }
       }
       zOut.close();
       block.setBlockData(bOut.toByteArray());
     } else {
       block = _remote.readFromStreamZipped(_domain, paths, offset, len);
     }
   } catch (Exception ex) {
     ex.printStackTrace();
   }
   return block;
 }
  /**
   * write zipped data to a group of existing files in a webdav server to be stored in the original
   * form using the current domain
   *
   * @param paths The paths relative to the domain for the files to be written
   * @param block The zipped contents of the block of data to be written and the description for
   *     each file
   * @param last true if this is the last block of data
   * @return The total number of bytes stored or null if method failed
   */
  public long writeToStreamZipped(String[] paths, MultiFileBlock block, boolean last) {
    long result = -1L;
    if (_tempFile == null) _tempFile = Util.createCache();

    try {
      byte[] buffer = block.getBlockData();
      ByteArrayInputStream bIn = new ByteArrayInputStream(buffer);
      GZIPInputStream zIn = new GZIPInputStream(bIn);
      int bufSize = 0;

      byte[] tmpBuf = new byte[buffer.length];
      FileOutputStream fOut = new FileOutputStream(_tempFile.getCanonicalPath(), true);
      BlockFileDescriptor des = block.getBlockFileDescriptor(0);
      int i = 1;
      do {
        bufSize = zIn.read(tmpBuf);
        if (bufSize != -1) {
          long partSize = des.getFileSize() - _tempFile.length();
          if (partSize < bufSize) {
            fOut.write(tmpBuf, 0, (int) partSize);
            fOut.close();
            if (_isLocal) {
              File partRootFile = Util.initLocalResource(des.getFileDomain());
              File tmpFile =
                  new File(
                      partRootFile.getCanonicalPath() + File.separatorChar + des.getFilePath());
              if (_tempFile.renameTo(tmpFile)) {
                result = tmpFile.length();
              }
            } else {
              WebdavResource webdavRes = Util.initWebdavResource(_domain);
              if (webdavRes == null) {
                _tempFile.delete();
                _tempFile = null;
                return result;
              }
              result = Util.putFile(webdavRes, des.getFileDomain(), des.getFilePath(), _tempFile);
            }
            _tempFile = Util.createCache();
            des = block.getBlockFileDescriptor(i);
            i++;
            fOut = new FileOutputStream(_tempFile.getCanonicalPath(), true);
            fOut.write(tmpBuf, (int) partSize, (int) (bufSize - partSize));
          } else {
            fOut.write(tmpBuf, 0, bufSize);
          }
          fOut.flush();
        }
      } while (bufSize == tmpBuf.length);
      fOut.close();

      zIn.close();
      bIn.close();

      if (last) {
        if (_isLocal) {
          File partRootFile = Util.initLocalResource(des.getFileDomain());
          File tmpFile =
              new File(partRootFile.getCanonicalPath() + File.separatorChar + des.getFilePath());
          if (_tempFile.renameTo(tmpFile)) {
            _tempFile = null;
            return tmpFile.length();
          }
        } else {
          WebdavResource webdavRes = Util.initWebdavResource(_domain);
          if (webdavRes == null) {
            _tempFile.delete();
            _tempFile = null;
            return result;
          }
          result = Util.putFile(webdavRes, des.getFileDomain(), des.getFilePath(), _tempFile);
        }
      } else {
        return _tempFile.length();
      }
    } catch (Exception ex) {
      ex.printStackTrace();
    }
    return result;
  }