001: /***** BEGIN LICENSE BLOCK *****
002: * Version: CPL 1.0/GPL 2.0/LGPL 2.1
003: *
004: * The contents of this file are subject to the Common Public
005: * License Version 1.0 (the "License"); you may not use this file
006: * except in compliance with the License. You may obtain a copy of
007: * the License at http://www.eclipse.org/legal/cpl-v10.html
008: *
009: * Software distributed under the License is distributed on an "AS
010: * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
011: * implied. See the License for the specific language governing
012: * rights and limitations under the License.
013: *
014: * Copyright (C) 2006 Ola Bini <Ola.Bini@ki.se>
015: *
016: * Alternatively, the contents of this file may be used under the terms of
017: * either of the GNU General Public License Version 2 or later (the "GPL"),
018: * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
019: * in which case the provisions of the GPL or the LGPL are applicable instead
020: * of those above. If you wish to allow use of your version of this file only
021: * under the terms of either the GPL or the LGPL, and not to allow others to
022: * use your version of this file under the terms of the CPL, indicate your
023: * decision by deleting the provisions above and replace them with the notice
024: * and other provisions required by the GPL or the LGPL. If you do not delete
025: * the provisions above, a recipient may use your version of this file under
026: * the terms of any one of the CPL, the GPL or the LGPL.
027: ***** END LICENSE BLOCK *****/package org.jruby.util;
028:
029: import java.io.InputStream;
030: import java.io.IOException;
031:
032: import org.jruby.RubyFixnum;
033: import org.jruby.RubyString;
034: import org.jruby.runtime.builtin.IRubyObject;
035:
036: /**
037: * This class wraps a IRubyObject in an InputStream. Depending on which messages
038: * the IRubyObject answers to, it will have different functionality.
039: *
040: * The point is that the IRubyObject could exhibit duck typing, in the style of IO versus StringIO, for example.
041: *
042: * At the moment, the only functionality supported is reading, and the only requirement on the io-object is
043: * that it responds to read() like IO.
044: */
045: public class IOInputStream extends InputStream {
046: private IRubyObject io;
047: private final IRubyObject numOne;
048:
049: /**
050: * Creates a new InputStream with the object provided.
051: *
052: * @param io the ruby object
053: */
054: public IOInputStream(IRubyObject io) {
055: if (!io.respondsTo("read")) {
056: throw new IllegalArgumentException(
057: "Object: "
058: + io
059: + " is not a legal argument to this wrapper, cause it doesn't respond to \"read\".");
060: }
061: this .io = io;
062: this .numOne = RubyFixnum.one(this .io.getRuntime());
063: }
064:
065: public int read() throws IOException {
066: IRubyObject readValue = io.callMethod(io.getRuntime()
067: .getCurrentContext(), "read", numOne);
068: int returnValue = -1;
069: if (!readValue.isNil()) {
070: returnValue = readValue.toString().charAt(0);
071: }
072: return returnValue;
073: }
074:
075: public int read(byte[] b) throws IOException {
076: IRubyObject readValue = io.callMethod(io.getRuntime()
077: .getCurrentContext(), "read", this .io.getRuntime()
078: .newFixnum(b.length));
079: int returnValue = -1;
080: if (!readValue.isNil()) {
081: ByteList str = ((RubyString) readValue).getByteList();
082: System.arraycopy(str.bytes, str.begin, b, 0, str.realSize);
083: returnValue = str.realSize;
084: }
085: return returnValue;
086: }
087:
088: public int read(byte[] b, int off, int len) throws IOException {
089: IRubyObject readValue = io.callMethod(io.getRuntime()
090: .getCurrentContext(), "read", io.getRuntime()
091: .newFixnum(len));
092: int returnValue = -1;
093: if (!readValue.isNil()) {
094: ByteList str = ((RubyString) readValue).getByteList();
095: System
096: .arraycopy(str.bytes, str.begin, b, off,
097: str.realSize);
098: returnValue = str.realSize;
099: }
100: return returnValue;
101: }
102: }
|