27
28 import java.io.FileDescriptor;
29 import java.io.FileOutputStream;
30 import java.io.IOException;
31 import java.nio.channels.FileChannel;
32
33 /**
34 * This stream extends FileOutputStream to implement a
35 * SocketOutputStream. Note that this class should <b>NOT</b> be
36 * public.
37 *
38 * @author Jonathan Payne
39 * @author Arthur van Hoff
40 */
41 class SocketOutputStream extends FileOutputStream {
42 static {
43 init();
44 }
45
46 private AbstractPlainSocketImpl impl = null;
47 private byte temp[] = new byte[1];
48 private Socket socket = null;
49
50 /**
51 * Creates a new SocketOutputStream. Can only be called
52 * by a Socket. This method needs to hang on to the owner Socket so
53 * that the fd will not be closed.
54 * @param impl the socket output stream inplemented
55 */
56 SocketOutputStream(AbstractPlainSocketImpl impl) throws IOException {
57 super(impl.getFileDescriptor());
58 this.impl = impl;
59 socket = impl.getSocket();
60 }
61
62 /**
63 * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
64 * object associated with this file output stream. </p>
65 *
66 * The {@code getChannel} method of {@code SocketOutputStream}
67 * returns {@code null} since it is a socket based stream.</p>
77
78 /**
79 * Writes to the socket.
80 * @param fd the FileDescriptor
81 * @param b the data to be written
82 * @param off the start offset in the data
83 * @param len the number of bytes that are written
84 * @exception IOException If an I/O error has occurred.
85 */
86 private native void socketWrite0(FileDescriptor fd, byte[] b, int off,
87 int len) throws IOException;
88
89 /**
90 * Writes to the socket with appropriate locking of the
91 * FileDescriptor.
92 * @param b the data to be written
93 * @param off the start offset in the data
94 * @param len the number of bytes that are written
95 * @exception IOException If an I/O error has occurred.
96 */
97 private void socketWrite(byte b[], int off, int len) throws IOException {
98
99
100 if (len <= 0 || off < 0 || len > b.length - off) {
101 if (len == 0) {
102 return;
103 }
104 throw new ArrayIndexOutOfBoundsException("len == " + len
105 + " off == " + off + " buffer length == " + b.length);
106 }
107
108 FileDescriptor fd = impl.acquireFD();
109 try {
110 socketWrite0(fd, b, off, len);
111 } catch (SocketException se) {
112 if (impl.isClosedOrPending()) {
113 throw new SocketException("Socket closed");
114 } else {
115 throw se;
116 }
117 } finally {
118 impl.releaseFD();
119 }
120 }
121
122 /**
123 * Writes a byte to the socket.
124 * @param b the data to be written
125 * @exception IOException If an I/O error has occurred.
126 */
127 public void write(int b) throws IOException {
128 temp[0] = (byte)b;
129 socketWrite(temp, 0, 1);
130 }
131
132 /**
133 * Writes the contents of the buffer <i>b</i> to the socket.
134 * @param b the data to be written
135 * @exception SocketException If an I/O error has occurred.
136 */
137 public void write(byte b[]) throws IOException {
138 socketWrite(b, 0, b.length);
139 }
140
141 /**
142 * Writes <i>length</i> bytes from buffer <i>b</i> starting at
143 * offset <i>len</i>.
144 * @param b the data to be written
145 * @param off the start offset in the data
146 * @param len the number of bytes that are written
147 * @exception SocketException If an I/O error has occurred.
148 */
149 public void write(byte b[], int off, int len) throws IOException {
150 socketWrite(b, off, len);
151 }
152
153 /**
154 * Closes the stream.
155 */
156 private boolean closing = false;
157 public void close() throws IOException {
158 // Prevent recursion. See BugId 4484411
159 if (closing)
160 return;
161 closing = true;
162 if (socket != null) {
163 if (!socket.isClosed())
164 socket.close();
165 } else
166 impl.close();
167 closing = false;
168 }
169
|
27
28 import java.io.FileDescriptor;
29 import java.io.FileOutputStream;
30 import java.io.IOException;
31 import java.nio.channels.FileChannel;
32
33 /**
34 * This stream extends FileOutputStream to implement a
35 * SocketOutputStream. Note that this class should <b>NOT</b> be
36 * public.
37 *
38 * @author Jonathan Payne
39 * @author Arthur van Hoff
40 */
41 class SocketOutputStream extends FileOutputStream {
42 static {
43 init();
44 }
45
46 private AbstractPlainSocketImpl impl = null;
47 private byte[] temp = new byte[1];
48 private Socket socket = null;
49
50 /**
51 * Creates a new SocketOutputStream. Can only be called
52 * by a Socket. This method needs to hang on to the owner Socket so
53 * that the fd will not be closed.
54 * @param impl the socket output stream inplemented
55 */
56 SocketOutputStream(AbstractPlainSocketImpl impl) throws IOException {
57 super(impl.getFileDescriptor());
58 this.impl = impl;
59 socket = impl.getSocket();
60 }
61
62 /**
63 * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
64 * object associated with this file output stream. </p>
65 *
66 * The {@code getChannel} method of {@code SocketOutputStream}
67 * returns {@code null} since it is a socket based stream.</p>
77
78 /**
79 * Writes to the socket.
80 * @param fd the FileDescriptor
81 * @param b the data to be written
82 * @param off the start offset in the data
83 * @param len the number of bytes that are written
84 * @exception IOException If an I/O error has occurred.
85 */
86 private native void socketWrite0(FileDescriptor fd, byte[] b, int off,
87 int len) throws IOException;
88
89 /**
90 * Writes to the socket with appropriate locking of the
91 * FileDescriptor.
92 * @param b the data to be written
93 * @param off the start offset in the data
94 * @param len the number of bytes that are written
95 * @exception IOException If an I/O error has occurred.
96 */
97 private void socketWrite(byte[] b, int off, int len) throws IOException {
98
99
100 if (len <= 0 || off < 0 || len > b.length - off) {
101 if (len == 0) {
102 return;
103 }
104 throw new ArrayIndexOutOfBoundsException("len == " + len
105 + " off == " + off + " buffer length == " + b.length);
106 }
107
108 FileDescriptor fd = impl.acquireFD();
109 try {
110 socketWrite0(fd, b, off, len);
111 } catch (SocketException se) {
112 if (impl.isClosedOrPending()) {
113 throw new SocketException("Socket closed");
114 } else {
115 throw se;
116 }
117 } finally {
118 impl.releaseFD();
119 }
120 }
121
122 /**
123 * Writes a byte to the socket.
124 * @param b the data to be written
125 * @exception IOException If an I/O error has occurred.
126 */
127 public void write(int b) throws IOException {
128 temp[0] = (byte)b;
129 socketWrite(temp, 0, 1);
130 }
131
132 /**
133 * Writes the contents of the buffer <i>b</i> to the socket.
134 * @param b the data to be written
135 * @exception SocketException If an I/O error has occurred.
136 */
137 public void write(byte[] b) throws IOException {
138 socketWrite(b, 0, b.length);
139 }
140
141 /**
142 * Writes <i>length</i> bytes from buffer <i>b</i> starting at
143 * offset <i>len</i>.
144 * @param b the data to be written
145 * @param off the start offset in the data
146 * @param len the number of bytes that are written
147 * @exception SocketException If an I/O error has occurred.
148 */
149 public void write(byte[] b, int off, int len) throws IOException {
150 socketWrite(b, off, len);
151 }
152
153 /**
154 * Closes the stream.
155 */
156 private boolean closing = false;
157 public void close() throws IOException {
158 // Prevent recursion. See BugId 4484411
159 if (closing)
160 return;
161 closing = true;
162 if (socket != null) {
163 if (!socket.isClosed())
164 socket.close();
165 } else
166 impl.close();
167 closing = false;
168 }
169
|