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 Victor A. Martynov
021: * @version $Revision: 1.1.2.3 $
022: */package org.apache.harmony.rmi.remoteref;
023:
024: import java.io.IOException;
025: import java.io.ObjectInput;
026: import java.io.ObjectOutput;
027: import java.lang.reflect.Constructor;
028: import java.lang.reflect.Method;
029: import java.net.ConnectException;
030: import java.rmi.ConnectIOException;
031: import java.rmi.Remote;
032: import java.rmi.StubNotFoundException;
033: import java.rmi.activation.ActivationDesc;
034: import java.rmi.activation.ActivationID;
035: import java.rmi.activation.UnknownObjectException;
036: import java.rmi.server.RMIClassLoader;
037: import java.rmi.server.RemoteRef;
038: import java.rmi.server.RemoteStub;
039:
040: import org.apache.harmony.rmi.common.RMILog;
041: import org.apache.harmony.rmi.common.RMIUtil;
042: import org.apache.harmony.rmi.internal.nls.Messages;
043:
044: /**
045: * Activatable ref is the Remote Reference that organizes the next level of indirection during the remote method invocation.
046: * It means that ActivatableRef contains another RemoteRef inside that can be 'null' if the ActivatableRef wasn't yet activated or will contain
047: * the Remote Reference to the active object.
048: *
049: * @author Victor A. Martynov
050: * @version $Revision: 1.1.2.3 $
051: *
052: * ActivatableRef
053: */
054: public class ActivatableRef extends UnicastRef2 {
055:
056: private static final long serialVersionUID = -2842326509564440186L;
057:
058: RMILog rlog = RMILog.getActivationLog();
059:
060: /**
061: * The ActivationID of the Activatable Object of this ActivatableRef.
062: */
063: protected ActivationID id;
064:
065: /**
066: * The internal Remote Reference of this ActivatableRef. This ref is 'null' initially
067: * but when the remote call happens, 'ref' points to the active object.
068: */
069: protected RemoteRef ref;
070:
071: /**
072: * Default constructor. It is used mostly in Deserialization.
073: */
074: public ActivatableRef() {
075: }
076:
077: /**
078: * Special constructor to create ActivatableRef with the given Remote Reference and ActivationID.
079: * Used in ActivatableServerRef.
080: * @param aid The handle for the Activatable Object.
081: * @param ref The internal reference of this ActivatableRef.
082: */
083: public ActivatableRef(ActivationID aid, RemoteRef ref) {
084: this .ref = ref;
085: this .id = aid;
086: }
087:
088: /**
089: * Returns the Remote Stub for the given activatable class.
090: */
091: public static RemoteStub getStub(ActivationDesc desc,
092: ActivationID aid) throws StubNotFoundException {
093:
094: String cn = desc.getClassName();
095: String stubName = ""; //$NON-NLS-1$
096:
097: try {
098: Class cl = RMIClassLoader.loadClass(desc.getLocation(), cn);
099: Class rcl = RMIUtil.getRemoteClass(cl);
100: stubName = rcl.getName() + "_Stub"; //$NON-NLS-1$
101: Class stubClass = RMIClassLoader.loadClass((String) null,
102: stubName);
103: Constructor constructor = stubClass
104: .getConstructor(new Class[] { RemoteRef.class });
105: RemoteStub stub = (RemoteStub) constructor
106: .newInstance(new Object[] { new ActivatableRef(aid,
107: null) });
108: return stub;
109:
110: } catch (Exception ex) {
111: // rmi.68=Stub {0} not found.
112: throw new StubNotFoundException(Messages.getString(
113: "rmi.68", stubName), //$NON-NLS-1$ //$NON-NLS-2$
114: ex);
115: }
116: }
117:
118: /**
119: * The getRefClass method returns "ActivatableRef" String.
120: */
121: public String getRefClass(ObjectOutput objectoutput) {
122: return "ActivatableRef"; //$NON-NLS-1$
123: }
124:
125: /**
126: * To obtain the description of the Serialization of this class see the Serialized form of
127: * java.rmi.server.RemoteObject.
128: */
129: public void writeExternal(ObjectOutput out) throws IOException {
130:
131: out.writeObject(id);
132:
133: if (ref == null) {
134: out.writeUTF(""); //$NON-NLS-1$
135: } else {
136: out.writeUTF(ref.getRefClass(out));
137: ref.writeExternal(out);
138: }
139: }
140:
141: /**
142: * To obtain the description of the Serialization of this class see the Serialized form of
143: * java.rmi.server.RemoteObject.
144: */
145: public void readExternal(ObjectInput in) throws IOException,
146: ClassNotFoundException {
147: id = (ActivationID) in.readObject();
148:
149: String s = in.readUTF();
150:
151: if (s.equals("")) { //$NON-NLS-1$
152: return;
153: }
154: Class extRefTypeClass = Class.forName(RemoteRef.packagePrefix
155: + "." + s); //$NON-NLS-1$
156:
157: try {
158: ref = (RemoteRef) extRefTypeClass.newInstance();
159: } catch (Throwable t) {
160: // rmi.73=Instantiation failed.
161: throw new ClassNotFoundException(Messages
162: .getString("rmi.73"), t); //$NON-NLS-1$
163: }
164: ref.readExternal(in);
165: }
166:
167: /**
168: * If the internal remote reference of this ActivatableRef is null, the activatable object is activated using
169: * ActivationID.activate() method. After that the remote call is delegated to the ref, by means of calling its 'invoke' method.
170: */
171: public Object invoke(Remote obj, Method method, Object[] params,
172: long opnum) throws Exception {
173: Exception signal_exception = null;
174: RemoteRef rref;
175:
176: // rmi.log.106=$$$$$$$$$ ActivatableRef.invoke:
177: rlog
178: .log(
179: RMILog.VERBOSE,
180: Messages.getString("rmi.log.106") + obj + ", " + method + ";"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
181:
182: if (ref == null) {
183: // rmi.log.107=ref == null
184: rlog.log(RMILog.VERBOSE, Messages.getString("rmi.log.107")); //$NON-NLS-1$
185:
186: RemoteStub stub = (RemoteStub) id.activate(false); //ToDo Check whether it returns Remote or RemoteStub
187: // rmi.log.3C=Stub = {0}
188: rlog.log(RMILog.VERBOSE, Messages.getString(
189: "rmi.log.3C", stub)); //$NON-NLS-1$
190:
191: ActivatableRef aref = (ActivatableRef) stub.getRef();
192: // rmi.log.108=aref = {0}
193: rlog.log(RMILog.VERBOSE, Messages.getString(
194: "rmi.log.108", aref)); //$NON-NLS-1$
195:
196: ref = aref.ref; // Global variable stored for next calls
197: rref = aref.ref; // local variable
198: } else {
199: rref = ref;
200: }
201:
202: /*
203: * If the group's VM was killed(or something bad happened to it) we may have stale activatable reference to the object.
204: * In this case rref.invoke() will throw 3 types of Exceptions: ConnectException, ConnectIOException and UnknownObjectException
205: * which should be caught and activation group should be activated again.
206: */
207: try {
208: return rref.invoke(obj, method, params, opnum);
209: } catch (ConnectException ce) {
210: } catch (ConnectIOException cioe) {
211: } catch (UnknownObjectException uoe) {
212: } catch (Exception t) {
213: signal_exception = t;
214: }
215:
216: // rmi.log.109=signal_exception = {0}
217: rlog.log(RMILog.VERBOSE, Messages.getString(
218: "rmi.log.109", signal_exception)); //$NON-NLS-1$
219:
220: if (signal_exception == null) {
221: RemoteStub stub = (RemoteStub) id.activate(true);
222: ActivatableRef aref = (ActivatableRef) stub.getRef();
223: ref = aref.ref;
224: rref = aref.ref;
225: return rref.invoke(obj, method, params, opnum);
226: } else {
227: throw signal_exception;
228: }
229: }
230:
231: /**
232: * Standard remoteEquals implementation.
233: *
234: * @param ref
235: *
236: * @return
237: */
238: public boolean remoteEquals(RemoteRef ref) {
239: if (ref instanceof ActivatableRef) {
240: ActivationID id = ((ActivatableRef) ref).id;
241: return this .id.equals(id);
242: }
243: return false;
244: }
245: }
|