Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/src/share/classes/sun/rmi/transport/StreamRemoteCall.java
+++ new/src/share/classes/sun/rmi/transport/StreamRemoteCall.java
1 1 /*
2 2 * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 4 *
5 5 * This code is free software; you can redistribute it and/or modify it
6 6 * under the terms of the GNU General Public License version 2 only, as
7 7 * published by the Free Software Foundation. Oracle designates this
8 8 * particular file as subject to the "Classpath" exception as provided
9 9 * by Oracle in the LICENSE file that accompanied this code.
10 10 *
11 11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 14 * version 2 for more details (a copy is included in the LICENSE file that
15 15 * accompanied this code).
16 16 *
17 17 * You should have received a copy of the GNU General Public License version
18 18 * 2 along with this work; if not, write to the Free Software Foundation,
19 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 20 *
21 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 22 * or visit www.oracle.com if you need additional information or have any
23 23 * questions.
24 24 */
25 25
26 26 package sun.rmi.transport;
27 27
28 28 import java.io.DataInputStream;
29 29 import java.io.DataOutputStream;
30 30 import java.io.IOException;
31 31 import java.io.ObjectInput;
32 32 import java.io.ObjectOutput;
33 33 import java.io.StreamCorruptedException;
34 34 import java.rmi.RemoteException;
35 35 import java.rmi.MarshalException;
36 36 import java.rmi.UnmarshalException;
37 37 import java.rmi.server.ObjID;
38 38 import java.rmi.server.RemoteCall;
39 39 import sun.rmi.runtime.Log;
40 40 import sun.rmi.server.UnicastRef;
41 41 import sun.rmi.transport.tcp.TCPEndpoint;
42 42
43 43 /**
44 44 * Stream-based implementation of the RemoteCall interface.
45 45 *
46 46 * @author Ann Wollrath
47 47 */
48 48 public class StreamRemoteCall implements RemoteCall {
49 49 private ConnectionInputStream in = null;
50 50 private ConnectionOutputStream out = null;
51 51 private Connection conn;
52 52 private boolean resultStarted = false;
53 53 private Exception serverException = null;
54 54
55 55 public StreamRemoteCall(Connection c) {
56 56 conn = c;
57 57 }
58 58
59 59 public StreamRemoteCall(Connection c, ObjID id, int op, long hash)
60 60 throws RemoteException
61 61 {
62 62 try {
63 63 conn = c;
64 64 Transport.transportLog.log(Log.VERBOSE,
65 65 "write remote call header...");
66 66
67 67 // write out remote call header info...
68 68 // call header, part 1 (read by Transport)
69 69 conn.getOutputStream().write(TransportConstants.Call);
70 70 getOutputStream(); // creates a MarshalOutputStream
71 71 id.write(out); // object id (target of call)
72 72 // call header, part 2 (read by Dispatcher)
73 73 out.writeInt(op); // method number (operation index)
74 74 out.writeLong(hash); // stub/skeleton hash
75 75 } catch (IOException e) {
76 76 throw new MarshalException("Error marshaling call header", e);
77 77 }
78 78 }
79 79
80 80 /**
81 81 * Return the connection associated with this call.
82 82 */
83 83 public Connection getConnection() {
84 84 return conn;
85 85 }
86 86
87 87 /**
88 88 * Return the output stream the stub/skeleton should put arguments/results
89 89 * into.
90 90 */
91 91 public ObjectOutput getOutputStream() throws IOException {
92 92 return getOutputStream(false);
93 93 }
94 94
95 95 private ObjectOutput getOutputStream(boolean resultStream)
96 96 throws IOException
97 97 {
98 98 if (out == null) {
99 99 Transport.transportLog.log(Log.VERBOSE, "getting output stream");
100 100
101 101 out = new ConnectionOutputStream(conn, resultStream);
102 102 }
103 103 return out;
104 104 }
105 105
106 106 /**
107 107 * Release the outputStream Currently, will not complain if the
108 108 * output stream is released more than once.
109 109 */
110 110 public void releaseOutputStream() throws IOException {
111 111 try {
112 112 if (out != null) {
113 113 try {
114 114 out.flush();
115 115 } finally {
116 116 out.done(); // always start DGC ack timer
117 117 }
118 118 }
119 119 conn.releaseOutputStream();
120 120 } finally {
121 121 out = null;
122 122 }
123 123 }
124 124
125 125 /**
126 126 * Get the InputStream the stub/skeleton should get results/arguments
127 127 * from.
128 128 */
129 129 public ObjectInput getInputStream() throws IOException {
130 130 if (in == null) {
131 131 Transport.transportLog.log(Log.VERBOSE, "getting input stream");
132 132
133 133 in = new ConnectionInputStream(conn.getInputStream());
134 134 }
135 135 return in;
136 136 }
137 137
138 138 /**
139 139 * Release the input stream, this would allow some transports to release
140 140 * the channel early.
141 141 */
142 142 public void releaseInputStream() throws IOException {
143 143 /* WARNING: Currently, the UnicastRef.java invoke methods rely
144 144 * upon this method not throwing an IOException.
145 145 */
146 146
147 147 try {
148 148 if (in != null) {
149 149 // execute MarshalInputStream "done" callbacks
150 150 try {
151 151 in.done();
152 152 } catch (RuntimeException e) {
153 153 }
154 154
155 155 // add saved references to DGC table
156 156 in.registerRefs();
157 157
158 158 /* WARNING: The connection being passed to done may have
159 159 * already been freed.
160 160 */
161 161 in.done(conn);
162 162 }
163 163 conn.releaseInputStream();
164 164 } finally {
165 165 in = null;
166 166 }
167 167 }
168 168
169 169 /**
170 170 * Returns an output stream (may put out header information
171 171 * relating to the success of the call).
172 172 * @param success If true, indicates normal return, else indicates
173 173 * exceptional return.
174 174 * @exception StreamCorruptedException If result stream previously
175 175 * acquired
176 176 * @exception IOException For any other problem with I/O.
177 177 */
178 178 public ObjectOutput getResultStream(boolean success) throws IOException {
179 179 /* make sure result code only marshaled once. */
180 180 if (resultStarted)
181 181 throw new StreamCorruptedException("result already in progress");
182 182 else
183 183 resultStarted = true;
184 184
185 185 // write out return header
186 186 // return header, part 1 (read by Transport)
187 187 DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
188 188 wr.writeByte(TransportConstants.Return);// transport op
189 189 getOutputStream(true); // creates a MarshalOutputStream
190 190 // return header, part 2 (read by client-side RemoteCall)
↓ open down ↓ |
190 lines elided |
↑ open up ↑ |
191 191 if (success) //
192 192 out.writeByte(TransportConstants.NormalReturn);
193 193 else
194 194 out.writeByte(TransportConstants.ExceptionalReturn);
195 195 out.writeID(); // write id for gcAck
196 196 return out;
197 197 }
198 198
199 199 /**
200 200 * Do whatever it takes to execute the call.
201 + * (Exception thrown before fallthrough can occur)
201 202 */
203 + @SuppressWarnings("fallthrough")
202 204 public void executeCall() throws Exception {
203 205 byte returnType;
204 206
205 207 // read result header
206 208 DGCAckHandler ackHandler = null;
207 209 try {
208 210 if (out != null) {
209 211 ackHandler = out.getDGCAckHandler();
210 212 }
211 213 releaseOutputStream();
212 214 DataInputStream rd = new DataInputStream(conn.getInputStream());
213 215 byte op = rd.readByte();
214 216 if (op != TransportConstants.Return) {
215 217 if (Transport.transportLog.isLoggable(Log.BRIEF)) {
216 218 Transport.transportLog.log(Log.BRIEF,
217 219 "transport return code invalid: " + op);
218 220 }
219 221 throw new UnmarshalException("Transport return code invalid");
220 222 }
221 223 getInputStream();
222 224 returnType = in.readByte();
223 225 in.readID(); // id for DGC acknowledgement
224 226 } catch (UnmarshalException e) {
225 227 throw e;
226 228 } catch (IOException e) {
227 229 throw new UnmarshalException("Error unmarshaling return header",
228 230 e);
229 231 } finally {
230 232 if (ackHandler != null) {
231 233 ackHandler.release();
232 234 }
233 235 }
234 236
235 237 // read return value
236 238 switch (returnType) {
237 239 case TransportConstants.NormalReturn:
238 240 break;
239 241
240 242 case TransportConstants.ExceptionalReturn:
241 243 Object ex;
242 244 try {
243 245 ex = in.readObject();
244 246 } catch (Exception e) {
245 247 throw new UnmarshalException("Error unmarshaling return", e);
246 248 }
247 249
248 250 // An exception should have been received,
249 251 // if so throw it, else flag error
250 252 if (ex instanceof Exception) {
251 253 exceptionReceivedFromServer((Exception) ex);
252 254 } else {
253 255 throw new UnmarshalException("Return type not Exception");
254 256 }
255 257 default:
256 258 if (Transport.transportLog.isLoggable(Log.BRIEF)) {
257 259 Transport.transportLog.log(Log.BRIEF,
258 260 "return code invalid: " + returnType);
259 261 }
260 262 throw new UnmarshalException("Return code invalid");
261 263 }
262 264 }
263 265
264 266 /**
265 267 * Routine that causes the stack traces of remote exceptions to be
266 268 * filled in with the current stack trace on the client. Detail
267 269 * exceptions are filled in iteratively.
268 270 */
269 271 protected void exceptionReceivedFromServer(Exception ex) throws Exception {
270 272 serverException = ex;
271 273
272 274 StackTraceElement[] serverTrace = ex.getStackTrace();
273 275 StackTraceElement[] clientTrace = (new Throwable()).getStackTrace();
274 276 StackTraceElement[] combinedTrace =
275 277 new StackTraceElement[serverTrace.length + clientTrace.length];
276 278 System.arraycopy(serverTrace, 0, combinedTrace, 0,
277 279 serverTrace.length);
278 280 System.arraycopy(clientTrace, 0, combinedTrace, serverTrace.length,
279 281 clientTrace.length);
280 282 ex.setStackTrace(combinedTrace);
281 283
282 284 /*
283 285 * Log the details of a server exception thrown as a result of a
284 286 * remote method invocation.
285 287 */
286 288 if (UnicastRef.clientCallLog.isLoggable(Log.BRIEF)) {
287 289 /* log call exception returned from server before it is rethrown */
288 290 TCPEndpoint ep = (TCPEndpoint) conn.getChannel().getEndpoint();
289 291 UnicastRef.clientCallLog.log(Log.BRIEF, "outbound call " +
290 292 "received exception: [" + ep.getHost() + ":" +
291 293 ep.getPort() + "] exception: ", ex);
292 294 }
293 295
294 296 throw ex;
295 297 }
296 298
297 299 /*
298 300 * method to retrieve possible server side exceptions (which will
299 301 * be throw from exceptionReceivedFromServer(...) )
300 302 */
301 303 public Exception getServerException() {
302 304 return serverException;
303 305 }
304 306
305 307 public void done() throws IOException {
306 308 /* WARNING: Currently, the UnicastRef.java invoke methods rely
307 309 * upon this method not throwing an IOException.
308 310 */
309 311
310 312 releaseInputStream();
311 313 }
312 314 }
↓ open down ↓ |
101 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX