1 /*
2 * Copyright (c) 1998-2003 The Jgroup Team.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16 *
17 */
18 package jgroup.relacs.gmi;
19
20 import java.io.Externalizable;
21 import java.io.IOException;
22 import java.io.ObjectInput;
23 import java.io.ObjectOutput;
24 import java.lang.reflect.InvocationTargetException;
25 import java.lang.reflect.Method;
26 import java.rmi.RemoteException;
27
28 import org.apache.log4j.Logger;
29
30 import jgroup.core.View;
31
32 /**
33 * Encapsulates invocation results and the server-side view identifier
34 * at the time of result generation.
35 *
36 * @author Tor Arve Stangeland
37 * @author Hein Meling
38 */
39 public final class InvocationResult
40 implements Externalizable
41 {
42
43 ////////////////////////////////////////////////////////////////////////////////////////////
44 // Logger
45 ////////////////////////////////////////////////////////////////////////////////////////////
46
47 /** Obtain logger for this class */
48 private static final Logger log = Logger.getLogger(InvocationResult.class);
49
50
51 ////////////////////////////////////////////////////////////////////////////////////////////
52 // Constants
53 ////////////////////////////////////////////////////////////////////////////////////////////
54
55 private static final long serialVersionUID = -416389148892987660L;
56
57
58 ////////////////////////////////////////////////////////////////////////////////////////////
59 // RequestHandler return codes
60 ////////////////////////////////////////////////////////////////////////////////////////////
61
62 /** Indicates that the invocation completed, and a result will follow. */
63 public static final int INVOCATION_COMPLETED = 0x00;
64
65 /** Indicates that the invocation completed, and a result will follow. */
66 public static final int INVOCATION_BLOCKED = 0x01;
67
68 /** Indicates that the invocation failed with the attached exception. */
69 public static final int INVOCATION_FAILED = 0x02;
70
71 /**
72 * Indicates that the invocation could not be performed since it
73 * had an unknown invocation semantics for the given request.
74 */
75 public static final int UNKNOWN_INVOCATION_SEMANTICS = 0x03;
76
77
78 ////////////////////////////////////////////////////////////////////////////////////////////
79 // Fields
80 ////////////////////////////////////////////////////////////////////////////////////////////
81
82 /** The result of the invocation; it may be an exception. */
83 private Object result;
84
85 /** Indicates if the results contains an exception. */
86 private boolean isException = false;
87
88 /**
89 * The server-side view identifier of the group being invoked
90 * (always transmitted)
91 */
92 private long serverViewId;
93
94 /**
95 * The server-side view of the group being invoked
96 * (only transmitted when a change has been detected).
97 */
98 private View serverView = null;
99
100
101 ////////////////////////////////////////////////////////////////////////////////////////////
102 // Constructors
103 ////////////////////////////////////////////////////////////////////////////////////////////
104
105 /**
106 * Empty constructor for externalizable
107 */
108 public InvocationResult() {}
109
110 /**
111 * Invokes method <code>m</code> on object <code>o</code> with the
112 * provided arguments. The method may return a result which is stored
113 * in the <code>result</code> field of this object, or it may return an
114 * exception. The latter is also stored in the <code>result</code>
115 * field, but in addition the boolean field <code>isException</code> is
116 * set to true.
117 *
118 * @param m Method to invoke
119 * @param args Arguments to method <code>m</code>
120 * @param o Object to invoke method on
121 * @param serverView The server-side view in which the method was invoked
122 * @param clientViewId The client-side view in which this method was invoked
123 */
124 public InvocationResult(Method m, Object[] args, Object o,
125 View serverView, long clientViewId)
126 throws IllegalArgumentException, IllegalAccessException
127 {
128 this.serverViewId = serverView.getVid();
129 this.serverView = (clientViewId != serverViewId) ? serverView : null;
130 try {
131 result = m.invoke(o, args);
132 } catch (InvocationTargetException itex) {
133 // The method threw an exception
134 isException = true;
135 result = itex.getCause();
136 log.error("Invocation threw an exception", itex.getCause());
137 }
138 }
139
140 public InvocationResult(RemoteException e)
141 {
142 isException = true;
143 result = e;
144 log.error("Invocation returned with a remote exception", e);
145 }
146
147
148 ////////////////////////////////////////////////////////////////////////////////////////////
149 // Client-side access methods (GroupInvocationHandler)
150 ////////////////////////////////////////////////////////////////////////////////////////////
151
152 /**
153 * Returns the result of the invocation.
154 * If the invoked object threw an exception this exception is thrown.
155 */
156 Object getResult()
157 throws Exception
158 {
159 if (isException)
160 throw (Exception) result;
161 return result;
162 }
163
164 /**
165 * Returns the server-side view identifier attached with this
166 * <code>InvocationResult</code> message.
167 */
168 long getServerViewId()
169 {
170 return serverViewId;
171 }
172
173 /**
174 * Returns the server-side view attached with this
175 * <code>InvocationResult</code> message.
176 */
177 View getServerView()
178 {
179 return serverView;
180 }
181
182
183 ////////////////////////////////////////////////////////////////////////////////////////////
184 // Methods from Externalizable
185 ////////////////////////////////////////////////////////////////////////////////////////////
186
187 /* (non-javadoc)
188 * @see java.io.Externalizable#readExternal(ObjectInput)
189 */
190 public void readExternal(ObjectInput in)
191 throws IOException, ClassNotFoundException
192 {
193 result = in.readObject();
194 isException = in.readBoolean();
195 serverViewId = in.readLong();
196 boolean containsView = in.readBoolean();
197 if (containsView)
198 serverView = (View) in.readObject();
199 }
200
201 /* (non-javadoc)
202 * @see java.io.Externalizable#writeExternal(ObjectOutput)
203 */
204 public void writeExternal(ObjectOutput out)
205 throws IOException
206 {
207 out.writeObject(result);
208 out.writeBoolean(isException);
209 out.writeLong(serverViewId);
210 out.writeBoolean(serverView != null);
211 if (serverView != null)
212 out.writeObject(serverView);
213 }
214
215
216 ////////////////////////////////////////////////////////////////////////////////////////////
217 // Methods from Object
218 ////////////////////////////////////////////////////////////////////////////////////////////
219
220 public String toString()
221 {
222 StringBuilder buf = new StringBuilder("InvocationResult[");
223 if (isException)
224 buf.append("Result is an exception, ");
225 buf.append("serverViewId=");
226 buf.append(serverViewId);
227 buf.append(", result=");
228 buf.append(result == null ? "null" : result.toString());
229 buf.append("]");
230 return buf.toString();
231 }
232
233 } // END InvocationResult