001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: *
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: /**
020: * @author Mikhail A. Markov
021: * @version $Revision: 1.1.2.2 $
022: */package org.apache.harmony.rmi.remoteref;
023:
024: import java.lang.reflect.Method;
025: import java.io.DataOutputStream;
026: import java.io.IOException;
027: import java.io.ObjectOutputStream;
028: import java.io.ObjectOutput;
029: import java.io.ObjectInput;
030: import java.rmi.MarshalException;
031: import java.rmi.Remote;
032: import java.rmi.RemoteException;
033: import java.rmi.UnmarshalException;
034: import java.rmi.server.ObjID;
035: import java.rmi.server.RemoteObject;
036: import java.rmi.server.RemoteCall;
037: import java.rmi.server.Operation;
038:
039: import org.apache.harmony.rmi.client.ClientConnection;
040: import org.apache.harmony.rmi.client.ClientConnectionManager;
041: import org.apache.harmony.rmi.client.ClientRemoteCall;
042: import org.apache.harmony.rmi.common.RMILog;
043: import org.apache.harmony.rmi.internal.nls.Messages;
044: import org.apache.harmony.rmi.server.RemoteRefBase;
045: import org.apache.harmony.rmi.transport.Endpoint;
046: import org.apache.harmony.rmi.transport.RMIObjectInputStream;
047: import org.apache.harmony.rmi.transport.RMIObjectOutputStream;
048: import org.apache.harmony.rmi.transport.RMIProtocolConstants;
049:
050: /**
051: * Implementation of handle for remote objects.
052: *
053: * @author Mikhail A. Markov
054: * @version $Revision: 1.1.2.2 $
055: */
056: public class UnicastRef extends RemoteRefBase {
057:
058: private static final long serialVersionUID = -2637470287094993242L;
059:
060: /** Logger where to write client-side log of remote calls. */
061: public static final RMILog clientCallsLog = RMILog
062: .getClientCallsLog();
063:
064: // Log where to write server-side log of remote reference activity
065: private static final RMILog clientRefLog = RMILog.getClientRefLog();
066:
067: /**
068: * Default constructor: constructs an empty instance of this class.
069: */
070: public UnicastRef() {
071: ep = null;
072: objId = null;
073: }
074:
075: /**
076: * Constructs UnicastRef.
077: *
078: * @param host host name where remote object impl. is located.
079: * @param port port on remote host where remote object accepts RMI calls
080: * @param objId Object ID of remoteObject
081: */
082: public UnicastRef(String host, int port, ObjID objId) {
083: this (new Endpoint(host, port, null, null), objId);
084: }
085:
086: /**
087: * Constructs UnicastRef using specified Endpoint and objId.
088: *
089: * @param ep Endpoint for remote calls
090: * @param objId Object ID of remote object
091: */
092: public UnicastRef(Endpoint ep, ObjID objId) {
093: this (ep, objId, false);
094: }
095:
096: /**
097: * Constructs UnicastRef using specified Endpoint and objId.
098: *
099: * @param ep Endpoint for remote calls
100: * @param objId Object ID of remote object
101: * @param isLocal if true this UnicastRef belongs to local object
102: */
103: public UnicastRef(Endpoint ep, ObjID objId, boolean isLocal) {
104: this .ep = ep;
105: this .objId = objId;
106: this .isLocal = isLocal;
107: }
108:
109: /**
110: * @see RemoteRef.invoke(Remote, Method, Object[], long)
111: */
112: public Object invoke(Remote obj, Method m, Object[] params, long h)
113: throws Exception {
114: Object toReturn = null;
115: logClientCall(obj, m.toString());
116:
117: if (clientRefLog.isLoggable(RMILog.BRIEF)) {
118: // rmi.log.100=New call: method = [{0}], hash = {1}
119: clientRefLog.log(RMILog.BRIEF, Messages.getString(
120: "rmi.log.100", //$NON-NLS-1$
121: m, h));
122: }
123:
124: // initiate a new call
125: RemoteCall call = newCall(null, null, -1, h);
126: ((ClientRemoteCall) call).setMethod(m);
127:
128: try {
129: // write arguments for the method called
130: RMIObjectOutputStream oout = (RMIObjectOutputStream) call
131: .getOutputStream();
132: Class[] paramTypes = m.getParameterTypes();
133:
134: try {
135: if (params != null) {
136: for (int i = 0; i < params.length; ++i) {
137: oout.writeRMIObject(params[i], paramTypes[i]);
138: }
139: }
140: } catch (IOException ioe) {
141: // rmi.6F=I/O error occurred while marshalling arguments
142: throw new MarshalException(
143: Messages.getString("rmi.6F"), ioe); //$NON-NLS-1$
144: }
145:
146: // execute the call
147: invoke(call);
148:
149: // read return value
150: // if we pass here then server produced no exceptions
151: if (m.getReturnType() != Void.TYPE) {
152: RMIObjectInputStream oin = (RMIObjectInputStream) call
153: .getInputStream();
154:
155: try {
156: toReturn = oin.readRMIObject(m.getReturnType());
157: } catch (IOException ioe) {
158: // rmi.70=IOException occurred while unmarshalling return value
159: throw new UnmarshalException(Messages
160: .getString("rmi.70"), ioe); //$NON-NLS-1$
161: } catch (ClassNotFoundException cnfe) {
162: // rmi.71=ClassNotFoundException occurred while unmarshalling return value
163: throw new UnmarshalException(Messages
164: .getString("rmi.71"), cnfe); //$NON-NLS-1$
165: }
166: }
167: } catch (IOException ioe) {
168: ((ClientRemoteCall) call).close();
169: throw ioe;
170: }
171: done(call);
172: return toReturn;
173: }
174:
175: /**
176: * @see RemoteRef.getRefClass(ObjectOutput)
177: */
178: public String getRefClass(ObjectOutput out) {
179: return "UnicastRef"; //$NON-NLS-1$
180: }
181:
182: /**
183: * Writes this UnicastRef object to the specified output stream.
184: *
185: * @param out the stream to write the object to
186: *
187: * @throws IOException if any I/O error occurred or class is not serializable
188: */
189: public void writeExternal(ObjectOutput out) throws IOException {
190: ep.writeExternal(out, false);
191: writeCommon(out);
192: }
193:
194: /**
195: * Reads data for creating RemoteRef object from the specified input stream.
196: *
197: * @param in the stream to read data from
198: *
199: * @throws IOException if any I/O error occurred
200: * @throws ClassNotFoundException if class could not be loaded by current
201: * class loader
202: */
203: public void readExternal(ObjectInput in) throws IOException,
204: ClassNotFoundException {
205: ep = Endpoint.readExternal(in, false);
206: readCommon(in);
207: }
208:
209: /**
210: * @see RemoteRef.newCall(RemoteObject, Operation[], int, long)
211: */
212: public RemoteCall newCall(RemoteObject obj, Operation[] op,
213: int opnum, long hash) throws RemoteException {
214: if (opnum != -1) {
215: if (clientRefLog.isLoggable(RMILog.BRIEF)) {
216: // rmi.log.101=New call: method = [{0}], opnum = {1}, hash = {2}
217: clientRefLog.log(RMILog.BRIEF, Messages.getString(
218: "rmi.log.101", //$NON-NLS-1$
219: new Object[] { op[opnum].toString(), opnum,
220: hash }));
221: }
222: logClientCall(obj, op[opnum].toString());
223: }
224: ClientConnection conn = ClientConnectionManager
225: .getConnection(ep);
226: RemoteCall call = new ClientRemoteCall(conn);
227:
228: if (clientRefLog.isLoggable(RMILog.VERBOSE)) {
229: //rmi.log.102=Created new call {0}
230: clientRefLog.log(RMILog.VERBOSE, Messages.getString(
231: "rmi.log.102", call)); //$NON-NLS-1$
232: }
233:
234: try {
235: // write method signature
236: DataOutputStream dout = new DataOutputStream(conn
237: .getOutputStream());
238: dout.writeByte(RMIProtocolConstants.CALL_MSG);
239: ObjectOutputStream oout = (ObjectOutputStream) call
240: .getOutputStream();
241: objId.write(oout);
242: oout.writeInt(opnum);
243: oout.writeLong(hash);
244: return call;
245: } catch (IOException ioe) {
246: done(call);
247: // rmi.72=Unable to marshal call header
248: throw new MarshalException(
249: Messages.getString("rmi.72"), ioe); //$NON-NLS-1$
250: }
251: }
252:
253: /**
254: * @see RemoteRef.invoke(RemoteCall)
255: */
256: public void invoke(RemoteCall call) throws Exception {
257: if (clientRefLog.isLoggable(RMILog.VERBOSE)) {
258: // rmi.log.103=Execute call {0}
259: clientRefLog.log(RMILog.VERBOSE, Messages.getString(
260: "rmi.log.103", call)); //$NON-NLS-1$
261: }
262: call.releaseOutputStream();
263: call.executeCall();
264: }
265:
266: /**
267: * @see RemoteRef.done(RemoteCall)
268: */
269: public void done(RemoteCall call) throws RemoteException {
270: if (clientRefLog.isLoggable(RMILog.VERBOSE)) {
271: // rmi.log.104=Finalize call {0}
272: clientRefLog.log(RMILog.VERBOSE, Messages.getString(
273: "rmi.log.104", call)); //$NON-NLS-1$
274: }
275:
276: try {
277: call.done();
278: } catch (Exception ex) {
279: }
280: }
281:
282: // Logs remote method call on client side.
283: private void logClientCall(Remote obj, String m) {
284: if (clientCallsLog.isLoggable(RMILog.VERBOSE)) {
285: // rmi.log.105=Outbound remote call to endpoint:{0}: method:[{1}], obj:[{2}].
286: clientCallsLog.log(RMILog.VERBOSE, Messages.getString(
287: "rmi.log.105", //$NON-NLS-1$
288: new Object[] { ep, m, obj }));
289: }
290: }
291: }
|