001: /*
002: * All content copyright (c) 2003-2007 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.impl.java.JavaClassInfo;
008: import com.tc.logging.TCLogger;
009: import com.tc.object.config.DSOClientConfigHelper;
010: import com.tc.object.walker.MemberValue;
011: import com.tc.object.walker.PrintVisitor;
012: import com.tc.object.walker.Visitor;
013: import com.tc.object.walker.WalkTest;
014: import com.tc.object.walker.PrintVisitor.OutputSink;
015: import com.tc.object.walker.PrintVisitor.ValueFormatter;
016:
017: import java.lang.reflect.Field;
018:
019: public class NonPortableWalkVisitor implements Visitor, ValueFormatter,
020: WalkTest, OutputSink {
021:
022: public static final String MARKER = "!!";
023: private static final String NON_PORTABLE = MARKER + " ";
024: private static final String PORTABLE = spaces(NON_PORTABLE.length());
025: private static final LiteralValues literals = new LiteralValues();
026:
027: private final PrintVisitor delegate;
028: private final ClientObjectManager objMgr;
029: private final DSOClientConfigHelper config;
030: private final TCLogger logger;
031: private StringBuffer buffer = new StringBuffer();
032:
033: public NonPortableWalkVisitor(TCLogger logger,
034: ClientObjectManager objMgr, DSOClientConfigHelper config,
035: Object root) {
036: this .logger = logger;
037: this .objMgr = objMgr;
038: this .config = config;
039: delegate = new PrintVisitor(this , this , this );
040:
041: logger
042: .warn("Dumping object graph of non-portable instance of type "
043: + root.getClass().getName()
044: + ". Lines that start with "
045: + NonPortableWalkVisitor.MARKER
046: + " are non-portable types.");
047: }
048:
049: public void output(String line) {
050: logger.warn(buffer.toString() + line);
051: buffer = new StringBuffer();
052: }
053:
054: private static String spaces(int n) {
055: String s = "";
056: for (int i = 0; i < n; i++) {
057: s += " ";
058: }
059: return s;
060: }
061:
062: public void visitMapEntry(int index, int depth) {
063: buffer.append(PORTABLE);
064: delegate.visitMapEntry(index, depth);
065: }
066:
067: public void visitRootObject(MemberValue value) {
068: indicatePortability(value);
069: delegate.visitRootObject(value);
070: }
071:
072: public void visitValue(MemberValue value, int depth) {
073: if (skipVisit(value)) {
074: return;
075: }
076: indicatePortability(value);
077: delegate.visitValue(value, depth);
078: }
079:
080: public String format(Object value) {
081: if (value == null) {
082: return "null";
083: }
084:
085: int type = literals.valueFor(value);
086: switch (type) {
087: case LiteralValues.OBJECT: {
088: return "(" + value.getClass().getName() + ")";
089: }
090: case LiteralValues.JAVA_LANG_CLASSLOADER: {
091: return "Classloader (" + value.getClass().getName() + ")";
092: }
093: case LiteralValues.STRING: {
094: return "\"" + value + "\"";
095: }
096: default: {
097: return String.valueOf(value);
098: }
099: }
100: }
101:
102: public String valueAdornment(MemberValue value) {
103: if (isTransient(value)) {
104: return " (transient)";
105: }
106:
107: Object o = value.getValueObject();
108: if (o != null
109: && config.isNeverAdaptable(JavaClassInfo.getClassInfo(o
110: .getClass()))) {
111: return " (never portable)";
112: }
113:
114: return null;
115: }
116:
117: public boolean shouldTraverse(MemberValue val) {
118: if (literals.isLiteralInstance(val.getValueObject())) {
119: return false;
120: }
121: if (isTransient(val)) {
122: return false;
123: }
124:
125: Object o = val.getValueObject();
126: if (o != null
127: && config.isNeverAdaptable(JavaClassInfo.getClassInfo(o
128: .getClass()))) {
129: return false;
130: }
131:
132: return true;
133: }
134:
135: private boolean isTransient(MemberValue val) {
136: Field f = val.getSourceField();
137: if (f == null) {
138: return false;
139: }
140:
141: return config.isTransient(f.getModifiers(), JavaClassInfo
142: .getClassInfo(f.getDeclaringClass()), f.getName());
143: }
144:
145: public boolean includeFieldsForType(Class type) {
146: return !config.isLogical(type.getName());
147: }
148:
149: private boolean skipVisit(MemberValue value) {
150: Field field = value.getSourceField();
151: if (field != null) {
152: return (field.getType().getName().startsWith("com.tc."));
153: }
154: return false;
155: }
156:
157: private void indicatePortability(MemberValue value) {
158: if (objMgr.isPortableInstance(value.getValueObject())) {
159: buffer.append(PORTABLE);
160: } else {
161: buffer.append(NON_PORTABLE);
162: }
163: }
164:
165: }
|