001: /*
002: * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.security.ssl;
027:
028: import java.io.OutputStream;
029: import java.io.IOException;
030:
031: /*
032: * Output stream for application data. This is the kind of stream
033: * that's handed out via SSLSocket.getOutputStream(). It's all the application
034: * ever sees.
035: *
036: * Once the initial handshake has completed, application data may be
037: * interleaved with handshake data. That is handled internally and remains
038: * transparent to the application.
039: *
040: * @version 1.35 05/05/07
041: * @author David Brownell
042: */
043: class AppOutputStream extends OutputStream {
044:
045: private SSLSocketImpl c;
046: OutputRecord r;
047:
048: // One element array used to implement the write(byte) method
049: private final byte[] oneByte = new byte[1];
050:
051: AppOutputStream(SSLSocketImpl conn) {
052: r = new OutputRecord(Record.ct_application_data);
053: c = conn;
054: }
055:
056: /**
057: * Write the data out, NOW.
058: */
059: synchronized public void write(byte b[], int off, int len)
060: throws IOException {
061: // check if the Socket is invalid (error or closed)
062: c.checkWrite();
063: //
064: // Always flush at the end of each application level record.
065: // This lets application synchronize read and write streams
066: // however they like; if we buffered here, they couldn't.
067: //
068: // NOTE: *must* call c.writeRecord() even for len == 0
069: try {
070: do {
071: int howmuch = Math.min(len, r.availableDataBytes());
072:
073: if (howmuch > 0) {
074: r.write(b, off, howmuch);
075: off += howmuch;
076: len -= howmuch;
077: }
078: c.writeRecord(r);
079: c.checkWrite();
080: } while (len > 0);
081: } catch (Exception e) {
082: // shutdown and rethrow (wrapped) exception as appropriate
083: c.handleException(e);
084: }
085: }
086:
087: /**
088: * Write one byte now.
089: */
090: synchronized public void write(int i) throws IOException {
091: oneByte[0] = (byte) i;
092: write(oneByte, 0, 1);
093: }
094:
095: /*
096: * Socket close is already synchronized, no need to block here.
097: */
098: public void close() throws IOException {
099: c.close();
100: }
101:
102: // inherit no-op flush()
103: }
|