Package org.eclipse.php.internal.core.phar

Source Code of org.eclipse.php.internal.core.phar.PharBufferedOutputStream

/*******************************************************************************
* Copyright (c) 2009 Zhao and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     Zhao - initial API and implementation
*******************************************************************************/
package org.eclipse.php.internal.core.phar;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.php.internal.core.tar.CBZip2OutputStreamForPhar;
import org.eclipse.php.internal.core.tar.CRCable;
import org.eclipse.php.internal.core.tar.GZIPOutputStreamForPhar;

/**
* the mean class to write a pure phar
*
* @author zhaozw
*
*/
public class PharBufferedOutputStream implements IAchiveOutputStream {
  // private static final byte[] DEFAULT_STUB =
  // "<?php\r\n__HALT_COMPILER();\r\n".getBytes();

  List<PharAchiveOutputEntry> entries = new ArrayList<PharAchiveOutputEntry>();
  PharAchiveOutputEntry currentEntry;
  boolean currentStart;
  SignatureBufferedOutputStream os;
  OutputStream currentOutputStream;
  OutputStream manifestOutputStream;
  OutputStream fileDescriptionOutputStream;
  NumberedBufferedOutputStream fileContentStream;
  int currentIndex = 0;
  private File fileContent;
  private File manifest;
  private File fileDescription;
  PharPackage pharPackage;
  int fileNumber = 0;

  public PharBufferedOutputStream(
      SignatureBufferedOutputStream fileContentStream2,
      PharPackage pharPackage) throws IOException {
    this.os = fileContentStream2;
    manifest = File.createTempFile("temp1", ".tmp"); //$NON-NLS-1$ //$NON-NLS-2$
    manifestOutputStream = new BufferedOutputStream(new FileOutputStream(
        manifest));

    fileDescription = File.createTempFile("temp2", ".tmp"); //$NON-NLS-1$ //$NON-NLS-2$
    fileDescriptionOutputStream = new BufferedOutputStream(
        new FileOutputStream(fileDescription));

    fileContent = File.createTempFile("temp3", ".tmp"); //$NON-NLS-1$ //$NON-NLS-2$
    fileContentStream = new NumberedBufferedOutputStream(
        new FileOutputStream(fileContent));
    this.pharPackage = pharPackage;
  }

  public void writeStub(IStub stub) throws IOException, CoreException {
    stub.write(os);
  }

  public void close() throws IOException {
    os.close();
  }

  private void mergeFiles() throws IOException {
    fileDescriptionOutputStream.close();

    writeManifest();
    manifestOutputStream.close();

    fileContentStream.getInnerOutputStream().close();

    writeTempFileToStream(manifest);
    writeTempFileToStream(fileDescription);
    writeTempFileToStream(fileContent);
    manifest.delete();
    fileDescription.delete();
    fileContent.delete();
  }

  private void writeManifest() throws IOException {

    int aliasLength = 0;
    if (pharPackage.getAlias() != null) {
      aliasLength = pharPackage.getAlias().length();
    }
    // fileNumber4 + version2 + bitmap4 + aliaslength4 + metadatalength4 =
    // 18
    int manifestLength = (int) (18 + aliasLength + fileDescription.length());
    writeInt(manifestOutputStream, manifestLength);
    writeInt(manifestOutputStream, fileNumber);

    // write Version
    manifestOutputStream.write(PharUtil.getStubVersionBytes(pharPackage
        .getStubVersion()));
    // manifestOutputStream.write(new byte[] { 17, 0 });
    // writeString(manifestOutputStream,pharData.getStubVersion());
    // write bitmap
    manifestOutputStream.write(PharUtil.getGlobalBitmap(pharPackage));

    writeInt(manifestOutputStream, aliasLength);
    if (aliasLength != 0) {
      writeString(manifestOutputStream, pharPackage.getAlias());
    }
    writeInt(manifestOutputStream, 0);
  }

  private void writeTempFileToStream(File file) throws IOException {

    InputStream contentStream = new BufferedInputStream(
        new FileInputStream(file));
    try {
      int n;
      byte[] readBuffer = new byte[4096];
      while ((n = contentStream.read(readBuffer)) > 0) {
        os.write(readBuffer, 0, n);
      }
    } finally {
      if (contentStream != null) {
        contentStream.close();
      }
    }

  }

  public void putNextEntry(IAchiveOutputEntry output) throws IOException {

    assert output instanceof PharAchiveOutputEntry;
    fileNumber++;

    currentEntry = (PharAchiveOutputEntry) output;
    entries.add(currentEntry);
    currentStart = true;
  }

  private void setEntryInfo() throws IOException {
    // if(currentEntry != null){
    // fileContentStream.flush();
    currentEntry.setCompressedSize(fileContentStream.getCurrent()
        - currentIndex);
    currentEntry.setCrc(getCrc(currentOutputStream));
    currentIndex = fileContentStream.getCurrent();
    // }
  }

  private long getCrc(OutputStream currentOutputStream2) {
    return ((CRCable) currentOutputStream2).getCrc();
  }

  public void write(byte[] b, int off, int len) throws IOException {

    // if currentStart is true,it should initialize the currentOutputStream
    // depends on the method of currentEntry
    if (currentStart) {
      currentStart = false;
      if (currentEntry.getMethod() == PharConstants.NONE_COMPRESSED) {
        currentOutputStream = fileContentStream;
      } else if (currentEntry.getMethod() == PharConstants.BZ2_COMPRESSED) {
        currentOutputStream = new CBZip2OutputStreamForPhar(
            fileContentStream);
      } else if (currentEntry.getMethod() == PharConstants.GZ_COMPRESSED) {
        currentOutputStream = new GZIPOutputStreamForPhar(
            fileContentStream);
      }
      currentOutputStream = new CRCableOutputStream(currentOutputStream);
    }

    currentOutputStream.write(b, off, len);
  }

  public void closeEntry() throws IOException {
    // the close method is called to force to flush the cache when the
    // phar's content is compressed
    currentOutputStream.close();
    setEntryInfo();
    writeCurrentEntry();
  }

  // write the entry info to fileDescriptionOutputStream
  private void writeCurrentEntry() throws IOException {

    writeInt(fileDescriptionOutputStream, currentEntry.getName().length());
    writeString(fileDescriptionOutputStream, currentEntry.getName());
    writeInt(fileDescriptionOutputStream, (int) currentEntry.getSize());
    writeInt(fileDescriptionOutputStream, (int) currentEntry.getTime());
    writeInt(fileDescriptionOutputStream, (int) currentEntry
        .getCompressedSize());
    writeInt(fileDescriptionOutputStream, (int) currentEntry.getCrc());
    fileDescriptionOutputStream
        .write(PharUtil.getBitmapBytes(currentEntry));
    // writeInt(fileDescriptionOutputStream, (int)
    // currentEntry.getMethod());
    writeInt(fileDescriptionOutputStream, 0);
  }

  private void writeString(OutputStream os, String name) throws IOException {
    os.write(name.getBytes());
  }

  /*
   * Writes integer in Intel byte order to a byte array, starting at a given
   * offset.
   */
  private void writeInt(OutputStream os, int i) throws IOException {
    writeShort(os, i & 0xffff);
    writeShort(os, (i >> 16) & 0xffff);
  }

  /*
   * Writes short integer in Intel byte order to a byte array, starting at a
   * given offset
   */
  private void writeShort(OutputStream os, int s) throws IOException {
    os.write((byte) (s & 0xff));
    os.write((byte) ((s >> 8) & 0xff));
  }

  public void writeSignature() throws IOException {
    mergeFiles();
    os.flush();
    byte[] signature = os.getSignature();

    if (signature != null) {

      os.write(PharUtil.getWholeSignature(signature, pharPackage));
      // os
      // .write(Digest.DIGEST_MAP.get(pharData.getSignature())
      // .getBitMap());
      // os.write("GBMB".getBytes());
    }

  }
}
TOP

Related Classes of org.eclipse.php.internal.core.phar.PharBufferedOutputStream

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.