001 /*
002 * Copyright 1995-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 java.net;
027
028 import java.io.FileDescriptor;
029 import java.io.FileOutputStream;
030 import java.io.IOException;
031 import java.nio.channels.FileChannel;
032
033 /**
034 * This stream extends FileOutputStream to implement a
035 * SocketOutputStream. Note that this class should <b>NOT</b> be
036 * public.
037 *
038 * @version 1.38, 06/11/07
039 * @author Jonathan Payne
040 * @author Arthur van Hoff
041 */
042 class SocketOutputStream extends FileOutputStream {
043 static {
044 init();
045 }
046
047 private AbstractPlainSocketImpl impl = null;
048 private byte temp[] = new byte[1];
049 private Socket socket = null;
050
051 /**
052 * Creates a new SocketOutputStream. Can only be called
053 * by a Socket. This method needs to hang on to the owner Socket so
054 * that the fd will not be closed.
055 * @param impl the socket output stream inplemented
056 */
057 SocketOutputStream(AbstractPlainSocketImpl impl) throws IOException {
058 super (impl.getFileDescriptor());
059 this .impl = impl;
060 socket = impl.getSocket();
061 }
062
063 /**
064 * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
065 * object associated with this file output stream. </p>
066 *
067 * The <code>getChannel</code> method of <code>SocketOutputStream</code>
068 * returns <code>null</code> since it is a socket based stream.</p>
069 *
070 * @return the file channel associated with this file output stream
071 *
072 * @since 1.4
073 * @spec JSR-51
074 */
075 public final FileChannel getChannel() {
076 return null;
077 }
078
079 /**
080 * Writes to the socket.
081 * @param fd the FileDescriptor
082 * @param b the data to be written
083 * @param off the start offset in the data
084 * @param len the number of bytes that are written
085 * @exception IOException If an I/O error has occurred.
086 */
087 private native void socketWrite0(FileDescriptor fd, byte[] b,
088 int off, int len) throws IOException;
089
090 /**
091 * Writes to the socket with appropriate locking of the
092 * FileDescriptor.
093 * @param b the data to be written
094 * @param off the start offset in the data
095 * @param len the number of bytes that are written
096 * @exception IOException If an I/O error has occurred.
097 */
098 private void socketWrite(byte b[], int off, int len)
099 throws IOException {
100
101 if (len <= 0 || off < 0 || off + len > b.length) {
102 if (len == 0) {
103 return;
104 }
105 throw new ArrayIndexOutOfBoundsException();
106 }
107
108 FileDescriptor fd = impl.acquireFD();
109 try {
110 socketWrite0(fd, b, off, len);
111 } catch (SocketException se) {
112 if (se instanceof sun.net.ConnectionResetException) {
113 impl.setConnectionResetPending();
114 se = new SocketException("Connection reset");
115 }
116 if (impl.isClosedOrPending()) {
117 throw new SocketException("Socket closed");
118 } else {
119 throw se;
120 }
121 } finally {
122 impl.releaseFD();
123 }
124 }
125
126 /**
127 * Writes a byte to the socket.
128 * @param b the data to be written
129 * @exception IOException If an I/O error has occurred.
130 */
131 public void write(int b) throws IOException {
132 temp[0] = (byte) b;
133 socketWrite(temp, 0, 1);
134 }
135
136 /**
137 * Writes the contents of the buffer <i>b</i> to the socket.
138 * @param b the data to be written
139 * @exception SocketException If an I/O error has occurred.
140 */
141 public void write(byte b[]) throws IOException {
142 socketWrite(b, 0, b.length);
143 }
144
145 /**
146 * Writes <i>length</i> bytes from buffer <i>b</i> starting at
147 * offset <i>len</i>.
148 * @param b the data to be written
149 * @param off the start offset in the data
150 * @param len the number of bytes that are written
151 * @exception SocketException If an I/O error has occurred.
152 */
153 public void write(byte b[], int off, int len) throws IOException {
154 socketWrite(b, off, len);
155 }
156
157 /**
158 * Closes the stream.
159 */
160 private boolean closing = false;
161
162 public void close() throws IOException {
163 // Prevent recursion. See BugId 4484411
164 if (closing)
165 return;
166 closing = true;
167 if (socket != null) {
168 if (!socket.isClosed())
169 socket.close();
170 } else
171 impl.close();
172 closing = false;
173 }
174
175 /**
176 * Overrides finalize, the fd is closed by the Socket.
177 */
178 protected void finalize() {
179 }
180
181 /**
182 * Perform class load-time initializations.
183 */
184 private native static void init();
185
186 }
|