Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/src/share/classes/sun/rmi/server/ActivatableRef.java
+++ new/src/share/classes/sun/rmi/server/ActivatableRef.java
1 1 /*
2 2 * Copyright (c) 1997, 2003, 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.Proxy;
32 32 import java.net.MalformedURLException;
33 33 import java.net.URL;
34 34 import java.rmi.*;
35 35 import java.rmi.activation.*;
36 36 import java.rmi.server.Operation;
37 37 import java.rmi.server.RMIClassLoader;
38 38 import java.rmi.server.RemoteCall;
39 39 import java.rmi.server.RemoteObject;
40 40 import java.rmi.server.RemoteObjectInvocationHandler;
41 41 import java.rmi.server.RemoteRef;
42 42 import java.rmi.server.RemoteStub;
43 43
44 44 public class ActivatableRef implements RemoteRef {
45 45
46 46 private static final long serialVersionUID = 7579060052569229166L;
47 47
48 48 protected ActivationID id;
49 49 protected RemoteRef ref;
50 50 transient boolean force = false;
51 51
52 52 private static final int MAX_RETRIES = 3;
53 53 private static final String versionComplaint =
54 54 "activation requires 1.2 stubs";
55 55
56 56 /**
57 57 * Create a new (empty) ActivatableRef
58 58 */
59 59 public ActivatableRef()
60 60 {}
61 61
62 62 /**
63 63 * Create a ActivatableRef with the specified id
64 64 */
65 65 public ActivatableRef(ActivationID id, RemoteRef ref)
66 66 {
67 67 this.id = id;
68 68 this.ref = ref;
69 69 }
70 70
71 71 /**
72 72 * Returns the stub for the remote object whose class is
↓ open down ↓ |
72 lines elided |
↑ open up ↑ |
73 73 * specified in the activation descriptor. The ActivatableRef
74 74 * in the resulting stub has its activation id set to the
75 75 * activation id supplied as the second argument.
76 76 */
77 77 public static Remote getStub(ActivationDesc desc, ActivationID id)
78 78 throws StubNotFoundException
79 79 {
80 80 String className = desc.getClassName();
81 81
82 82 try {
83 - Class cl =
83 + Class<?> cl =
84 84 RMIClassLoader.loadClass(desc.getLocation(), className);
85 85 RemoteRef clientRef = new ActivatableRef(id, null);
86 86 return Util.createProxy(cl, clientRef, false);
87 87
88 88 } catch (IllegalArgumentException e) {
89 89 throw new StubNotFoundException(
90 90 "class implements an illegal remote interface", e);
91 91
92 92 } catch (ClassNotFoundException e) {
93 93 throw new StubNotFoundException("unable to load class: " +
94 94 className, e);
95 95 } catch (MalformedURLException e) {
96 96 throw new StubNotFoundException("malformed URL", e);
97 97 }
98 98 }
99 99
100 100 /**
101 101 * Invoke method on remote object. This method delegates remote
102 102 * method invocation to the underlying ref type. If the
103 103 * underlying reference is not known (is null), then the object
104 104 * must be activated first. If an attempt at method invocation
105 105 * fails, the object should force reactivation. Method invocation
106 106 * must preserve "at most once" call semantics. In RMI, "at most
107 107 * once" applies to parameter deserialization at the remote site
108 108 * and the remote object's method execution. "At most once" does
109 109 * not apply to parameter serialization at the client so the
110 110 * parameters of a call don't need to be buffered in anticipation
111 111 * of call retry. Thus, a method call is only be retried if the
112 112 * initial method invocation does not execute at all at the server
113 113 * (including parameter deserialization).
114 114 */
115 115 public Object invoke(Remote obj,
116 116 java.lang.reflect.Method method,
117 117 Object[] params,
118 118 long opnum)
119 119 throws Exception
120 120 {
121 121
122 122 boolean force = false;
123 123 RemoteRef localRef;
124 124 Exception exception = null;
125 125
126 126 /*
127 127 * Attempt object activation if active ref is unknown.
128 128 * Throws a RemoteException if object can't be activated.
129 129 */
130 130 synchronized (this) {
131 131 if (ref == null) {
132 132 localRef = activate(force);
133 133 force = true;
134 134 } else {
135 135 localRef = ref;
136 136 }
137 137 }
138 138
139 139 for (int retries = MAX_RETRIES; retries > 0; retries--) {
140 140
141 141 try {
142 142 return localRef.invoke(obj, method, params, opnum);
143 143 } catch (NoSuchObjectException e) {
144 144 /*
145 145 * Object is not active in VM; retry call
146 146 */
147 147 exception = e;
148 148 } catch (ConnectException e) {
149 149 /*
150 150 * Failure during connection setup; retry call
151 151 */
152 152 exception = e;
153 153 } catch (UnknownHostException e) {
154 154 /*
155 155 * Failure during connection setup; retry call.
156 156 */
157 157 exception = e;
158 158 } catch (ConnectIOException e) {
159 159 /*
160 160 * Failure setting up multiplexed connection or reusing
161 161 * cached connection; retry call
162 162 */
163 163 exception = e;
164 164 } catch (MarshalException e) {
165 165 /*
166 166 * Failure during parameter serialization; call may
167 167 * have reached server, so call retry not possible.
168 168 */
169 169 throw e;
170 170 } catch (ServerError e) {
171 171 /*
172 172 * Call reached server; propagate remote exception.
173 173 */
174 174 throw e;
175 175 } catch (ServerException e) {
176 176 /*
177 177 * Call reached server; propagate remote exception
178 178 */
179 179 throw e;
180 180 } catch (RemoteException e) {
181 181 /*
182 182 * This is a catch-all for other RemoteExceptions.
183 183 * UnmarshalException being the only one relevant.
184 184 *
185 185 * StubNotFoundException should never show up because
186 186 * it is generally thrown when attempting to locate
187 187 * a stub.
188 188 *
189 189 * UnexpectedException should never show up because
190 190 * it is only thrown by a stub and would be wrapped
191 191 * in a ServerException if it was propagated by a
192 192 * remote call.
193 193 */
194 194 synchronized (this) {
195 195 if (localRef == ref) {
196 196 ref = null; // this may be overly conservative
197 197 }
198 198 }
199 199
200 200 throw e;
201 201 }
202 202
203 203 if (retries > 1) {
204 204 /*
205 205 * Activate object, since object could not be reached.
206 206 */
207 207 synchronized (this) {
208 208 if (localRef.remoteEquals(ref) || ref == null) {
209 209 RemoteRef newRef = activate(force);
210 210
211 211 if (newRef.remoteEquals(localRef) &&
212 212 exception instanceof NoSuchObjectException &&
213 213 force == false) {
214 214 /*
215 215 * If last exception was NoSuchObjectException,
216 216 * then old value of ref is definitely wrong,
217 217 * so make sure that it is different.
218 218 */
219 219 newRef = activate(true);
220 220 }
221 221
222 222 localRef = newRef;
223 223 force = true;
224 224 } else {
225 225 localRef = ref;
226 226 force = false;
227 227 }
228 228 }
229 229 }
230 230 }
231 231
232 232 /*
233 233 * Retries unsuccessful, so throw last exception
234 234 */
235 235 throw exception;
236 236 }
237 237
238 238 /**
239 239 * private method to obtain the ref for a call.
240 240 */
241 241 private synchronized RemoteRef getRef()
242 242 throws RemoteException
243 243 {
244 244 if (ref == null) {
245 245 ref = activate(false);
246 246 }
247 247
248 248 return ref;
249 249 }
250 250
251 251 /**
252 252 * private method to activate the remote object.
253 253 *
254 254 * NOTE: the caller must be synchronized on "this" before
255 255 * calling this method.
256 256 */
257 257 private RemoteRef activate(boolean force)
258 258 throws RemoteException
259 259 {
260 260 assert Thread.holdsLock(this);
261 261
262 262 ref = null;
263 263 try {
264 264 /*
265 265 * Activate the object and retrieve the remote reference
266 266 * from inside the stub returned as the result. Then
267 267 * set this activatable ref's internal ref to be the
268 268 * ref inside the ref of the stub. In more clear terms,
269 269 * the stub returned from the activate call contains an
270 270 * ActivatableRef. We need to set the ref in *this*
271 271 * ActivatableRef to the ref inside the ActivatableRef
272 272 * retrieved from the stub. The ref type embedded in the
273 273 * ActivatableRef is typically a UnicastRef.
274 274 */
275 275
276 276 Remote proxy = id.activate(force);
277 277 ActivatableRef newRef = null;
278 278
279 279 if (proxy instanceof RemoteStub) {
280 280 newRef = (ActivatableRef) ((RemoteStub) proxy).getRef();
281 281 } else {
282 282 /*
283 283 * Assume that proxy is an instance of a dynamic proxy
284 284 * class. If that assumption is not correct, or either of
285 285 * the casts below fails, the resulting exception will be
286 286 * wrapped in an ActivateFailedException below.
287 287 */
288 288 RemoteObjectInvocationHandler handler =
289 289 (RemoteObjectInvocationHandler)
290 290 Proxy.getInvocationHandler(proxy);
291 291 newRef = (ActivatableRef) handler.getRef();
292 292 }
293 293 ref = newRef.ref;
294 294 return ref;
295 295
296 296 } catch (ConnectException e) {
297 297 throw new ConnectException("activation failed", e);
298 298 } catch (RemoteException e) {
299 299 throw new ConnectIOException("activation failed", e);
300 300 } catch (UnknownObjectException e) {
301 301 throw new NoSuchObjectException("object not registered");
302 302 } catch (ActivationException e) {
303 303 throw new ActivateFailedException("activation failed", e);
304 304 }
305 305 }
306 306
307 307 /**
308 308 * This call is used by the old 1.1 stub protocol and is
309 309 * unsupported since activation requires 1.2 stubs.
310 310 */
311 311 public synchronized RemoteCall newCall(RemoteObject obj,
312 312 Operation[] ops,
313 313 int opnum,
314 314 long hash)
315 315 throws RemoteException
316 316 {
317 317 throw new UnsupportedOperationException(versionComplaint);
318 318 }
319 319
320 320 /**
321 321 * This call is used by the old 1.1 stub protocol and is
322 322 * unsupported since activation requires 1.2 stubs.
323 323 */
324 324 public void invoke(RemoteCall call) throws Exception
325 325 {
326 326 throw new UnsupportedOperationException(versionComplaint);
327 327 }
328 328
329 329 /**
330 330 * This call is used by the old 1.1 stub protocol and is
331 331 * unsupported since activation requires 1.2 stubs.
332 332 */
333 333 public void done(RemoteCall call) throws RemoteException {
334 334 throw new UnsupportedOperationException(versionComplaint);
335 335 }
336 336
337 337 /**
338 338 * Returns the class of the ref type to be serialized
339 339 */
340 340 public String getRefClass(ObjectOutput out)
341 341 {
342 342 return "ActivatableRef";
343 343 }
344 344
345 345 /**
346 346 * Write out external representation for remote ref.
347 347 */
348 348 public void writeExternal(ObjectOutput out) throws IOException
349 349 {
350 350 RemoteRef localRef = ref;
351 351
352 352 out.writeObject(id);
353 353 if (localRef == null) {
354 354 out.writeUTF("");
355 355 } else {
356 356 out.writeUTF(localRef.getRefClass(out));
357 357 localRef.writeExternal(out);
358 358 }
359 359 }
360 360
361 361 /**
362 362 * Read in external representation for remote ref.
363 363 * @exception ClassNotFoundException If the class for an object
364 364 * being restored cannot be found.
365 365 */
↓ open down ↓ |
272 lines elided |
↑ open up ↑ |
366 366 public void readExternal(ObjectInput in)
367 367 throws IOException, ClassNotFoundException
368 368 {
369 369 id = (ActivationID)in.readObject();
370 370 ref = null;
371 371 String className = in.readUTF();
372 372
373 373 if (className.equals("")) return;
374 374
375 375 try {
376 - Class refClass = Class.forName(RemoteRef.packagePrefix + "." +
376 + Class<?> refClass = Class.forName(RemoteRef.packagePrefix + "." +
377 377 className);
378 378 ref = (RemoteRef)refClass.newInstance();
379 379 ref.readExternal(in);
380 380 } catch (InstantiationException e) {
381 381 throw new UnmarshalException("Unable to create remote reference",
382 382 e);
383 383 } catch (IllegalAccessException e) {
384 384 throw new UnmarshalException("Illegal access creating remote reference");
385 385 }
386 386 }
387 387
388 388 //----------------------------------------------------------------------;
389 389 /**
390 390 * Method from object, forward from RemoteObject
391 391 */
392 392 public String remoteToString() {
393 393 return Util.getUnqualifiedName(getClass()) +
394 394 " [remoteRef: " + ref + "]";
395 395 }
396 396
397 397 /**
398 398 * default implementation of hashCode for remote objects
399 399 */
400 400 public int remoteHashCode() {
401 401 return id.hashCode();
402 402 }
403 403
404 404 /** default implementation of equals for remote objects
405 405 */
406 406 public boolean remoteEquals(RemoteRef ref) {
407 407 if (ref instanceof ActivatableRef)
408 408 return id.equals(((ActivatableRef)ref).id);
409 409 return false;
410 410 }
411 411 }
↓ open down ↓ |
25 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX