KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > cache > marshall > CacheMarshaller200


1 /*
2  * JBoss, Home of Professional Open Source
3  *
4  * Distributable under LGPL license.
5  * See terms of license at gnu.org.
6  */

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 JavaDoc;
21 import java.io.ObjectInputStream JavaDoc;
22 import java.io.ObjectOutputStream JavaDoc;
23 import java.io.Serializable JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.Collections JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.Map JavaDoc;
29 import java.util.Set JavaDoc;
30
31 /**
32  * An enhanced marshaller for RPC calls between CacheImpl instances.
33  *
34  * @author <a HREF="mailto:manik@jboss.org">Manik Surtani (manik@jboss.org)</a>
35  */

36 public class CacheMarshaller200 extends Marshaller
37 {
38    // logger
39
private Log log = LogFactory.getLog(CacheMarshaller200.class);
40
41    // magic numbers
42
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    // -------- Marshaller interface
69

70    public void objectToStream(Object JavaDoc o, ObjectOutputStream JavaDoc out) throws Exception JavaDoc
71    {
72       if (log.isTraceEnabled()) log.trace("Marshalling object " + o);
73       Map JavaDoc<Object JavaDoc, Integer JavaDoc> refMap = new HashMap JavaDoc<Object JavaDoc, Integer JavaDoc>();
74
75       if (useRegionBasedMarshalling)
76       {
77          // we first marshall the Fqn as a String (ugh!)
78
MethodCall call = (MethodCall) o;
79          String JavaDoc fqnAsString = extractFqnAsString(call);
80          marshallObject(fqnAsString, out, refMap);
81       }
82
83       marshallObject(o, out, refMap);
84    }
85
86    public Object JavaDoc objectFromStream(ObjectInputStream JavaDoc in) throws Exception JavaDoc
87    {
88       Object JavaDoc retValue;
89       Map JavaDoc<Integer JavaDoc, Object JavaDoc> refMap = new HashMap JavaDoc<Integer JavaDoc, Object JavaDoc>();
90
91       if (useRegionBasedMarshalling)
92       {
93          // first unmarshall the fqn as a String
94
// This may be null if the call being unmarshalled is
95
// not region-based
96
String JavaDoc fqn = (String JavaDoc) 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 JavaDoc fqn) throws InactiveRegionException
113    {
114       Region region;
115       // obtain a region from MarshRegionManager, if not, will use default.
116
region = fqn == null ? null : getRegion(fqn);
117
118       if (region != null)
119       {
120          if (!region.isActive())
121          {
122             // throw new InactiveRegionException("Cannot unmarshall message for region " + fqn
123
// + ". This region is inactive.");
124
throw IRE;
125          }
126       }
127       else if (defaultInactive)
128       {
129          // No region but default inactive means region is inactive
130
// throw new InactiveRegionException("Cannot unmarshall message for region " + fqn + ". By default region " + fqn
131
// + " is inactive.");
132
throw IRE;
133       }
134
135       return region;
136    }
137
138    private String JavaDoc extractFqnAsString(MethodCall call) throws Exception JavaDoc
139    {
140       String JavaDoc 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    // --------- Marshalling methods
163

164    private void marshallObject(Object JavaDoc o, ObjectOutputStream JavaDoc out, Map JavaDoc<Object JavaDoc, Integer JavaDoc> refMap) throws Exception JavaDoc
165    {
166       if (o == null)
167       {
168          out.writeByte(MAGICNUMBER_NULL);
169       }
170       else if (refMap.containsKey(o))// see if this object has been marshalled before.
171
{
172          out.writeByte(MAGICNUMBER_REF);
173          out.writeShort(refMap.get(o));
174       }
175       else if (o instanceof MethodCall)
176       {
177          // first see if this is a 'known' method call.
178
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 JavaDoc("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 JavaDoc)
215       {
216          out.writeByte(MAGICNUMBER_LIST);
217          marshallList((List JavaDoc) o, out, refMap);
218       }
219       else if (o instanceof Boolean JavaDoc)
220       {
221          out.writeByte(MAGICNUMBER_BOOLEAN);
222          out.writeBoolean(((Boolean JavaDoc) o).booleanValue());
223       }
224       else if (o instanceof Integer JavaDoc)
225       {
226          out.writeByte(MAGICNUMBER_INTEGER);
227          out.writeInt(((Integer JavaDoc) o).intValue());
228       }
229       else if (o instanceof Long JavaDoc)
230       {
231          out.writeByte(MAGICNUMBER_LONG);
232          out.writeLong(((Long JavaDoc) o).longValue());
233       }
234       else if (o instanceof String JavaDoc)
235       {
236          int refId = createReference(o, refMap);
237          out.writeByte(MAGICNUMBER_STRING);
238          out.writeShort(refId);
239          marshallString((String JavaDoc) o, out);
240       }
241       else if (o instanceof Map JavaDoc)
242       {
243          out.writeByte(MAGICNUMBER_MAP);
244          marshallMap((Map JavaDoc) o, out, refMap);
245       }
246       else if (o instanceof Serializable JavaDoc)
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 JavaDoc("Don't know how to marshall object of type " + o.getClass());
260       }
261    }
262
263    private int createReference(Object JavaDoc o, Map JavaDoc<Object JavaDoc, Integer JavaDoc> refMap)
264    {
265       int reference = refMap.size();
266       refMap.put(o, reference);
267       return reference;
268    }
269
270    private void marshallString(String JavaDoc s, ObjectOutputStream JavaDoc out) throws Exception JavaDoc
271    {
272       //StringUtil.saveString(out, s);
273
out.writeObject(s);
274    }
275
276    private void marshallMethodCall(MethodCall methodCall, ObjectOutputStream JavaDoc out, Map JavaDoc<Object JavaDoc, Integer JavaDoc> refMap) throws Exception JavaDoc
277    {
278       out.writeShort(methodCall.getMethodId());
279       Object JavaDoc[] 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 JavaDoc out, Map JavaDoc<Object JavaDoc, Integer JavaDoc> refMap) throws Exception JavaDoc
290    {
291       out.writeLong(globalTransaction.getId());
292       marshallObject(globalTransaction.getAddress(), out, refMap);
293    }
294
295
296    private void marshallFqn(Fqn fqn, ObjectOutputStream JavaDoc out, Map JavaDoc<Object JavaDoc, Integer JavaDoc> refMap) throws Exception JavaDoc
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 JavaDoc out) throws Exception JavaDoc
311    {
312       ipAddress.writeExternal(out);
313    }
314
315    private void marshallList(List JavaDoc l, ObjectOutputStream JavaDoc out, Map JavaDoc<Object JavaDoc, Integer JavaDoc> refMap) throws Exception JavaDoc
316    {
317       out.writeInt(l.size());
318       for (Object JavaDoc o : l)
319       {
320          marshallObject(o, out, refMap);
321       }
322    }
323
324    private void marshallMap(Map JavaDoc map, ObjectOutputStream JavaDoc out, Map JavaDoc<Object JavaDoc, Integer JavaDoc> refMap) throws Exception JavaDoc
325    {
326       int mapSize = map.size();
327       out.writeInt(mapSize);
328       if (mapSize == 0) return;
329
330       for (Map.Entry JavaDoc me : (Set JavaDoc<Map.Entry JavaDoc>) map.entrySet())
331       {
332          marshallObject(me.getKey(), out, refMap);
333          marshallObject(me.getValue(), out, refMap);
334       }
335    }
336
337    // --------- Unmarshalling methods
338

339    private Object JavaDoc unmarshallObject(ObjectInputStream JavaDoc in, ClassLoader JavaDoc loader, Map JavaDoc<Integer JavaDoc, Object JavaDoc> refMap) throws Exception JavaDoc
340    {
341       if (loader == null)
342       {
343          return unmarshallObject(in, refMap);
344       }
345       else
346       {
347          Thread JavaDoc currentThread = Thread.currentThread();
348          ClassLoader JavaDoc 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 JavaDoc unmarshallObject(ObjectInputStream JavaDoc in, Map JavaDoc<Integer JavaDoc, Object JavaDoc> refMap) throws Exception JavaDoc
362    {
363       byte magicNumber = in.readByte();
364       Integer JavaDoc reference;
365       Object JavaDoc 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 JavaDoc("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 JavaDoc("Unknown magic number " + magicNumber);
423       }
424    }
425
426    private String JavaDoc unmarshallString(ObjectInputStream JavaDoc in) throws Exception JavaDoc
427    {
428       //return StringUtil.readString(in, null);
429
return (String JavaDoc) in.readObject();
430    }
431
432    private MethodCall unmarshallMethodCall(ObjectInputStream JavaDoc in, Map JavaDoc<Integer JavaDoc, Object JavaDoc> refMap) throws Exception JavaDoc
433    {
434       short methodId = in.readShort();
435       byte numArgs = in.readByte();
436       Object JavaDoc[] args = null;
437
438       if (numArgs > 0)
439       {
440          args = new Object JavaDoc[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 JavaDoc in, Map JavaDoc<Integer JavaDoc, Object JavaDoc> refMap) throws Exception JavaDoc
451    {
452       GlobalTransaction gtx = new GlobalTransaction();
453       long id = in.readLong();
454       Object JavaDoc address = unmarshallObject(in, refMap);
455       gtx.setId(id);
456       gtx.setAddress((Address) address);
457       return gtx;
458    }
459
460    private Fqn unmarshallFqn(ObjectInputStream JavaDoc in, Map JavaDoc<Integer JavaDoc, Object JavaDoc> refMap) throws Exception JavaDoc
461    {
462
463       boolean isRoot = in.readBoolean();
464       Fqn fqn;
465       if (!isRoot)
466       {
467          int numElements = in.readShort();
468          List JavaDoc<Object JavaDoc> elements = new ArrayList JavaDoc<Object JavaDoc>(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 JavaDoc in) throws Exception JavaDoc
483    {
484       IpAddress ipAddress = new IpAddress();
485       ipAddress.readExternal(in);
486       return ipAddress;
487    }
488
489    private List JavaDoc unmarshallList(ObjectInputStream JavaDoc in, Map JavaDoc<Integer JavaDoc, Object JavaDoc> refMap) throws Exception JavaDoc
490    {
491       int listSize = in.readInt();
492       List JavaDoc<Object JavaDoc> list = new ArrayList JavaDoc<Object JavaDoc>(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 JavaDoc unmarshallMap(ObjectInputStream JavaDoc in, Map JavaDoc<Integer JavaDoc, Object JavaDoc> refMap) throws Exception JavaDoc
501    {
502       int mapSize = in.readInt();
503       if (mapSize == 0) return Collections.emptyMap();
504       Map JavaDoc<Object JavaDoc, Object JavaDoc> map = new HashMap JavaDoc<Object JavaDoc, Object JavaDoc>(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