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