001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tc.object.applicator;
005:
006: import com.tc.object.ClientObjectManager;
007: import com.tc.object.ObjectID;
008: import com.tc.object.TCObject;
009: import com.tc.object.TraversedReferences;
010: import com.tc.object.bytecode.Manageable;
011: import com.tc.object.bytecode.TransparentAccess;
012: import com.tc.object.dna.api.DNA;
013: import com.tc.object.dna.api.DNACursor;
014: import com.tc.object.dna.api.DNAWriter;
015: import com.tc.object.dna.api.DNAEncoding;
016: import com.tc.object.dna.api.PhysicalAction;
017: import com.tc.object.tx.optimistic.OptimisticTransactionManager;
018: import com.tc.object.tx.optimistic.TCObjectClone;
019: import com.tc.util.Assert;
020:
021: import java.io.IOException;
022: import java.lang.reflect.InvocationHandler;
023: import java.lang.reflect.Proxy;
024: import java.util.IdentityHashMap;
025: import java.util.Map;
026:
027: public class ProxyApplicator extends BaseApplicator {
028: private static final String CLASSLOADER_FIELD_NAME = "java.lang.reflect.Proxy.loader";
029: private static final String INTERFACES_FIELD_NAME = "java.lang.reflect.Proxy.interfaces";
030: private static final String INVOCATION_HANDLER_FIELD_NAME = "java.lang.reflect.Proxy.h";
031:
032: public ProxyApplicator(DNAEncoding encoding) {
033: super (encoding);
034: }
035:
036: public TraversedReferences getPortableObjects(Object pojo,
037: TraversedReferences addTo) {
038: addTo.addAnonymousReference(Proxy.getInvocationHandler(pojo));
039: return addTo;
040: }
041:
042: public void hydrate(ClientObjectManager objectManager,
043: TCObject tcObject, DNA dna, Object po) throws IOException,
044: IllegalArgumentException, ClassNotFoundException {
045: // Most of the time, hydrate() of ProxyApplicator will not be needed as we create
046: // instance of a Proxy instance using the getNewInstance() method. This is being
047: // called only when someone is modifying the invocation handler field of a proxy using
048: // reflection.
049: DNACursor cursor = dna.getCursor();
050: String fieldName;
051: Object fieldValue;
052:
053: while (cursor.next(encoding)) {
054: PhysicalAction a = cursor.getPhysicalAction();
055: Assert.eval(a.isTruePhysical());
056: fieldName = a.getFieldName();
057: fieldValue = a.getObject();
058:
059: if (fieldName.equals(INVOCATION_HANDLER_FIELD_NAME)) {
060: fieldValue = objectManager
061: .lookupObject((ObjectID) fieldValue);
062: ((TransparentAccess) po).__tc_setfield(fieldName,
063: fieldValue);
064: }
065: }
066: }
067:
068: public void dehydrate(ClientObjectManager objectManager,
069: TCObject tcObject, DNAWriter writer, Object pojo) {
070: InvocationHandler handler = Proxy.getInvocationHandler(pojo);
071: Object dehydratableHandler = getDehydratableObject(handler,
072: objectManager);
073:
074: //writer.addPhysicalAction(CLASSLOADER_FIELD_NAME, pojo.getClass().getClassLoader());
075: writer.addClassLoaderAction(CLASSLOADER_FIELD_NAME, pojo
076: .getClass().getClassLoader());
077: writer.addPhysicalAction(INTERFACES_FIELD_NAME, pojo.getClass()
078: .getInterfaces());
079: writer.addPhysicalAction(INVOCATION_HANDLER_FIELD_NAME,
080: dehydratableHandler);
081: }
082:
083: public Object getNewInstance(ClientObjectManager objectManager,
084: DNA dna) throws IOException, ClassNotFoundException {
085: DNACursor cursor = dna.getCursor();
086: Assert.assertEquals(3, cursor.getActionCount());
087:
088: cursor.next(encoding);
089: PhysicalAction a = cursor.getPhysicalAction();
090: ClassLoader loader = (ClassLoader) a.getObject();
091:
092: cursor.next(encoding);
093: a = cursor.getPhysicalAction();
094: Object[] values = (Object[]) a.getObject();
095: Class[] interfaces = new Class[values.length];
096: System.arraycopy(values, 0, interfaces, 0, values.length);
097:
098: cursor.next(encoding);
099: a = cursor.getPhysicalAction();
100: Object handler = a.getObject();
101:
102: handler = objectManager.lookupObject((ObjectID) handler);
103:
104: return Proxy.newProxyInstance(loader, interfaces,
105: (InvocationHandler) handler);
106: }
107:
108: public Map connectedCopy(Object source, Object dest, Map visited,
109: ClientObjectManager objectManager,
110: OptimisticTransactionManager txManager) {
111: Map cloned = new IdentityHashMap();
112:
113: Proxy srcProxy = (Proxy) source;
114: Proxy destProxy = (Proxy) dest;
115:
116: InvocationHandler handler = Proxy
117: .getInvocationHandler(srcProxy);
118: InvocationHandler clonedHandler = (InvocationHandler) createCopyIfNecessary(
119: objectManager, visited, cloned, handler);
120:
121: ((TransparentAccess) destProxy).__tc_setfield(
122: INVOCATION_HANDLER_FIELD_NAME, clonedHandler);
123:
124: TCObject srcTCObject = ((Manageable) srcProxy).__tc_managed();
125: ((Manageable) destProxy).__tc_managed(new TCObjectClone(
126: srcTCObject, txManager));
127:
128: return cloned;
129: }
130: }
|