History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/rmi/server/ActivatableRef.java (1 of 18352 files). Show all

Unified · Split

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