Package com.caucho.quercus.lib.file

Source Code of com.caucho.quercus.lib.file.WrappedStream$WrappedOutputStream

/*
* Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT.  See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
*   Free Software Foundation, Inc.
*   59 Temple Place, Suite 330
*   Boston, MA 02111-1307  USA
*
* @author Emil Ong
*/

package com.caucho.quercus.lib.file;

import com.caucho.quercus.QuercusModuleException;
import com.caucho.quercus.env.*;
import com.caucho.vfs.TempBuffer;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

/**
* A stream that has its operations mediated by a Quercus object.
*/
public class WrappedStream implements BinaryInput, BinaryOutput {
  private static final UnicodeBuilderValue STREAM_CLOSE
    = new UnicodeBuilderValue("stream_close");
  private static final UnicodeBuilderValue STREAM_EOF
    = new UnicodeBuilderValue("stream_eof");
  private static final UnicodeBuilderValue STREAM_FLUSH
    = new UnicodeBuilderValue("stream_flush");
  private static final UnicodeBuilderValue STREAM_OPEN
    = new UnicodeBuilderValue("stream_open");
  private static final UnicodeBuilderValue STREAM_READ
    = new UnicodeBuilderValue("stream_read");
  private static final UnicodeBuilderValue STREAM_SEEK
    = new UnicodeBuilderValue("stream_seek");
  private static final UnicodeBuilderValue STREAM_TELL
    = new UnicodeBuilderValue("stream_tell");
  private static final UnicodeBuilderValue STREAM_WRITE
    = new UnicodeBuilderValue("stream_write");
 
  private byte []printBuffer = new byte[1];

  private Env _env;
  private Value _wrapper;
  private LineReader _lineReader;

  private InputStream _is;
  private OutputStream _os;
  private int _buffer;
  private boolean _doUnread = false;

  private int _writeLength;

  private WrappedStream(Env env, Value wrapper)
  {
    _env = env;

    _wrapper = wrapper;

    _lineReader = new LineReader(env);
  }

  public WrappedStream(Env env,
                       QuercusClass qClass,
                       StringValue path,
                       StringValue mode,
                       LongValue options)
  {
    _env = env;

    _lineReader = new LineReader(env);

    _wrapper = qClass.callNew(_env, new Value[0]);

    _wrapper.callMethod(_env, STREAM_OPEN,
                        path, mode, options, NullValue.NULL);
  }

  public InputStream getInputStream()
  {
    if (_is == null)
      _is = new WrappedInputStream();

    return _is;
  }

  public OutputStream getOutputStream()
  {
    if (_os == null)
      _os = new WrappedOutputStream();

    return _os;
  }

  /**
   * Opens a new copy.
   */
  public BinaryInput openCopy()
    throws IOException
  {
    return new WrappedStream(_env, _wrapper);
  }

  /**
   * Sets the current read encoding.  The encoding can either be a
   * Java encoding name or a mime encoding.
   *
   * @param encoding name of the read encoding
   */
  public void setEncoding(String encoding)
    throws UnsupportedEncodingException
  {
  }

  public void closeRead()
  {
    close();
  }

  public void closeWrite()
  {
    close();
  }

  public void close()
  {
    _wrapper.callMethod(_env, STREAM_CLOSE);
  }

  /**
   * Reads a character from a file, returning -1 on EOF.
   */
  public int read()
    throws IOException
  {
    if (_doUnread) {
      _doUnread = false;

      return _buffer;
    } else {
      Value output = _wrapper.callMethod(_env, STREAM_READ, LongValue.ONE);

      _buffer = (int) output.toLong();

      return _buffer;
    }
  }

  /**
   * Unread a character.
   */
  public void unread()
    throws IOException
  {
    _doUnread = true;
  }

  public int read(byte []buffer, int offset, int length)
  {
    // XXX: shgould be reimplemented

    Value output = _wrapper.callMethod(_env, STREAM_READ,
                                       LongValue.create(length));

    // XXX "0"?

    if (! output.toBoolean())
      return -1;

    byte []outputBytes = output.toString().getBytes();

    if (outputBytes.length < length)
      length = outputBytes.length;

    System.arraycopy(outputBytes, 0, buffer, offset, length);

    return length;
  }

  public int read(char []buffer, int offset, int length)
  {
    // XXX: shgould be reimplemented

    Value output = _wrapper.callMethod(_env, STREAM_READ,
                                       LongValue.create(length));

    // XXX "0"?

    if (! output.toBoolean())
      return -1;

    byte []outputBytes = output.toString().getBytes();

    if (outputBytes.length < length)
      length = outputBytes.length;

    System.arraycopy(outputBytes, 0, buffer, offset, length);

    return length;
  }

  /**
   * Appends to a string builder.
   */
  public StringValue appendTo(StringValue builder)
  {
    try {
      int ch;
   
      while ((ch = read()) >= 0) {
        builder.append((char) ch);
      }

      return builder;
    } catch (IOException e) {
      throw new QuercusModuleException(e);
    }
  }


  /**
   * Reads a Binary string.
   */
  public StringValue read(int length)
    throws IOException
  {
    Value output = _wrapper.callMethod(_env, STREAM_READ,
                                       LongValue.create(length));

    return output.toBinaryValue(_env);
  }

  /**
   * Reads the optional linefeed character from a \r\n
   */
  public boolean readOptionalLinefeed()
    throws IOException
  {
    int ch = read();

    if (ch == '\n') {
      return true;
    }
    else {
      unread();
      return false;
    }
  }

    /**
   * Reads a line from a file, returning null on EOF.
   */
  public StringValue readLine(long length)
    throws IOException
  {
    return _lineReader.readLine(_env, this, length);
  }
 
  public void write(byte []buffer, int offset, int length)
    throws IOException
  {
    StringValue bb = _env.createBinaryBuilder(buffer, offset, length);

    Value output = _wrapper.callMethod(_env, STREAM_WRITE, bb);

    _writeLength = (int) output.toLong();
  }

  /**
   * Writes to a stream.
   */
  public int write(InputStream is, int length)
  {
    int writeLength = 0;

    TempBuffer tb = TempBuffer.allocate();
    byte []buffer = tb.getBuffer();

    try {
      while (length > 0) {
        int sublen;

        if (length < buffer.length)
          sublen = length;
        else
          sublen = buffer.length;

        sublen = is.read(buffer, 0, sublen);

        if (sublen < 0)
          break;

        for (int offset = 0; offset < sublen;) {
          write(buffer, offset, sublen);

          if (_writeLength > 0)
            offset += _writeLength;
          else
            return writeLength;
        }

        writeLength += sublen;
        length -= sublen;
      }

      return writeLength;
    } catch (IOException e) {
      throw new QuercusModuleException(e);
    } finally {
      TempBuffer.free(tb);
    }
  }

  /**
   * Prints a string to a file.
   */
  public void print(char v)
    throws IOException
  {
    printBuffer[0] = (byte) v;

    write(printBuffer, 0, 1);
  }

  /**
   * Prints a string to a file.
   */
  public void print(String v)
    throws IOException
  {
    for (int i = 0; i < v.length(); i++)
      print(v.charAt(i));
  }

  /**
   * Returns true if end-of-file has been reached
   */
  public boolean isEOF()
  {
    return _wrapper.callMethod(_env, STREAM_EOF).toBoolean();
  }

  /**
   * Tells the position in the stream
   */
  public long getPosition()
  {
    return _wrapper.callMethod(_env, STREAM_TELL).toLong();
  }

  /**
   * Sets the position.
   */
  public boolean setPosition(long offset)
  {
    LongValue offsetValue = LongValue.create(offset);
    LongValue whenceValue = LongValue.create(SEEK_SET);

    return _wrapper.callMethod(_env, STREAM_SEEK,
                               offsetValue, whenceValue).toBoolean();
  }

  public long seek(long offset, int whence)
  {
    LongValue offsetValue = LongValue.create(offset);
    LongValue whenceValue = LongValue.create(whence);

    return _wrapper.callMethod(_env, STREAM_SEEK,
                               offsetValue, whenceValue).toLong();
  }

  public void flush()
    throws IOException
  {
    if (! _wrapper.callMethod(_env, STREAM_FLUSH).toBoolean())
      throw new IOException(); // Get around java.io.Flushable
  }

  public Value stat()
  {
    return _wrapper.callMethod(_env, STREAM_FLUSH);
  }

  private class WrappedInputStream extends InputStream {
    public int read()
      throws IOException
    {
      return WrappedStream.this.read();
    }
  }

  private class WrappedOutputStream extends OutputStream {
    public void write(int b)
      throws IOException
    {
      _wrapper.callMethod(_env, STREAM_WRITE, LongValue.create(b));
    }
  }
}
TOP

Related Classes of com.caucho.quercus.lib.file.WrappedStream$WrappedOutputStream

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.