1 7 package org.jboss.cache.marshall; 8 9 import org.apache.commons.logging.Log; 10 import org.apache.commons.logging.LogFactory; 11 import org.jboss.cache.Fqn; 12 import org.jboss.cache.GlobalTransaction; 13 import org.jboss.cache.Region; 14 import org.jboss.cache.RegionManager; 15 import org.jboss.cache.optimistic.DefaultDataVersion; 16 import org.jboss.cache.rpc.RpcTreeCache; 17 import org.jgroups.Address; 18 import org.jgroups.stack.IpAddress; 19 20 import java.io.IOException ; 21 import java.io.ObjectInputStream ; 22 import java.io.ObjectOutputStream ; 23 import java.io.Serializable ; 24 import java.util.ArrayList ; 25 import java.util.Collections ; 26 import java.util.HashMap ; 27 import java.util.List ; 28 import java.util.Map ; 29 import java.util.Set ; 30 31 36 public class CacheMarshaller200 extends Marshaller 37 { 38 private Log log = LogFactory.getLog(CacheMarshaller200.class); 40 41 protected static final int MAGICNUMBER_METHODCALL = 1; 43 protected static final int MAGICNUMBER_FQN = 2; 44 protected static final int MAGICNUMBER_GTX = 3; 45 protected static final int MAGICNUMBER_IPADDRESS = 4; 46 protected static final int MAGICNUMBER_LIST = 5; 47 protected static final int MAGICNUMBER_INTEGER = 6; 48 protected static final int MAGICNUMBER_LONG = 7; 49 protected static final int MAGICNUMBER_BOOLEAN = 8; 50 protected static final int MAGICNUMBER_STRING = 9; 51 protected static final int MAGICNUMBER_MAP = 10; 52 protected static final int MAGICNUMBER_DEFAULT_DATA_VERSION = 11; 53 protected static final int MAGICNUMBER_NULL = 99; 54 protected static final int MAGICNUMBER_SERIALIZABLE = 100; 55 protected static final int MAGICNUMBER_REF = 101; 56 57 protected static final InactiveRegionException IRE = new InactiveRegionException("Cannot unmarshall to an inactive region"); 58 59 public CacheMarshaller200(RegionManager manager, boolean defaultInactive, boolean useRegionBasedMarshalling) 60 { 61 init(manager, defaultInactive, useRegionBasedMarshalling); 62 if (useRegionBasedMarshalling) 63 { 64 log.debug("Using region based marshalling logic : marshalling Fqn as a String first for every call."); 65 } 66 } 67 68 70 public void objectToStream(Object o, ObjectOutputStream out) throws Exception 71 { 72 if (log.isTraceEnabled()) log.trace("Marshalling object " + o); 73 Map <Object , Integer > refMap = new HashMap <Object , Integer >(); 74 75 if (useRegionBasedMarshalling) 76 { 77 MethodCall call = (MethodCall) o; 79 String fqnAsString = extractFqnAsString(call); 80 marshallObject(fqnAsString, out, refMap); 81 } 82 83 marshallObject(o, out, refMap); 84 } 85 86 public Object objectFromStream(ObjectInputStream in) throws Exception 87 { 88 Object retValue; 89 Map <Integer , Object > refMap = new HashMap <Integer , Object >(); 90 91 if (useRegionBasedMarshalling) 92 { 93 String fqn = (String ) unmarshallObject(in, refMap); 97 Region region = null; 98 if (fqn != null) 99 { 100 region = findRegion(fqn); 101 } 102 retValue = region == null ? unmarshallObject(in, refMap) : unmarshallObject(in, region.getClassLoader(), refMap); 103 } 104 else 105 { 106 retValue = unmarshallObject(in, refMap); 107 } 108 109 return retValue; 110 } 111 112 private Region findRegion(String fqn) throws InactiveRegionException 113 { 114 Region region; 115 region = fqn == null ? null : getRegion(fqn); 117 118 if (region != null) 119 { 120 if (!region.isActive()) 121 { 122 throw IRE; 125 } 126 } 127 else if (defaultInactive) 128 { 129 throw IRE; 133 } 134 135 return region; 136 } 137 138 private String extractFqnAsString(MethodCall call) throws Exception 139 { 140 String fqnAsString; 141 if (call.getMethod().equals(MethodDeclarations.replicateMethod)) 142 { 143 fqnAsString = extractFqnFromMethodCall(call); 144 } 145 else if (call.getMethod().equals(MethodDeclarations.replicateAllMethod)) 146 { 147 fqnAsString = extractFqnFromListOfMethodCall(call); 148 } 149 else if (call.getMethod().equals(RpcTreeCache.dispatchRpcCallMethod)) 150 { 151 MethodCall call2 = (MethodCall) call.getArgs()[1]; 152 fqnAsString = extractFqn(call2); 153 } 154 else 155 { 156 fqnAsString = extractFqn(call); 157 } 158 159 return fqnAsString; 160 } 161 162 164 private void marshallObject(Object o, ObjectOutputStream out, Map <Object , Integer > refMap) throws Exception 165 { 166 if (o == null) 167 { 168 out.writeByte(MAGICNUMBER_NULL); 169 } 170 else if (refMap.containsKey(o)) { 172 out.writeByte(MAGICNUMBER_REF); 173 out.writeShort(refMap.get(o)); 174 } 175 else if (o instanceof MethodCall) 176 { 177 MethodCall call = (MethodCall) o; 179 180 if (call.getMethodId() > -1) 181 { 182 out.writeByte(MAGICNUMBER_METHODCALL); 183 marshallMethodCall(call, out, refMap); 184 } 185 else 186 { 187 throw new IllegalArgumentException ("MethodCall does not have a valid method id. Was this method call created with MethodCallFactory?"); 188 } 189 } 190 else if (o instanceof Fqn) 191 { 192 int refId = createReference(o, refMap); 193 out.writeByte(MAGICNUMBER_FQN); 194 out.writeShort(refId); 195 marshallFqn((Fqn) o, out, refMap); 196 } 197 else if (o instanceof GlobalTransaction) 198 { 199 int refId = createReference(o, refMap); 200 out.writeByte(MAGICNUMBER_GTX); 201 out.writeShort(refId); 202 marshallGlobalTransaction((GlobalTransaction) o, out, refMap); 203 } 204 else if (o instanceof IpAddress) 205 { 206 out.writeByte(MAGICNUMBER_IPADDRESS); 207 marshallIpAddress((IpAddress) o, out); 208 } 209 else if (o instanceof DefaultDataVersion) 210 { 211 out.writeByte(MAGICNUMBER_DEFAULT_DATA_VERSION); 212 out.writeLong(((DefaultDataVersion) o).getRawVersion()); 213 } 214 else if (o instanceof List ) 215 { 216 out.writeByte(MAGICNUMBER_LIST); 217 marshallList((List ) o, out, refMap); 218 } 219 else if (o instanceof Boolean ) 220 { 221 out.writeByte(MAGICNUMBER_BOOLEAN); 222 out.writeBoolean(((Boolean ) o).booleanValue()); 223 } 224 else if (o instanceof Integer ) 225 { 226 out.writeByte(MAGICNUMBER_INTEGER); 227 out.writeInt(((Integer ) o).intValue()); 228 } 229 else if (o instanceof Long ) 230 { 231 out.writeByte(MAGICNUMBER_LONG); 232 out.writeLong(((Long ) o).longValue()); 233 } 234 else if (o instanceof String ) 235 { 236 int refId = createReference(o, refMap); 237 out.writeByte(MAGICNUMBER_STRING); 238 out.writeShort(refId); 239 marshallString((String ) o, out); 240 } 241 else if (o instanceof Map ) 242 { 243 out.writeByte(MAGICNUMBER_MAP); 244 marshallMap((Map ) o, out, refMap); 245 } 246 else if (o instanceof Serializable ) 247 { 248 int refId = createReference(o, refMap); 249 if (log.isTraceEnabled()) 250 { 251 log.trace("Warning: using object serialization for " + o.getClass()); 252 } 253 out.writeByte(MAGICNUMBER_SERIALIZABLE); 254 out.writeShort(refId); 255 out.writeObject(o); 256 } 257 else 258 { 259 throw new Exception ("Don't know how to marshall object of type " + o.getClass()); 260 } 261 } 262 263 private int createReference(Object o, Map <Object , Integer > refMap) 264 { 265 int reference = refMap.size(); 266 refMap.put(o, reference); 267 return reference; 268 } 269 270 private void marshallString(String s, ObjectOutputStream out) throws Exception 271 { 272 out.writeObject(s); 274 } 275 276 private void marshallMethodCall(MethodCall methodCall, ObjectOutputStream out, Map <Object , Integer > refMap) throws Exception 277 { 278 out.writeShort(methodCall.getMethodId()); 279 Object [] args = methodCall.getArgs(); 280 byte numArgs = (byte) (args == null ? 0 : args.length); 281 out.writeByte(numArgs); 282 283 for (int i = 0; i < numArgs; i++) 284 { 285 marshallObject(args[i], out, refMap); 286 } 287 } 288 289 private void marshallGlobalTransaction(GlobalTransaction globalTransaction, ObjectOutputStream out, Map <Object , Integer > refMap) throws Exception 290 { 291 out.writeLong(globalTransaction.getId()); 292 marshallObject(globalTransaction.getAddress(), out, refMap); 293 } 294 295 296 private void marshallFqn(Fqn fqn, ObjectOutputStream out, Map <Object , Integer > refMap) throws Exception 297 { 298 boolean isRoot = fqn.isRoot(); 299 out.writeBoolean(isRoot); 300 if (!isRoot) 301 { 302 out.writeShort(fqn.size()); 303 for (int i = 0; i < fqn.size(); i++) 304 { 305 marshallObject(fqn.get(i), out, refMap); 306 } 307 } 308 } 309 310 private void marshallIpAddress(IpAddress ipAddress, ObjectOutputStream out) throws Exception 311 { 312 ipAddress.writeExternal(out); 313 } 314 315 private void marshallList(List l, ObjectOutputStream out, Map <Object , Integer > refMap) throws Exception 316 { 317 out.writeInt(l.size()); 318 for (Object o : l) 319 { 320 marshallObject(o, out, refMap); 321 } 322 } 323 324 private void marshallMap(Map map, ObjectOutputStream out, Map <Object , Integer > refMap) throws Exception 325 { 326 int mapSize = map.size(); 327 out.writeInt(mapSize); 328 if (mapSize == 0) return; 329 330 for (Map.Entry me : (Set <Map.Entry >) map.entrySet()) 331 { 332 marshallObject(me.getKey(), out, refMap); 333 marshallObject(me.getValue(), out, refMap); 334 } 335 } 336 337 339 private Object unmarshallObject(ObjectInputStream in, ClassLoader loader, Map <Integer , Object > refMap) throws Exception 340 { 341 if (loader == null) 342 { 343 return unmarshallObject(in, refMap); 344 } 345 else 346 { 347 Thread currentThread = Thread.currentThread(); 348 ClassLoader old = currentThread.getContextClassLoader(); 349 try 350 { 351 currentThread.setContextClassLoader(loader); 352 return unmarshallObject(in, refMap); 353 } 354 finally 355 { 356 currentThread.setContextClassLoader(old); 357 } 358 } 359 } 360 361 private Object unmarshallObject(ObjectInputStream in, Map <Integer , Object > refMap) throws Exception 362 { 363 byte magicNumber = in.readByte(); 364 Integer reference; 365 Object retVal; 366 switch (magicNumber) 367 { 368 case MAGICNUMBER_NULL: 369 return null; 370 case MAGICNUMBER_REF: 371 reference = (int) in.readShort(); 372 if (!refMap.containsKey(reference)) 373 { 374 throw new IOException ("Unable to locate object reference " + reference + " in byte stream!"); 375 } 376 return refMap.get(reference); 377 case MAGICNUMBER_SERIALIZABLE: 378 reference = (int) in.readShort(); 379 retVal = in.readObject(); 380 refMap.put(reference, retVal); 381 return retVal; 382 case MAGICNUMBER_METHODCALL: 383 retVal = unmarshallMethodCall(in, refMap); 384 return retVal; 385 case MAGICNUMBER_FQN: 386 reference = (int) in.readShort(); 387 retVal = unmarshallFqn(in, refMap); 388 refMap.put(reference, retVal); 389 return retVal; 390 case MAGICNUMBER_GTX: 391 reference = (int) in.readShort(); 392 retVal = unmarshallGlobalTransaction(in, refMap); 393 refMap.put(reference, retVal); 394 return retVal; 395 case MAGICNUMBER_IPADDRESS: 396 retVal = unmarshallIpAddress(in); 397 return retVal; 398 case MAGICNUMBER_DEFAULT_DATA_VERSION: 399 retVal = new DefaultDataVersion(in.readLong()); 400 return retVal; 401 case MAGICNUMBER_LIST: 402 return unmarshallList(in, refMap); 403 case MAGICNUMBER_BOOLEAN: 404 return in.readBoolean() ? Boolean.TRUE : Boolean.FALSE; 405 case MAGICNUMBER_INTEGER: 406 return in.readInt(); 407 case MAGICNUMBER_LONG: 408 retVal = in.readLong(); 409 return retVal; 410 case MAGICNUMBER_STRING: 411 reference = (int) in.readShort(); 412 retVal = unmarshallString(in); 413 refMap.put(reference, retVal); 414 return retVal; 415 case MAGICNUMBER_MAP: 416 return unmarshallMap(in, refMap); 417 default: 418 if (log.isErrorEnabled()) 419 { 420 log.error("Unknown Magic Number " + magicNumber); 421 } 422 throw new Exception ("Unknown magic number " + magicNumber); 423 } 424 } 425 426 private String unmarshallString(ObjectInputStream in) throws Exception 427 { 428 return (String ) in.readObject(); 430 } 431 432 private MethodCall unmarshallMethodCall(ObjectInputStream in, Map <Integer , Object > refMap) throws Exception 433 { 434 short methodId = in.readShort(); 435 byte numArgs = in.readByte(); 436 Object [] args = null; 437 438 if (numArgs > 0) 439 { 440 args = new Object [numArgs]; 441 442 for (int i = 0; i < numArgs; i++) 443 { 444 args[i] = unmarshallObject(in, refMap); 445 } 446 } 447 return MethodCallFactory.create(MethodDeclarations.lookupMethod(methodId), args); 448 } 449 450 private GlobalTransaction unmarshallGlobalTransaction(ObjectInputStream in, Map <Integer , Object > refMap) throws Exception 451 { 452 GlobalTransaction gtx = new GlobalTransaction(); 453 long id = in.readLong(); 454 Object address = unmarshallObject(in, refMap); 455 gtx.setId(id); 456 gtx.setAddress((Address) address); 457 return gtx; 458 } 459 460 private Fqn unmarshallFqn(ObjectInputStream in, Map <Integer , Object > refMap) throws Exception 461 { 462 463 boolean isRoot = in.readBoolean(); 464 Fqn fqn; 465 if (!isRoot) 466 { 467 int numElements = in.readShort(); 468 List <Object > elements = new ArrayList <Object >(numElements); 469 for (int i = 0; i < numElements; i++) 470 { 471 elements.add(unmarshallObject(in, refMap)); 472 } 473 fqn = new Fqn(elements); 474 } 475 else 476 { 477 fqn = Fqn.ROOT; 478 } 479 return fqn; 480 } 481 482 private IpAddress unmarshallIpAddress(ObjectInputStream in) throws Exception 483 { 484 IpAddress ipAddress = new IpAddress(); 485 ipAddress.readExternal(in); 486 return ipAddress; 487 } 488 489 private List unmarshallList(ObjectInputStream in, Map <Integer , Object > refMap) throws Exception 490 { 491 int listSize = in.readInt(); 492 List <Object > list = new ArrayList <Object >(listSize); 493 for (int i = 0; i < listSize; i++) 494 { 495 list.add(unmarshallObject(in, refMap)); 496 } 497 return list; 498 } 499 500 private Map unmarshallMap(ObjectInputStream in, Map <Integer , Object > refMap) throws Exception 501 { 502 int mapSize = in.readInt(); 503 if (mapSize == 0) return Collections.emptyMap(); 504 Map <Object , Object > map = new HashMap <Object , Object >(mapSize); 505 for (int i = 0; i < mapSize; i++) 506 { 507 map.put(unmarshallObject(in, refMap), unmarshallObject(in, refMap)); 508 } 509 return map; 510 } 511 512 513 } 514 | Popular Tags |