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/UnicastRef.java (1 of 18352 files). Show all

Unified · Split

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