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.util;
006:
007: import com.tc.aspectwerkz.reflect.ClassInfo;
008: import com.tc.exception.ImplementMe;
009: import com.tc.object.Portability;
010: import com.tc.object.PortabilityImpl;
011: import com.tc.object.bytecode.TransparentAccess;
012: import com.tc.object.config.DSOClientConfigHelper;
013: import com.tc.util.ClassUtils.ClassSpec;
014:
015: import java.io.ByteArrayOutputStream;
016: import java.io.OutputStream;
017: import java.lang.reflect.InvocationHandler;
018: import java.lang.reflect.Method;
019: import java.lang.reflect.Proxy;
020: import java.net.Socket;
021: import java.text.ParseException;
022: import java.util.Arrays;
023: import java.util.Collections;
024: import java.util.HashMap;
025: import java.util.Map;
026: import java.util.Set;
027:
028: import junit.framework.TestCase;
029:
030: public class ClassUtilsTest extends TestCase {
031:
032: // private StringWriter stringWriter;
033: // private PrintWriter printWriter;
034: // private NonPortableReasonFormatter reasonFormatter;
035:
036: public void setUp() {
037: // stringWriter = new StringWriter();
038: // printWriter = new PrintWriter(stringWriter);
039: // reasonFormatter = newFormatter(printWriter);
040: }
041:
042: public void testArrayMethods() {
043: assertEquals(int.class, ClassUtils
044: .baseComponentType(int[][][][][].class));
045: assertEquals(Object.class, ClassUtils
046: .baseComponentType(Object[].class));
047:
048: try {
049: ClassUtils.baseComponentType(null);
050: fail();
051: } catch (NullPointerException e) {
052: // expected
053: }
054:
055: try {
056: ClassUtils.baseComponentType(int.class);
057: fail();
058: } catch (IllegalArgumentException e) {
059: // expected
060: }
061:
062: assertEquals(5, ClassUtils.arrayDimensions(int[][][][][].class));
063: assertEquals(1, ClassUtils.arrayDimensions(Object[].class));
064:
065: try {
066: ClassUtils.arrayDimensions(null);
067: fail();
068: } catch (NullPointerException e) {
069: // expected
070: }
071:
072: try {
073: ClassUtils.arrayDimensions(int.class);
074: fail();
075: } catch (IllegalArgumentException e) {
076: // expected
077: }
078:
079: }
080:
081: public void testNonPortableReason() {
082: NonPortableReason reason = null;
083: DSOClientConfigHelper config;
084: Portability p;
085:
086: // NonPortableReason.CLASS_NOT_ADAPTABLE
087: config = getConfig(Collections.singleton(NotAdaptable.class
088: .getName()));
089: p = new PortabilityImpl(config);
090: reason = p.getNonPortableReason(NotAdaptable.class);
091: assertEquals(NonPortableReason.CLASS_NOT_ADAPTABLE, reason
092: .getReason());
093: assertEquals(NotAdaptable.class.getName(), reason
094: .getClassName());
095: assertEquals(Collections.EMPTY_LIST, reason
096: .getErroneousBootJarSuperClasses());
097: assertEquals(Collections.EMPTY_LIST, reason
098: .getErroneousSuperClasses());
099: // This is here for visual inspection of the output.
100: // printReason(reason);
101:
102: // NonPortableReason.SUPER_CLASS_NOT_ADAPTABLE
103: config = getConfig(Collections.singleton(NotAdaptable.class
104: .getName()));
105: p = new PortabilityImpl(config);
106: reason = p.getNonPortableReason(ExtendsNotAdaptable.class);
107: assertEquals(NonPortableReason.SUPER_CLASS_NOT_ADAPTABLE,
108: reason.getReason());
109: assertEquals(ExtendsNotAdaptable.class.getName(), reason
110: .getClassName());
111: assertEquals(Collections.EMPTY_LIST, reason
112: .getErroneousBootJarSuperClasses());
113: assertEquals(Arrays.asList(new Object[] { NotAdaptable.class
114: .getName() }), reason.getErroneousSuperClasses());
115: // printReason(reason);
116:
117: // NonPortableReason.SUBCLASS_OF_LOGICALLY_MANAGED_CLASS
118: config = getConfig(Collections.EMPTY_SET);
119: p = new PortabilityImpl(config);
120: reason = p.getNonPortableReason(LogicalSubclass.class);
121: assertEquals(
122: NonPortableReason.SUBCLASS_OF_LOGICALLY_MANAGED_CLASS,
123: reason.getReason());
124: assertEquals(LogicalSubclass.class.getName(), reason
125: .getClassName());
126: assertEquals(Arrays.asList(new Object[] { HashMap.class
127: .getName() }), reason.getErroneousBootJarSuperClasses());
128: assertEquals(Collections.EMPTY_LIST, reason
129: .getErroneousSuperClasses());
130: // printReason(reason);
131:
132: // NonPortableReason.CLASS_NOT_IN_BOOT_JAR
133: // -- no supers
134: config = getConfig(Collections.EMPTY_SET);
135: p = new PortabilityImpl(config);
136: reason = p.getNonPortableReason(OutputStream.class);
137: assertEquals(NonPortableReason.CLASS_NOT_IN_BOOT_JAR, reason
138: .getReason());
139: assertEquals(OutputStream.class.getName(), reason
140: .getClassName());
141: assertEquals(Collections.EMPTY_LIST, reason
142: .getErroneousBootJarSuperClasses());
143: assertEquals(Collections.EMPTY_LIST, reason
144: .getErroneousSuperClasses());
145: // printReason(reason);
146:
147: // NonPortableReason.CLASS_NOT_IN_BOOT_JAR
148: // -- boot jar supers
149: config = getConfig(Collections.EMPTY_SET);
150: p = new PortabilityImpl(config);
151: reason = p.getNonPortableReason(ByteArrayOutputStream.class);
152: assertEquals(NonPortableReason.CLASS_NOT_IN_BOOT_JAR, reason
153: .getReason());
154: assertEquals(ByteArrayOutputStream.class.getName(), reason
155: .getClassName());
156: assertEquals(Arrays.asList(new Object[] { OutputStream.class
157: .getName() }), reason.getErroneousBootJarSuperClasses());
158: assertEquals(Collections.EMPTY_LIST, reason
159: .getErroneousSuperClasses());
160: // printReason(reason);
161:
162: // NOTE: NonPortableReason.CLASS_NOT_IN_BOOT_JAR cannot have non-boot jar super classes
163: // (or a mix of boot-jar and non-boot-jar supers)
164:
165: // NonPortableReason.CLASS_NOT_INCLUDED_IN_CONFIG
166: // -- no supers
167: config = getConfig(Collections.EMPTY_SET);
168: p = new PortabilityImpl(config);
169: reason = p.getNonPortableReason(Pojo.class);
170: assertEquals(NonPortableReason.CLASS_NOT_INCLUDED_IN_CONFIG,
171: reason.getReason());
172: assertEquals(Pojo.class.getName(), reason.getClassName());
173: assertEquals(Collections.EMPTY_LIST, reason
174: .getErroneousBootJarSuperClasses());
175: assertEquals(Collections.EMPTY_LIST, reason
176: .getErroneousSuperClasses());
177: // printReason(reason);
178:
179: // NonPortableReason.CLASS_NOT_INCLUDED_IN_CONFIG
180: // -- regular supers
181: config = getConfig(Collections.EMPTY_SET);
182: p = new PortabilityImpl(config);
183: reason = p.getNonPortableReason(SubPojo.class);
184: assertEquals(NonPortableReason.CLASS_NOT_INCLUDED_IN_CONFIG,
185: reason.getReason());
186: assertEquals(SubPojo.class.getName(), reason.getClassName());
187: assertEquals(Collections.EMPTY_LIST, reason
188: .getErroneousBootJarSuperClasses());
189: assertEquals(Arrays
190: .asList(new Object[] { Pojo.class.getName() }), reason
191: .getErroneousSuperClasses());
192: // printReason(reason);
193:
194: // NonPortableReason.CLASS_NOT_INCLUDED_IN_CONFIG
195: // -- boot jar supers
196: config = getConfig(Collections.EMPTY_SET);
197: p = new PortabilityImpl(config);
198: reason = p.getNonPortableReason(SubClassOfBootJarClass.class);
199: assertEquals(NonPortableReason.CLASS_NOT_INCLUDED_IN_CONFIG,
200: reason.getReason());
201: assertEquals(SubClassOfBootJarClass.class.getName(), reason
202: .getClassName());
203: assertEquals(Arrays.asList(new Object[] {
204: ByteArrayOutputStream.class.getName(),
205: OutputStream.class.getName() }), reason
206: .getErroneousBootJarSuperClasses());
207: assertEquals(Collections.EMPTY_LIST, reason
208: .getErroneousSuperClasses());
209: // printReason(reason);
210:
211: // NonPortableReason.CLASS_NOT_INCLUDED_IN_CONFIG
212: // -- both regular and non-boot jar supers
213: config = getConfig(Collections.EMPTY_SET);
214: p = new PortabilityImpl(config);
215: reason = p.getNonPortableReason(PojoExtendsBootJar.class);
216: assertEquals(NonPortableReason.CLASS_NOT_INCLUDED_IN_CONFIG,
217: reason.getReason());
218: assertEquals(PojoExtendsBootJar.class.getName(), reason
219: .getClassName());
220: assertEquals(Arrays.asList(new Object[] {
221: ByteArrayOutputStream.class.getName(),
222: OutputStream.class.getName() }), reason
223: .getErroneousBootJarSuperClasses());
224: assertEquals(Arrays
225: .asList(new Object[] { SubClassOfBootJarClass.class
226: .getName() }), reason
227: .getErroneousSuperClasses());
228: // printReason(reason);
229:
230: // NonPortableReason.SUPER_CLASS_NOT_INSTRUMENTED
231: // -- regular supers
232: config = getConfig(Collections.EMPTY_SET);
233: p = new PortabilityImpl(config);
234: reason = p
235: .getNonPortableReason(InstrumentedExtendsRegularNotInstrumented.class);
236: assertEquals(NonPortableReason.SUPER_CLASS_NOT_INSTRUMENTED,
237: reason.getReason());
238: assertEquals(InstrumentedExtendsRegularNotInstrumented.class
239: .getName(), reason.getClassName());
240: assertEquals(Collections.EMPTY_LIST, reason
241: .getErroneousBootJarSuperClasses());
242: assertEquals(Arrays
243: .asList(new Object[] { Pojo.class.getName() }), reason
244: .getErroneousSuperClasses());
245: // printReason(reason);
246:
247: // NonPortableReason.SUPER_CLASS_NOT_INSTRUMENTED
248: // -- boot jar supers
249: config = getConfig(Collections.EMPTY_SET);
250: p = new PortabilityImpl(config);
251: reason = p
252: .getNonPortableReason(InstrumentedExtendsBootJarNotInstrumented.class);
253: assertEquals(NonPortableReason.SUPER_CLASS_NOT_INSTRUMENTED,
254: reason.getReason());
255: assertEquals(InstrumentedExtendsBootJarNotInstrumented.class
256: .getName(), reason.getClassName());
257: assertEquals(Arrays.asList(new Object[] { OutputStream.class
258: .getName() }), reason.getErroneousBootJarSuperClasses());
259: assertEquals(Collections.EMPTY_LIST, reason
260: .getErroneousSuperClasses());
261: // printReason(reason);
262:
263: // NonPortableReason.SUPER_CLASS_NOT_INSTRUMENTED
264: // -- both regular and non-boot jar supers
265: config = getConfig(Collections.EMPTY_SET);
266: p = new PortabilityImpl(config);
267: reason = p
268: .getNonPortableReason(InstrumentedExtendsBothNotInstrumented.class);
269: assertEquals(NonPortableReason.SUPER_CLASS_NOT_INSTRUMENTED,
270: reason.getReason());
271: assertEquals(InstrumentedExtendsBothNotInstrumented.class
272: .getName(), reason.getClassName());
273: assertEquals(Arrays.asList(new Object[] {
274: ByteArrayOutputStream.class.getName(),
275: OutputStream.class.getName() }), reason
276: .getErroneousBootJarSuperClasses());
277: assertEquals(Arrays
278: .asList(new Object[] { SubClassOfBootJarClass.class
279: .getName() }), reason
280: .getErroneousSuperClasses());
281: // printReason(reason);
282:
283: }
284:
285: private DSOClientConfigHelper getConfig(final Set neverAdaptaed) {
286: InvocationHandler handler = new InvocationHandler() {
287: public Object invoke(Object proxy, Method method,
288: Object[] args) throws Throwable {
289: String name = method.getName();
290: if ("getNewCommonL1Config".equals(name)) {
291: return null;
292: } else if ("getLogicalExtendingClassName".equals(name)) {
293: return null;
294: } else if ("createDsoClassAdapterFor".equals(name)) {
295: return null;
296: } else if ("getModulesForInitialization".equals(name)) {
297: return null;
298: } else if ("shouldBeAdapted".equals(name)) {
299: return Boolean.TRUE;
300: } else if ("isPortableModuleClass".equals(name)) {
301: return Boolean.FALSE;
302: } else if ("getSpec".equals(name)) {
303: return null;
304: } else if ("isNeverAdaptable".equals(name)) {
305: return neverAdaptaed.contains(((ClassInfo) args[0])
306: .getName()) ? Boolean.TRUE : Boolean.FALSE;
307: } else if ("isLogical".equals(name)) { //
308: return ((String) args[0]).startsWith("java.util.") ? Boolean.TRUE
309: : Boolean.FALSE;
310: }
311:
312: throw new ImplementMe();
313: }
314: };
315: ClassLoader loader = getClass().getClassLoader();
316: Object proxy = Proxy.newProxyInstance(loader,
317: new Class[] { DSOClientConfigHelper.class }, handler);
318: return (DSOClientConfigHelper) proxy;
319: }
320:
321: // private void printReason(NonPortableReason reason) {
322: // reasonFormatter.formatReasonTypeName(reason.getReason());
323: // printWriter.println();
324: // reason.accept(reasonFormatter);
325: // reasonFormatter.flush();
326: // printWriter.flush();
327: //
328: // System.err.println("******************************************************************");
329: // System.err.println(stringWriter.getBuffer());
330: // System.err.println();
331: // stringWriter.getBuffer().delete(0, stringWriter.getBuffer().length());
332: // }
333:
334: // private NonPortableReasonFormatter newFormatter(PrintWriter out) {
335: // ConsoleParagraphFormatter paragraphFormatter = new ConsoleParagraphFormatter(120, new StringFormatter());
336: // NonPortableReasonFormatter formatter = new ConsoleNonPortableReasonFormatter(out, ": ", new StringFormatter(),
337: // paragraphFormatter);
338: // return formatter;
339: // }
340:
341: public void testIsPrimitiveArray() {
342:
343: assertTrue(ClassUtils.isPrimitiveArray(new byte[0]));
344: assertTrue(ClassUtils.isPrimitiveArray(new boolean[1]));
345: assertTrue(ClassUtils.isPrimitiveArray(new char[2]));
346: assertTrue(ClassUtils.isPrimitiveArray(new double[3]));
347: assertTrue(ClassUtils.isPrimitiveArray(new float[4]));
348: assertTrue(ClassUtils.isPrimitiveArray(new int[5]));
349: assertTrue(ClassUtils.isPrimitiveArray(new long[6]));
350: assertTrue(ClassUtils.isPrimitiveArray(new short[7]));
351:
352: assertFalse(ClassUtils.isPrimitiveArray(new Object[0]));
353: assertFalse(ClassUtils.isPrimitiveArray(new TestCase[42]));
354: assertFalse(ClassUtils.isPrimitiveArray(new Socket[][] { {} }));
355: assertFalse(ClassUtils.isPrimitiveArray(new byte[][] { {} }));
356:
357: assertFalse(ClassUtils.isPrimitiveArray(null));
358: assertFalse(ClassUtils.isPrimitiveArray(new Object()));
359: }
360:
361: public void testParseFullyQualifiedFieldName() throws Exception {
362: String shortFieldName = "baz";
363: String fullyQualifiedClassname = "foo.Bar";
364: String fullyQualifiedFieldname = fullyQualifiedClassname + "."
365: + shortFieldName;
366: ClassUtils
367: .parseFullyQualifiedFieldName(fullyQualifiedFieldname);
368:
369: ClassSpec spec = ClassUtils
370: .parseFullyQualifiedFieldName(fullyQualifiedFieldname);
371: assertEquals(shortFieldName, spec.getShortFieldName());
372: assertEquals(fullyQualifiedClassname, spec
373: .getFullyQualifiedClassName());
374:
375: try {
376: spec = ClassUtils
377: .parseFullyQualifiedFieldName(shortFieldName);
378: fail("Expected a ParseException");
379: } catch (ParseException e) {
380: // expected
381: }
382:
383: try {
384: spec = ClassUtils.parseFullyQualifiedFieldName("foo.");
385: fail("Excpected a ParseException");
386: } catch (ParseException e) {
387: // expected
388: }
389:
390: try {
391: spec = ClassUtils.parseFullyQualifiedFieldName(".foo");
392: fail("Excpected a ParseException");
393: } catch (ParseException e) {
394: // expected
395: }
396:
397: }
398:
399: private static class NotAdaptable {
400: //
401: }
402:
403: private static class ExtendsNotAdaptable extends NotAdaptable {
404: //
405: }
406:
407: private static class LogicalSubclass extends java.util.HashMap {
408: //
409: }
410:
411: private static class SubClassOfBootJarClass extends
412: ByteArrayOutputStream {
413: //
414: }
415:
416: private static class Pojo extends Object {
417: //
418: }
419:
420: private static class SubPojo extends Pojo {
421: //
422: }
423:
424: private static class PojoExtendsBootJar extends
425: SubClassOfBootJarClass {
426: //
427: }
428:
429: private static class InstrumentedExtendsBothNotInstrumented extends
430: SubClassOfBootJarClass implements TransparentAccess {
431: public void __tc_getallfields(Map map) {
432: throw new ImplementMe();
433: }
434:
435: public void __tc_setfield(String name, Object value) {
436: throw new ImplementMe();
437: }
438:
439: public Object __tc_getmanagedfield(String name) {
440: throw new ImplementMe();
441: }
442:
443: public void __tc_setmanagedfield(String name, Object value) {
444: throw new ImplementMe();
445: }
446: }
447:
448: private static class InstrumentedExtendsBootJarNotInstrumented
449: extends OutputStream implements TransparentAccess {
450:
451: public void write(int b) {
452: throw new ImplementMe();
453: }
454:
455: public void __tc_getallfields(Map map) {
456: throw new ImplementMe();
457: }
458:
459: public void __tc_setfield(String name, Object value) {
460: throw new ImplementMe();
461: }
462:
463: public Object __tc_getmanagedfield(String name) {
464: throw new ImplementMe();
465: }
466:
467: public void __tc_setmanagedfield(String name, Object value) {
468: throw new ImplementMe();
469: }
470: }
471:
472: private static class InstrumentedExtendsRegularNotInstrumented
473: extends Pojo implements TransparentAccess {
474: public void __tc_getallfields(Map map) {
475: throw new ImplementMe();
476: }
477:
478: public void __tc_setfield(String name, Object value) {
479: throw new ImplementMe();
480: }
481:
482: public Object __tc_getmanagedfield(String name) {
483: throw new ImplementMe();
484: }
485:
486: public void __tc_setmanagedfield(String name, Object value) {
487: throw new ImplementMe();
488: }
489: }
490:
491: }
|