Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/src/share/classes/sun/rmi/server/UnicastRef.java
+++ new/src/share/classes/sun/rmi/server/UnicastRef.java
1 1 /*
2 2 * Copyright (c) 1996, 2006, 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.server;
27 27
28 28 import java.io.IOException;
29 29 import java.io.ObjectInput;
30 30 import java.io.ObjectOutput;
31 31 import java.lang.reflect.Method;
32 32 import java.rmi.MarshalException;
33 33 import java.rmi.Remote;
34 34 import java.rmi.RemoteException;
35 35 import java.rmi.ServerException;
36 36 import java.rmi.UnmarshalException;
37 37 import java.rmi.server.Operation;
38 38 import java.rmi.server.RemoteCall;
39 39 import java.rmi.server.RemoteObject;
40 40 import java.rmi.server.RemoteRef;
41 41 import java.security.AccessController;
42 42 import sun.rmi.runtime.Log;
43 43 import sun.rmi.transport.Connection;
44 44 import sun.rmi.transport.LiveRef;
45 45 import sun.rmi.transport.StreamRemoteCall;
46 46 import sun.security.action.GetBooleanAction;
47 47
48 48 /**
49 49 * NOTE: There is a JDK-internal dependency on the existence of this
50 50 * class's getLiveRef method (as it is inherited by UnicastRef2) in
51 51 * the implementation of javax.management.remote.rmi.RMIConnector.
52 52 **/
53 53 public class UnicastRef implements RemoteRef {
54 54
55 55 /**
56 56 * Client-side transport log.
57 57 */
↓ open down ↓ |
57 lines elided |
↑ open up ↑ |
58 58 public static final Log clientRefLog =
59 59 Log.getLog("sun.rmi.client.ref", "transport", Util.logLevel);
60 60
61 61 /**
62 62 * Client-side call log.
63 63 */
64 64 public static final Log clientCallLog =
65 65 Log.getLog("sun.rmi.client.call", "RMI",
66 66 AccessController.doPrivileged(
67 67 new GetBooleanAction("sun.rmi.client.logCalls")));
68 + private static final long serialVersionUID = 8258372400816541186L;
68 69
69 70 protected LiveRef ref;
70 71
71 72 /**
72 73 * Create a new (empty) Unicast remote reference.
73 74 */
74 75 public UnicastRef() {
75 76 }
76 77
77 78 /**
78 79 * Create a new Unicast RemoteRef.
79 80 */
80 81 public UnicastRef(LiveRef liveRef) {
81 82 ref = liveRef;
82 83 }
83 84
84 85 /**
85 86 * Returns the current value of this UnicastRef's underlying
86 87 * LiveRef.
87 88 *
88 89 * NOTE: There is a JDK-internal dependency on the existence of
89 90 * this method (as it is inherited by UnicastRef) in the
90 91 * implementation of javax.management.remote.rmi.RMIConnector.
91 92 **/
92 93 public LiveRef getLiveRef() {
93 94 return ref;
94 95 }
95 96
96 97 /**
97 98 * Invoke a method. This form of delegating method invocation
98 99 * to the reference allows the reference to take care of
99 100 * setting up the connection to the remote host, marshalling
100 101 * some representation for the method and parameters, then
101 102 * communicating the method invocation to the remote host.
102 103 * This method either returns the result of a method invocation
103 104 * on the remote object which resides on the remote host or
104 105 * throws a RemoteException if the call failed or an
105 106 * application-level exception if the remote invocation throws
106 107 * an exception.
107 108 *
108 109 * @param obj the proxy for the remote object
109 110 * @param method the method to be invoked
110 111 * @param params the parameter list
111 112 * @param opnum a hash that may be used to represent the method
112 113 * @since 1.2
113 114 */
114 115 public Object invoke(Remote obj,
115 116 Method method,
116 117 Object[] params,
117 118 long opnum)
118 119 throws Exception
119 120 {
120 121 if (clientRefLog.isLoggable(Log.VERBOSE)) {
121 122 clientRefLog.log(Log.VERBOSE, "method: " + method);
122 123 }
123 124
124 125 if (clientCallLog.isLoggable(Log.VERBOSE)) {
125 126 logClientCall(obj, method);
126 127 }
127 128
128 129 Connection conn = ref.getChannel().newConnection();
129 130 RemoteCall call = null;
130 131 boolean reuse = true;
131 132
132 133 /* If the call connection is "reused" early, remember not to
133 134 * reuse again.
134 135 */
135 136 boolean alreadyFreed = false;
136 137
137 138 try {
138 139 if (clientRefLog.isLoggable(Log.VERBOSE)) {
139 140 clientRefLog.log(Log.VERBOSE, "opnum = " + opnum);
140 141 }
141 142
142 143 // create call context
143 144 call = new StreamRemoteCall(conn, ref.getObjID(), -1, opnum);
144 145
145 146 // marshal parameters
146 147 try {
147 148 ObjectOutput out = call.getOutputStream();
148 149 marshalCustomCallData(out);
149 150 Class<?>[] types = method.getParameterTypes();
150 151 for (int i = 0; i < types.length; i++) {
151 152 marshalValue(types[i], params[i], out);
152 153 }
153 154 } catch (IOException e) {
154 155 clientRefLog.log(Log.BRIEF,
155 156 "IOException marshalling arguments: ", e);
156 157 throw new MarshalException("error marshalling arguments", e);
157 158 }
158 159
159 160 // unmarshal return
160 161 call.executeCall();
161 162
162 163 try {
163 164 Class<?> rtype = method.getReturnType();
164 165 if (rtype == void.class)
165 166 return null;
166 167 ObjectInput in = call.getInputStream();
167 168
168 169 /* StreamRemoteCall.done() does not actually make use
169 170 * of conn, therefore it is safe to reuse this
170 171 * connection before the dirty call is sent for
171 172 * registered refs.
172 173 */
173 174 Object returnValue = unmarshalValue(rtype, in);
174 175
175 176 /* we are freeing the connection now, do not free
176 177 * again or reuse.
177 178 */
178 179 alreadyFreed = true;
179 180
180 181 /* if we got to this point, reuse must have been true. */
181 182 clientRefLog.log(Log.BRIEF, "free connection (reuse = true)");
182 183
183 184 /* Free the call's connection early. */
184 185 ref.getChannel().free(conn, true);
185 186
186 187 return returnValue;
187 188
188 189 } catch (IOException e) {
189 190 clientRefLog.log(Log.BRIEF,
190 191 "IOException unmarshalling return: ", e);
191 192 throw new UnmarshalException("error unmarshalling return", e);
192 193 } catch (ClassNotFoundException e) {
193 194 clientRefLog.log(Log.BRIEF,
194 195 "ClassNotFoundException unmarshalling return: ", e);
195 196
196 197 throw new UnmarshalException("error unmarshalling return", e);
197 198 } finally {
198 199 try {
199 200 call.done();
200 201 } catch (IOException e) {
201 202 /* WARNING: If the conn has been reused early,
202 203 * then it is too late to recover from thrown
203 204 * IOExceptions caught here. This code is relying
204 205 * on StreamRemoteCall.done() not actually
205 206 * throwing IOExceptions.
206 207 */
207 208 reuse = false;
208 209 }
209 210 }
210 211
211 212 } catch (RuntimeException e) {
212 213 /*
213 214 * Need to distinguish between client (generated by the
214 215 * invoke method itself) and server RuntimeExceptions.
215 216 * Client side RuntimeExceptions are likely to have
216 217 * corrupted the call connection and those from the server
217 218 * are not likely to have done so. If the exception came
218 219 * from the server the call connection should be reused.
219 220 */
220 221 if ((call == null) ||
221 222 (((StreamRemoteCall) call).getServerException() != e))
222 223 {
223 224 reuse = false;
224 225 }
225 226 throw e;
226 227
227 228 } catch (RemoteException e) {
228 229 /*
229 230 * Some failure during call; assume connection cannot
230 231 * be reused. Must assume failure even if ServerException
231 232 * or ServerError occurs since these failures can happen
232 233 * during parameter deserialization which would leave
233 234 * the connection in a corrupted state.
234 235 */
235 236 reuse = false;
236 237 throw e;
237 238
238 239 } catch (Error e) {
239 240 /* If errors occurred, the connection is most likely not
240 241 * reusable.
241 242 */
242 243 reuse = false;
243 244 throw e;
244 245
245 246 } finally {
246 247
247 248 /* alreadyFreed ensures that we do not log a reuse that
248 249 * may have already happened.
249 250 */
250 251 if (!alreadyFreed) {
251 252 if (clientRefLog.isLoggable(Log.BRIEF)) {
252 253 clientRefLog.log(Log.BRIEF, "free connection (reuse = " +
253 254 reuse + ")");
254 255 }
255 256 ref.getChannel().free(conn, reuse);
256 257 }
257 258 }
258 259 }
259 260
260 261 protected void marshalCustomCallData(ObjectOutput out) throws IOException
261 262 {}
262 263
263 264 /**
264 265 * Marshal value to an ObjectOutput sink using RMI's serialization
265 266 * format for parameters or return values.
266 267 */
267 268 protected static void marshalValue(Class<?> type, Object value,
268 269 ObjectOutput out)
269 270 throws IOException
270 271 {
271 272 if (type.isPrimitive()) {
272 273 if (type == int.class) {
273 274 out.writeInt(((Integer) value).intValue());
274 275 } else if (type == boolean.class) {
275 276 out.writeBoolean(((Boolean) value).booleanValue());
276 277 } else if (type == byte.class) {
277 278 out.writeByte(((Byte) value).byteValue());
278 279 } else if (type == char.class) {
279 280 out.writeChar(((Character) value).charValue());
280 281 } else if (type == short.class) {
281 282 out.writeShort(((Short) value).shortValue());
282 283 } else if (type == long.class) {
283 284 out.writeLong(((Long) value).longValue());
284 285 } else if (type == float.class) {
285 286 out.writeFloat(((Float) value).floatValue());
286 287 } else if (type == double.class) {
287 288 out.writeDouble(((Double) value).doubleValue());
288 289 } else {
289 290 throw new Error("Unrecognized primitive type: " + type);
290 291 }
291 292 } else {
292 293 out.writeObject(value);
293 294 }
294 295 }
295 296
296 297 /**
297 298 * Unmarshal value from an ObjectInput source using RMI's serialization
298 299 * format for parameters or return values.
299 300 */
300 301 protected static Object unmarshalValue(Class<?> type, ObjectInput in)
301 302 throws IOException, ClassNotFoundException
302 303 {
303 304 if (type.isPrimitive()) {
304 305 if (type == int.class) {
305 306 return Integer.valueOf(in.readInt());
306 307 } else if (type == boolean.class) {
307 308 return Boolean.valueOf(in.readBoolean());
308 309 } else if (type == byte.class) {
309 310 return Byte.valueOf(in.readByte());
310 311 } else if (type == char.class) {
311 312 return Character.valueOf(in.readChar());
312 313 } else if (type == short.class) {
313 314 return Short.valueOf(in.readShort());
314 315 } else if (type == long.class) {
315 316 return Long.valueOf(in.readLong());
316 317 } else if (type == float.class) {
317 318 return Float.valueOf(in.readFloat());
318 319 } else if (type == double.class) {
319 320 return Double.valueOf(in.readDouble());
320 321 } else {
321 322 throw new Error("Unrecognized primitive type: " + type);
322 323 }
323 324 } else {
324 325 return in.readObject();
325 326 }
326 327 }
327 328
328 329 /**
329 330 * Create an appropriate call object for a new call on this object.
330 331 * Passing operation array and index, allows the stubs generator to
331 332 * assign the operation indexes and interpret them. The RemoteRef
332 333 * may need the operation to encode in for the call.
333 334 */
334 335 public RemoteCall newCall(RemoteObject obj, Operation[] ops, int opnum,
335 336 long hash)
336 337 throws RemoteException
337 338 {
338 339 clientRefLog.log(Log.BRIEF, "get connection");
339 340
340 341 Connection conn = ref.getChannel().newConnection();
341 342 try {
342 343 clientRefLog.log(Log.VERBOSE, "create call context");
343 344
344 345 /* log information about the outgoing call */
345 346 if (clientCallLog.isLoggable(Log.VERBOSE)) {
346 347 logClientCall(obj, ops[opnum]);
347 348 }
348 349
349 350 RemoteCall call =
350 351 new StreamRemoteCall(conn, ref.getObjID(), opnum, hash);
351 352 try {
352 353 marshalCustomCallData(call.getOutputStream());
353 354 } catch (IOException e) {
354 355 throw new MarshalException("error marshaling " +
355 356 "custom call data");
356 357 }
357 358 return call;
358 359 } catch (RemoteException e) {
359 360 ref.getChannel().free(conn, false);
360 361 throw e;
361 362 }
362 363 }
363 364
364 365 /**
365 366 * Invoke makes the remote call present in the RemoteCall object.
366 367 *
367 368 * Invoke will raise any "user" exceptions which
368 369 * should pass through and not be caught by the stub. If any
369 370 * exception is raised during the remote invocation, invoke should
370 371 * take care of cleaning up the connection before raising the
371 372 * "user" or remote exception.
372 373 */
373 374 public void invoke(RemoteCall call) throws Exception {
374 375 try {
375 376 clientRefLog.log(Log.VERBOSE, "execute call");
376 377
377 378 call.executeCall();
378 379
379 380 } catch (RemoteException e) {
380 381 /*
381 382 * Call did not complete; connection can't be reused.
382 383 */
383 384 clientRefLog.log(Log.BRIEF, "exception: ", e);
384 385 free(call, false);
385 386 throw e;
386 387
387 388 } catch (Error e) {
388 389 /* If errors occurred, the connection is most likely not
389 390 * reusable.
390 391 */
391 392 clientRefLog.log(Log.BRIEF, "error: ", e);
392 393 free(call, false);
393 394 throw e;
394 395
395 396 } catch (RuntimeException e) {
396 397 /*
397 398 * REMIND: Since runtime exceptions are no longer wrapped,
398 399 * we can't assue that the connection was left in
399 400 * a reusable state. Is this okay?
400 401 */
401 402 clientRefLog.log(Log.BRIEF, "exception: ", e);
402 403 free(call, false);
403 404 throw e;
404 405
405 406 } catch (Exception e) {
406 407 /*
407 408 * Assume that these other exceptions are user exceptions
408 409 * and leave the connection in a reusable state.
409 410 */
410 411 clientRefLog.log(Log.BRIEF, "exception: ", e);
411 412 free(call, true);
412 413 /* reraise user (and unknown) exceptions. */
413 414 throw e;
414 415 }
415 416
416 417 /*
417 418 * Don't free the connection if an exception did not
418 419 * occur because the stub needs to unmarshal the
419 420 * return value. The connection will be freed
420 421 * by a call to the "done" method.
421 422 */
422 423 }
423 424
424 425 /**
425 426 * Private method to free a connection.
426 427 */
427 428 private void free(RemoteCall call, boolean reuse) throws RemoteException {
428 429 Connection conn = ((StreamRemoteCall)call).getConnection();
429 430 ref.getChannel().free(conn, reuse);
430 431 }
431 432
432 433 /**
433 434 * Done should only be called if the invoke returns successfully
434 435 * (non-exceptionally) to the stub. It allows the remote reference to
435 436 * clean up (or reuse) the connection.
436 437 */
437 438 public void done(RemoteCall call) throws RemoteException {
438 439
439 440 /* Done only uses the connection inside the call to obtain the
440 441 * channel the connection uses. Once all information is read
441 442 * from the connection, the connection may be freed.
442 443 */
443 444 clientRefLog.log(Log.BRIEF, "free connection (reuse = true)");
444 445
445 446 /* Free the call connection early. */
446 447 free(call, true);
447 448
448 449 try {
449 450 call.done();
450 451 } catch (IOException e) {
451 452 /* WARNING: If the conn has been reused early, then it is
452 453 * too late to recover from thrown IOExceptions caught
453 454 * here. This code is relying on StreamRemoteCall.done()
454 455 * not actually throwing IOExceptions.
455 456 */
456 457 }
457 458 }
458 459
459 460 /**
460 461 * Log the details of an outgoing call. The method parameter is either of
461 462 * type java.lang.reflect.Method or java.rmi.server.Operation.
462 463 */
463 464 void logClientCall(Object obj, Object method) {
464 465 clientCallLog.log(Log.VERBOSE, "outbound call: " +
465 466 ref + " : " + obj.getClass().getName() +
466 467 ref.getObjID().toString() + ": " + method);
467 468 }
468 469
469 470 /**
470 471 * Returns the class of the ref type to be serialized
471 472 */
472 473 public String getRefClass(ObjectOutput out) {
473 474 return "UnicastRef";
474 475 }
475 476
476 477 /**
477 478 * Write out external representation for remote ref.
478 479 */
479 480 public void writeExternal(ObjectOutput out) throws IOException {
480 481 ref.write(out, false);
481 482 }
482 483
483 484 /**
484 485 * Read in external representation for remote ref.
485 486 * @exception ClassNotFoundException If the class for an object
486 487 * being restored cannot be found.
487 488 */
488 489 public void readExternal(ObjectInput in)
489 490 throws IOException, ClassNotFoundException
490 491 {
491 492 ref = LiveRef.read(in, false);
492 493 }
493 494
494 495 //----------------------------------------------------------------------;
495 496 /**
496 497 * Method from object, forward from RemoteObject
497 498 */
498 499 public String remoteToString() {
499 500 return Util.getUnqualifiedName(getClass()) + " [liveRef: " + ref + "]";
500 501 }
501 502
502 503 /**
503 504 * default implementation of hashCode for remote objects
504 505 */
505 506 public int remoteHashCode() {
506 507 return ref.hashCode();
507 508 }
508 509
509 510 /** default implementation of equals for remote objects
510 511 */
511 512 public boolean remoteEquals(RemoteRef sub) {
512 513 if (sub instanceof UnicastRef)
513 514 return ref.remoteEquals(((UnicastRef)sub).ref);
514 515 return false;
515 516 }
516 517 }
↓ open down ↓ |
439 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX