~ubuntu-branches/ubuntu/oneiric/libjboss-remoting-java/oneiric

« back to all changes in this revision

Viewing changes to src/org/jboss/remoting/transport/multiplex/MultiplexingOutputStream.java

  • Committer: Package Import Robot
  • Author(s): Torsten Werner
  • Date: 2011-09-09 14:01:03 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: package-import@ubuntu.com-20110909140103-hqokx61534tas9rg
Tags: 2.5.3.SP1-1
* Newer but not newest upstream release. Do not build samples.
* Change debian/watch to upstream's svn repo.
* Add patch to fix compile error caused by tomcat update.
  (Closes: #628303)
* Switch to source format 3.0.
* Switch to debhelper level 7.
* Remove useless Depends.
* Update Standards-Version: 3.9.2.
* Update README.source.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
* JBoss, Home of Professional Open Source
3
 
* Copyright 2005, JBoss Inc., and individual contributors as indicated
4
 
* by the @authors tag. See the copyright.txt in the distribution for a
5
 
* full listing of individual contributors.
6
 
*
7
 
* This is free software; you can redistribute it and/or modify it
8
 
* under the terms of the GNU Lesser General Public License as
9
 
* published by the Free Software Foundation; either version 2.1 of
10
 
* the License, or (at your option) any later version.
11
 
*
12
 
* This software is distributed in the hope that it will be useful,
13
 
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
 
* Lesser General Public License for more details.
16
 
*
17
 
* You should have received a copy of the GNU Lesser General Public
18
 
* License along with this software; if not, write to the Free
19
 
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20
 
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21
 
*/
22
 
 
23
 
/*
24
 
 * Created on Jul 22, 2005
25
 
 */
26
 
 
27
 
package org.jboss.remoting.transport.multiplex;
28
 
 
29
 
import java.io.IOException;
30
 
import java.io.OutputStream;
31
 
import java.net.SocketException;
32
 
 
33
 
import org.jboss.logging.Logger;
34
 
 
35
 
/**
36
 
 * <code>MultiplexingOutputStream</code> is the class returned by
37
 
 * <code>VirtualSocket.getOutputStream()</code>.  
38
 
 * It supports the methods and behavior implemented by the <code>OutputStream</code> returned by
39
 
 * <code>java.net.Socket.getOutputStream()</code>.  For more information about the behavior
40
 
 * of the methods, see the javadoc for <code>java.io.OutputStream</code>.
41
 
 * <p>
42
 
 * Copyright (c) 2005
43
 
 * <p>
44
 
 * @author <a href="mailto:r.sigal@computer.org">Ron Sigal</a>
45
 
 * 
46
 
 * @deprecated As of release 2.4.0 the multiplex transport will no longer be actively supported.
47
 
 */
48
 
public class MultiplexingOutputStream extends OutputStream
49
 
{
50
 
   protected static final Logger log = Logger.getLogger(MultiplexingOutputStream.class);
51
 
   private MultiplexingManager manager;
52
 
   private OutputMultiplexor outputMultiplexor;
53
 
   private VirtualSocket virtualSocket;
54
 
   private SocketId socketId;
55
 
   private boolean outputShutdown = false;
56
 
   private boolean closed = false;
57
 
   private IOException writeException;
58
 
   
59
 
   private static final int OPEN                                = 0;
60
 
   private static final int CONNECTION_RESET    = 1;
61
 
   private static final int CLOSED                              = 2;
62
 
   private int connectionState = OPEN;
63
 
 
64
 
   private byte[] oneByte = new byte[1];
65
 
   private byte[] fourBytes = new byte[4];
66
 
   
67
 
/**
68
 
 * 
69
 
 * @param manager
70
 
 * @param socketId
71
 
 */
72
 
   public MultiplexingOutputStream(MultiplexingManager manager, SocketId socketId)
73
 
   {
74
 
      this(manager, null, socketId);
75
 
   }
76
 
   
77
 
   
78
 
/**
79
 
 * 
80
 
 * @param manager
81
 
 * @param virtualSocket
82
 
 * @param socketId
83
 
 */
84
 
   public MultiplexingOutputStream(MultiplexingManager manager, VirtualSocket virtualSocket, SocketId socketId)
85
 
   {
86
 
      this.manager = manager;
87
 
      this.virtualSocket = virtualSocket;
88
 
      this.socketId = socketId;
89
 
      this.outputMultiplexor = manager.getOutputMultiplexor();
90
 
   }
91
 
   
92
 
//////////////////////////////////////////////////////////////////////////////////////////////////
93
 
///                  The following methods are required of all OutputStreams                  '///
94
 
//////////////////////////////////////////////////////////////////////////////////////////////////
95
 
 
96
 
 /*************************************************************************************************
97
 
       ok: public void write(int b) throws IOException;
98
 
       ok: public void write(byte b[]) throws IOException;
99
 
       ok: public void write(byte b[], int off, int len) throws IOException;
100
 
           public void flush() throws IOException;
101
 
       ok: public void close() throws IOException;
102
 
 *************************************************************************************************/
103
 
 
104
 
   
105
 
/**
106
 
 * See superclass javadoc.
107
 
 */
108
 
   public void close() throws IOException
109
 
   {
110
 
      log.debug("MultiplexingOutputStream.close() entered");
111
 
      
112
 
      if (closed)
113
 
         return;
114
 
         
115
 
      closed = true;
116
 
      
117
 
      if (virtualSocket != null)
118
 
         virtualSocket.close();
119
 
   }
120
 
   
121
 
   
122
 
/**
123
 
 * See superclass javadoc.
124
 
 */
125
 
   public void flush() throws IOException
126
 
   {
127
 
      // Could use flush() to raise priority of messages waiting in OutputMultiplexor's write queue.
128
 
   }
129
 
   
130
 
   
131
 
/**
132
 
 * See superclass javadoc.
133
 
 */
134
 
   public void write(int i) throws IOException
135
 
   {
136
 
      checkStatus();
137
 
      oneByte[0] = (byte) i;
138
 
      outputMultiplexor.write(manager, socketId, oneByte);
139
 
   }
140
 
   
141
 
/**
142
 
 * See superclass javadoc.
143
 
 */
144
 
   public void write(byte[] array) throws IOException, NullPointerException
145
 
   { 
146
 
      checkStatus();
147
 
      outputMultiplexor.write(manager, socketId, array);
148
 
   }
149
 
   
150
 
   
151
 
/**
152
 
 * See superclass javadoc.
153
 
 */
154
 
   public void write(byte[] array, int off, int len)
155
 
   throws IOException, NullPointerException, IndexOutOfBoundsException
156
 
   { 
157
 
      checkStatus();
158
 
 
159
 
      if (array == null)
160
 
         throw new NullPointerException();
161
 
      
162
 
      if (off < 0 || len < 0 || off + len > array.length)
163
 
         throw new IndexOutOfBoundsException();
164
 
      
165
 
      byte[] subArray = new byte[len];
166
 
      
167
 
      for (int i = 0; i < len; i++)
168
 
         subArray[i] = array[off + i];
169
 
 
170
 
      outputMultiplexor.write(manager, socketId, subArray);
171
 
   }
172
 
   
173
 
  
174
 
//////////////////////////////////////////////////////////////////////////////////////////////////
175
 
///              The following methods are specific to MultiplexingOutputStream               '///
176
 
//////////////////////////////////////////////////////////////////////////////////////////////////
177
 
 
178
 
   protected void setWriteException(IOException e)
179
 
   {
180
 
      writeException = e;
181
 
   }
182
 
   
183
 
   
184
 
/**
185
 
 * <code>writeInt()</code> is borrowed from <code>DataOutputStream</code>.
186
 
 * It saves the extra expense of creating a <code>DataOutputStream</code>. 
187
 
 * @param i
188
 
 * @throws IOException
189
 
 */
190
 
   public void writeInt(int i) throws IOException
191
 
   {
192
 
      fourBytes[0] = (byte) ((i >>> 24) & 0xff);
193
 
      fourBytes[1] = (byte) ((i >>> 16) & 0xff);
194
 
      fourBytes[2] = (byte) ((i >>>  8) & 0xff);
195
 
      fourBytes[3] = (byte) ((i >>>  0) & 0xff);
196
 
      outputMultiplexor.write(manager, socketId, fourBytes);
197
 
   }
198
 
   
199
 
/**
200
 
 * Determines how to handle a write request depending on what this socket knows about the state
201
 
 * of the peer socket.
202
 
 * <p>
203
 
 * Once this socket knows that the peer socket has closed, no more write requests will be honored.
204
 
 * There seem to be two ways for a socket A to learn that its peer socket B has closed.
205
 
 * <p>
206
 
 * <ol>
207
 
 *  <li>If socket A has executed a write, but no subsequent write is performed on B,
208
 
 *      then the acknowledgement of the write will carry back the information that B has closed.
209
 
 *  <li>If socket B has no pending acknowledgements to send at the time it closes, and then socket A
210
 
 *      does a write after B has closed, the (negative) acknowledgement of the write will carry back
211
 
 *      the information that B has closed.
212
 
 * </ol>
213
 
 * <p>
214
 
 * Java seems to respond differently to the two cases.  The first write after this socket has learned
215
 
 * of the peer's closing through the first scenario will result in a SocketException("Connection reset").
216
 
 * In the second scenario, the first write by this socket after the peer has closed 
217
 
 * will quietly fail (no exception is thrown).  All subsequent writes after either of these two 
218
 
 * scenarios will result in a  SocketException("Broken pipe").
219
 
 * <p>
220
 
 * Currently, MultiplexingOutputStream implements only a simplified version of this behavior.  In
221
 
 * particular, it allows in all cases one write to silently fail, after which all writes result in a
222
 
 * SocketException("Broken pipe");
223
 
 * <p>
224
 
 * Note.  This discussion is based on empirical observation on a linux system, not on examination of code.
225
 
 * Your mileage may vary.
226
 
 */
227
 
   protected void checkStatus() throws IOException
228
 
   {
229
 
      if (closed)
230
 
         throw new SocketException("Socket closed");
231
 
      
232
 
      if (outputShutdown)
233
 
         throw new SocketException("Broken pipe");
234
 
      
235
 
      if (writeException != null)
236
 
         throw writeException;
237
 
      
238
 
      switch (connectionState)
239
 
      {
240
 
         case OPEN:
241
 
            return;
242
 
 
243
 
         case CONNECTION_RESET:
244
 
            connectionState = CLOSED;
245
 
            return;
246
 
            
247
 
         case CLOSED:
248
 
            throw new SocketException("Broken pipe");
249
 
            
250
 
         default:
251
 
            log.error("unrecognized connection state: " + connectionState);
252
 
      }
253
 
   }
254
 
   
255
 
   
256
 
/**
257
 
 * 
258
 
 */
259
 
   protected void handleRemoteDisconnect()
260
 
   {
261
 
      log.debug("entering handleRemoteDisconnect()");
262
 
      
263
 
      switch (connectionState)
264
 
      {
265
 
         case OPEN:
266
 
            connectionState = CONNECTION_RESET;
267
 
            return;
268
 
            
269
 
         default:
270
 
            connectionState = CLOSED;
271
 
            log.error("invalid connection state in handleRemoteDisconnect(): " + connectionState);
272
 
      }
273
 
   }
274
 
   
275
 
   
276
 
/**
277
 
 * 
278
 
 */
279
 
   protected void shutdown()
280
 
   {
281
 
      outputShutdown = true;
282
 
   }
283
 
   
284
 
   
285
 
/**
286
 
 * @param i
287
 
 * @param brackets
288
 
 * @throws IOException
289
 
 */
290
 
   protected void write(int i, int brackets) throws IOException
291
 
   {
292
 
      log.debug("brackets: " + brackets);
293
 
      oneByte[0] = (byte) i;
294
 
      outputMultiplexor.write(manager, socketId, oneByte, brackets);
295
 
   }
296
 
   
297
 
   
298
 
/**
299
 
 * @param i
300
 
 * @param brackets
301
 
 * @throws IOException
302
 
 */
303
 
   protected void writeInt(int i, int brackets) throws IOException
304
 
   {
305
 
      log.debug("brackets: " + brackets);
306
 
      fourBytes[0] = (byte) ((i >>> 24) & 0xff);
307
 
      fourBytes[1] = (byte) ((i >>> 16) & 0xff);
308
 
      fourBytes[2] = (byte) ((i >>>  8) & 0xff);
309
 
      fourBytes[3] = (byte) ((i >>>  0) & 0xff);
310
 
      outputMultiplexor.write(manager, socketId, fourBytes, brackets);
311
 
   }
312
 
}