001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.object.applicator;
006:
007: import com.tc.object.ClientObjectManager;
008: import com.tc.object.ObjectID;
009: import com.tc.object.TCObject;
010: import com.tc.object.TraversedReferences;
011: import com.tc.object.bytecode.ManagerUtil;
012: import com.tc.object.bytecode.hook.impl.ArrayManager;
013: import com.tc.object.dna.api.DNA;
014: import com.tc.object.dna.api.DNACursor;
015: import com.tc.object.dna.api.DNAWriter;
016: import com.tc.object.dna.api.DNAEncoding;
017: import com.tc.object.dna.api.PhysicalAction;
018: import com.tc.object.tx.optimistic.OptimisticTransactionManager;
019: import com.tc.object.tx.optimistic.TCObjectClone;
020: import com.tc.util.Assert;
021: import com.tc.util.ClassUtils;
022:
023: import java.io.IOException;
024: import java.lang.reflect.Array;
025: import java.util.Collections;
026: import java.util.IdentityHashMap;
027: import java.util.Map;
028:
029: public class ArrayApplicator extends BaseApplicator {
030:
031: public ArrayApplicator(DNAEncoding encoding) {
032: super (encoding);
033: }
034:
035: public TraversedReferences getPortableObjects(Object pojo,
036: TraversedReferences addTo) {
037: if (ClassUtils.isPrimitiveArray(pojo)) {
038: return addTo;
039: }
040:
041: Object[] array = (Object[]) pojo;
042:
043: for (int i = 0, len = array.length; i < len; i++) {
044: Object o = array[i];
045: if (o != null && isPortableReference(o.getClass())) {
046: addTo.addAnonymousReference(o);
047: }
048: }
049: return addTo;
050: }
051:
052: public void hydrate(ClientObjectManager objectManager,
053: TCObject tcObject, DNA dna, Object po) throws IOException,
054: IllegalArgumentException, ClassNotFoundException {
055: DNACursor cursor = dna.getCursor();
056:
057: while (cursor.next(encoding)) {
058: PhysicalAction a = cursor.getPhysicalAction();
059:
060: if (a.isArrayElement()) {
061: setArrayElement(a.getArrayIndex(), a.getObject(),
062: tcObject, po);
063: } else if (a.isEntireArray() || a.isSubArray()) {
064: Object array = a.getObject();
065: int offset = a.isEntireArray() ? 0 : a.getArrayIndex();
066:
067: if (ClassUtils.isPrimitiveArray(array)) {
068: System.arraycopy(array, 0, po, offset, Array
069: .getLength(array));
070: } else {
071: hydrateNonPrimitiveArray((Object[]) array,
072: tcObject, po, offset);
073: }
074: } else {
075: throw Assert
076: .failure("Invalid physical action for array");
077: }
078: }
079: }
080:
081: private static void hydrateNonPrimitiveArray(Object[] source,
082: TCObject tcObject, Object pojo, int offset) {
083: for (int i = 0, n = source.length; i < n; i++) {
084: setArrayElement(offset + i, source[i], tcObject, pojo);
085: }
086: }
087:
088: private static void setArrayElement(int index, Object value,
089: TCObject tcObject, Object pojo) {
090: String fieldName = String.valueOf(index);
091: if (value instanceof ObjectID) {
092: tcObject.setArrayReference(index, (ObjectID) value);
093: } else {
094: tcObject.clearReference(fieldName);
095: // if you're trying to get rid of reflection here, you need to make sure you deal properly with
096: // Wrapper objects (like Integer, Long, etc)
097: Array.set(pojo, index, value);
098: }
099: }
100:
101: public void dehydrate(ClientObjectManager objectManager,
102: TCObject tcObject, DNAWriter writer, Object pojo) {
103: writer.setArrayLength(Array.getLength(pojo));
104:
105: if (ClassUtils.isPrimitiveArray(pojo)) {
106: writer.addEntireArray(pojo);
107: } else {
108: Object[] array = (Object[]) pojo;
109: Object[] toEncode = new Object[array.length];
110:
111: // convert to array of literals and ObjectID
112: for (int i = 0, n = array.length; i < n; i++) {
113: Object element = array[i];
114: if (!objectManager.isPortableInstance(element)) {
115: toEncode[i] = ObjectID.NULL_ID;
116: continue;
117: }
118:
119: final Object obj = getDehydratableObject(element,
120: objectManager);
121: if (obj == null) {
122: toEncode[i] = ObjectID.NULL_ID;
123: } else {
124: toEncode[i] = obj;
125: }
126: }
127:
128: writer.addEntireArray(toEncode);
129: }
130: }
131:
132: public Object getNewInstance(ClientObjectManager objectManager,
133: DNA dna) {
134: throw new UnsupportedOperationException();
135: }
136:
137: public Map connectedCopy(Object source, Object dest, Map visited,
138: ClientObjectManager objectManager,
139: OptimisticTransactionManager txManager) {
140: if (source.getClass().getComponentType().isPrimitive()) {
141: System.arraycopy(source, 0, dest, 0, Array.getLength(dest));
142: return Collections.EMPTY_MAP;
143: }
144:
145: Map cloned = new IdentityHashMap();
146:
147: Object[] da = (Object[]) dest;
148: Object[] sa = (Object[]) source;
149: int len = da.length;
150: for (int i = 0; i < len; i++) {
151: Object v = sa[i];
152: da[i] = createCopyIfNecessary(objectManager, visited,
153: cloned, v);
154: }
155:
156: // HAck hack big hack
157: ManagerUtil.register(dest, new TCObjectClone(ArrayManager
158: .getCloneObject(source), txManager, len));
159: return cloned;
160: }
161: }
|