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;
006:
007: import com.tc.aspectwerkz.reflect.ClassInfo;
008: import com.tc.aspectwerkz.reflect.impl.java.JavaClassInfo;
009: import com.tc.exception.TCRuntimeException;
010: import com.tc.object.applicator.AccessibleObjectApplicator;
011: import com.tc.object.applicator.ArrayApplicator;
012: import com.tc.object.applicator.ChangeApplicator;
013: import com.tc.object.applicator.FileApplicator;
014: import com.tc.object.applicator.LiteralTypesApplicator;
015: import com.tc.object.applicator.PhysicalApplicator;
016: import com.tc.object.applicator.ProxyApplicator;
017: import com.tc.object.config.DSOClientConfigHelper;
018: import com.tc.object.config.TransparencyClassSpec;
019: import com.tc.object.dna.api.DNAEncoding;
020: import com.tc.object.dna.impl.DNAEncodingImpl;
021: import com.tc.object.field.TCFieldFactory;
022: import com.tc.object.loaders.ClassProvider;
023: import com.tc.util.ClassUtils;
024:
025: import java.lang.reflect.Constructor;
026: import java.util.HashMap;
027: import java.util.Map;
028:
029: /**
030: * @author steve
031: */
032: public class TCClassFactoryImpl implements TCClassFactory {
033: private static final LiteralValues literalValues = new LiteralValues();
034: private static Class[] APPLICATOR_CSTR_SIGNATURE = new Class[] { DNAEncoding.class };
035:
036: private final Map classes = new HashMap();
037: private final TCFieldFactory fieldFactory;
038: private final DSOClientConfigHelper config;
039: private final ClassProvider classProvider;
040: private final DNAEncoding encoding;
041:
042: public TCClassFactoryImpl(TCFieldFactory fieldFactory,
043: DSOClientConfigHelper config, ClassProvider classProvider) {
044: this .fieldFactory = fieldFactory;
045: this .config = config;
046: this .classProvider = classProvider;
047: this .encoding = new DNAEncodingImpl(classProvider);
048: }
049:
050: public TCClass getOrCreate(Class clazz,
051: ClientObjectManager objectManager) {
052: synchronized (classes) {
053: TCClass rv = (TCClass) classes.get(clazz);
054: if (rv == null) {
055: String loaderDesc = classProvider
056: .getLoaderDescriptionFor(clazz);
057: String className = clazz.getName();
058: ClassInfo classInfo = JavaClassInfo.getClassInfo(clazz);
059: rv = new TCClassImpl(
060: fieldFactory,
061: this ,
062: objectManager,
063: config.getTCPeerClass(clazz),
064: getLogicalSuperClassWithDefaultConstructor(clazz), //
065: loaderDesc,
066: config.getLogicalExtendingClassName(className),
067: config.isLogical(className), config
068: .isCallConstructorOnLoad(classInfo),
069: config.getOnLoadScriptIfDefined(classInfo),
070: config.getOnLoadMethodIfDefined(classInfo),
071: config.isUseNonDefaultConstructor(clazz));
072: classes.put(clazz, rv);
073: }
074: return rv;
075: }
076: }
077:
078: public Class getLogicalSuperClassWithDefaultConstructor(Class clazz) {
079: TransparencyClassSpec spec = config.getSpec(clazz.getName());
080: if (spec == null) {
081: return null;
082: }
083:
084: while (clazz != null) {
085: if (spec == null) {
086: return null;
087: }
088: if (spec.isLogical()) {
089: Constructor c = null;
090: try {
091: c = clazz.getDeclaredConstructor(new Class[0]);
092: } catch (SecurityException e) {
093: throw new TCRuntimeException(e);
094: } catch (NoSuchMethodException e) {
095: c = null;
096: }
097: if (c != null) {
098: return clazz;
099: }
100: }
101: clazz = clazz.getSuperclass();
102: if (clazz != null) {
103: spec = config.getSpec(clazz.getName());
104: } else {
105: spec = null;
106: }
107: }
108: return null;
109: }
110:
111: public ChangeApplicator createApplicatorFor(TCClass clazz,
112: boolean indexed) {
113: if (indexed) {
114: return new ArrayApplicator(encoding);
115: }
116: String name = clazz.getName();
117: Class applicatorClazz = config.getChangeApplicator(clazz
118: .getPeerClass());
119:
120: if (applicatorClazz == null) {
121: if (literalValues.isLiteral(name)) {
122: return new LiteralTypesApplicator(clazz, encoding);
123: } else if (clazz.isProxyClass()) {
124: return new ProxyApplicator(encoding);
125: } else if (ClassUtils.isPortableReflectionClass(clazz
126: .getPeerClass())) {
127: return new AccessibleObjectApplicator(encoding);
128: } else if ("java.io.File".equals(name)) {
129: return new FileApplicator(clazz, encoding);
130: } else if ("java.util.concurrent.atomic.AtomicInteger"
131: .equals(name)) {
132: try {
133: Class klass = Class
134: .forName("com.tc.object.applicator.AtomicIntegerApplicator");
135: Constructor constructor = klass
136: .getDeclaredConstructor(APPLICATOR_CSTR_SIGNATURE);
137: return (ChangeApplicator) constructor
138: .newInstance(new Object[] { encoding });
139: } catch (Exception e) {
140: throw new AssertionError(e);
141: }
142: } else if ("java.util.concurrent.atomic.AtomicLong"
143: .equals(name)) {
144: try {
145: Class klass = Class
146: .forName("com.tc.object.applicator.AtomicLongApplicator");
147: Constructor constructor = klass
148: .getDeclaredConstructor(APPLICATOR_CSTR_SIGNATURE);
149: return (ChangeApplicator) constructor
150: .newInstance(new Object[] { encoding });
151: } catch (Exception e) {
152: throw new AssertionError(e);
153: }
154: } else {
155: return new PhysicalApplicator(clazz, encoding);
156: }
157: }
158:
159: try {
160: Constructor cstr = applicatorClazz
161: .getConstructor(APPLICATOR_CSTR_SIGNATURE);
162: Object[] params = new Object[] { encoding };
163: return (ChangeApplicator) cstr.newInstance(params);
164: } catch (Exception e) {
165: throw new AssertionError(e);
166: }
167: }
168: }
|