001: /*
002: * Copyright (c) 2000 by Matt Welsh and The Regents of the University of
003: * California. All rights reserved.
004: *
005: * Permission to use, copy, modify, and distribute this software and its
006: * documentation for any purpose, without fee, and without written agreement is
007: * hereby granted, provided that the above copyright notice and the following
008: * two paragraphs appear in all copies of this software.
009: *
010: * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
011: * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
012: * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
013: * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
014: *
015: * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
016: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
017: * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
018: * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
019: * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
020: *
021: * Author: Matt Welsh <mdw@cs.berkeley.edu>
022: *
023: */
024:
025: package seda.nbio;
026:
027: import java.io.*;
028:
029: /**
030: * Package-internal class implementing NonblockingOutputStream for
031: * nonblocking sockets.
032: */
033: class NonblockingSocketOutputStream extends NonblockingOutputStream {
034:
035: private NBIOFileDescriptor fd;
036: private boolean eof;
037: private NonblockingSocketImpl impl;
038: private byte temp[] = new byte[1];
039:
040: private static final int SKIPBUFLEN = 4096;
041:
042: /* Non-blocking write on the underlying socket.
043: * Returns -1 if EOF has been reached, 0 if no data was written, otherwise
044: * the number of bytes written
045: */
046: private native int nbSocketWrite(byte b[], int off, int len)
047: throws IOException;
048:
049: NonblockingSocketOutputStream(NonblockingSocketImpl impl) {
050: fd = impl.getFileDescriptor();
051: this .impl = impl;
052: }
053:
054: /**
055: * Perform a <b>blocking</b> write of one byte to this output stream.
056: * Throws an EOFException if the end of stream has been reached.
057: * Use nbWrite() to perform a non-blocking write of one byte.
058: */
059: public void write(int b) throws IOException {
060: if (eof)
061: throw new EOFException("EOF on " + toString());
062: int n;
063: temp[0] = (byte) b;
064: // Spin until we write a byte -- ugly
065: while ((n = nbSocketWrite(temp, 0, 1)) == 0)
066: ;
067: if (n < 0) {
068: eof = true;
069: throw new EOFException("EOF on " + toString());
070: }
071: }
072:
073: /**
074: * Perform a blocking write of <code>b.length</code> bytes
075: * to the underlying stream. Use nbWrite() to perform a nonblocking
076: * write.
077: *
078: */
079: public void write(byte b[]) throws IOException {
080: if (eof)
081: throw new EOFException("EOF on " + toString());
082: int n, count = 0;
083: while (count < b.length) {
084: n = nbSocketWrite(b, count, (b.length - count));
085: if (n < 0) {
086: eof = true;
087: throw new EOFException("EOF on " + toString());
088: }
089: count += n;
090: }
091: }
092:
093: /**
094: * Perform a blocking write of <code>len</code> bytes to the
095: * underlying stream from the byte array <code>b</code> starting at offset
096: * <code>off</code>. Use nbWrite() to perform a nonblocking write.
097: */
098: public void write(byte b[], int off, int len) throws IOException {
099: if (eof)
100: throw new EOFException("EOF on " + toString());
101: int n, count = 0;
102: while (count < len) {
103: n = nbSocketWrite(b, count + off, (len - count));
104: if (n < 0) {
105: eof = true;
106: throw new EOFException("EOF on " + toString());
107: }
108: count += n;
109: }
110: }
111:
112: /**
113: * Perform a non-blocking write of one byte to this output stream.
114: * Returns 1 if the data was written or 0 if it could not be.
115: * Throws an EOFException if the end of the stream has been reached.
116: * Use write() to perform a blocking write of one byte.
117: */
118: public int nbWrite(byte b) throws IOException {
119: if (eof)
120: throw new EOFException("EOF on " + toString());
121: temp[0] = (byte) b;
122: int n = nbSocketWrite(temp, 0, 1);
123: if (n < 0) {
124: eof = true;
125: throw new EOFException("EOF on " + toString());
126: }
127: return n;
128: }
129:
130: /**
131: * Perform a nonblocking write of up to <code>b.length</code> bytes
132: * to the underlying stream. Returns the number of bytes written, or
133: * 0 if nothing was written. Use write() to perform a blocking
134: * write.
135: */
136: public int nbWrite(byte b[]) throws IOException {
137: if (eof)
138: throw new EOFException("EOF on " + toString());
139: int n = nbSocketWrite(b, 0, b.length);
140: if (n < 0) {
141: eof = true;
142: throw new EOFException("EOF on " + toString());
143: }
144: return n;
145: }
146:
147: /**
148: * Perform a nonblocking write of up to <code>len</code> bytes
149: * to the underlying stream starting at offset <code>off</code>.
150: * Returns the number of bytes written, or 0 if nothing was written.
151: * Use write() to perform a blocking write.
152: */
153: public int nbWrite(byte b[], int off, int len) throws IOException {
154: if (eof)
155: throw new EOFException("EOF on " + toString());
156: int n = nbSocketWrite(b, off, len);
157: if (n < 0) {
158: eof = true;
159: throw new EOFException("EOF on " + toString());
160: }
161: return n;
162: }
163:
164: /**
165: * flush() does nothing in this implementation.
166: */
167: public void flush() {
168: }
169:
170: public void close() throws IOException {
171: impl.close();
172: }
173:
174: }
|