001: /*
002: * Copyright (C) The MX4J Contributors.
003: * All rights reserved.
004: *
005: * This software is distributed under the terms of the MX4J License version 1.0.
006: * See the terms of the MX4J License in the documentation provided with this software.
007: */
008:
009: package test.javax.management.compliance.serialization.support;
010:
011: import java.lang.reflect.InvocationTargetException;
012: import java.lang.reflect.Method;
013:
014: /**
015: * @version $Revision: 1.4 $
016: */
017: public class SerializationVerifier {
018: private String instantiator;
019: private String comparator;
020:
021: public SerializationVerifier(String instantiator, String comparator) {
022: this .instantiator = instantiator;
023: this .comparator = comparator;
024: }
025:
026: public void verifySerialization(String name,
027: ClassLoader jmxriLoader, ClassLoader mx4jLoader)
028: throws Exception {
029: name = name.substring(name.lastIndexOf('.') + 1);
030:
031: // Create the object, one with MX4J, one with JMXRI
032: Thread.currentThread().setContextClassLoader(mx4jLoader);
033: Object mx4j = create(name);
034: Thread.currentThread().setContextClassLoader(jmxriLoader);
035: Object jmxri = create(name);
036:
037: // Be sure they're not the same class
038: if (mx4j.getClass().isInstance(jmxri))
039: throw new Exception("Classes must be different");
040: if (jmxri.getClass().isInstance(mx4j))
041: throw new Exception("Classes must be different");
042:
043: // Serialize MX4J object
044: Thread.currentThread().setContextClassLoader(mx4jLoader);
045: byte[] mx4jBytes = serialize(mx4j);
046:
047: // Deserialize with JMXRI
048: Thread.currentThread().setContextClassLoader(jmxriLoader);
049: Object jmxriObject = deserialize(mx4jBytes);
050:
051: // Be sure they're not the same class
052: if (mx4j.getClass().isInstance(jmxriObject))
053: throw new Exception("Classes must be different");
054: if (jmxriObject.getClass().isInstance(mx4j))
055: throw new Exception("Classes must be different");
056: // Be also sure the deserialized is of the same type as JMXRI
057: if (jmxri.getClass() != jmxriObject.getClass())
058: throw new Exception("Classes must be equal");
059:
060: // Now compare the original and the deserialized
061: compare(name, jmxri, jmxriObject);
062:
063: // Now, do the opposite
064:
065: // Serialize JMXRI object
066: Thread.currentThread().setContextClassLoader(jmxriLoader);
067: byte[] jmxriBytes = serialize(jmxri);
068:
069: // Deserialize with MX4J
070: Thread.currentThread().setContextClassLoader(mx4jLoader);
071: Object mx4jObject = deserialize(jmxriBytes);
072:
073: // Be sure they're not the same class
074: if (jmxri.getClass().isInstance(mx4jObject))
075: throw new Exception("Classes must be different");
076: if (mx4jObject.getClass().isInstance(jmxri))
077: throw new Exception("Classes must be different");
078: // Be also sure the deserialized is of the same type as MX4J
079: if (mx4j.getClass() != mx4jObject.getClass())
080: throw new Exception("Classes must be equal");
081:
082: // Now compare the original and the deserialized
083: compare(name, mx4j, mx4jObject);
084:
085: }
086:
087: private Object create(String name) throws Exception {
088: // Create an instance of the Instantiator
089: ClassLoader loader = Thread.currentThread()
090: .getContextClassLoader();
091: Object creator = loader.loadClass(instantiator).newInstance();
092:
093: // Lookup the creation method and call it
094: Method method = creator.getClass().getMethod("create" + name,
095: new Class[0]);
096: Object object = method.invoke(creator, new Object[0]);
097: return object;
098: }
099:
100: private byte[] serialize(Object object) throws Exception {
101: // Must delegate again to another object loaded with the correct classloader,
102: // otherwise the deserialization will use the system classloader instead of
103: // the context classloader
104: ClassLoader loader = Thread.currentThread()
105: .getContextClassLoader();
106: Object serializer = loader
107: .loadClass(
108: "test.javax.management.compliance.serialization.support.Serializer")
109: .newInstance();
110: Method method = serializer.getClass().getMethod("serialize",
111: new Class[] { Object.class });
112: return (byte[]) method.invoke(serializer,
113: new Object[] { object });
114: }
115:
116: private Object deserialize(byte[] bytes) throws Exception {
117: // Must delegate again to another object loaded with the correct classloader,
118: // otherwise the deserialization will use the system classloader instead of
119: // the context classloader
120: ClassLoader loader = Thread.currentThread()
121: .getContextClassLoader();
122: Object serializer = loader
123: .loadClass(
124: "test.javax.management.compliance.serialization.support.Serializer")
125: .newInstance();
126: Method method = serializer.getClass().getMethod("deserialize",
127: new Class[] { byte[].class });
128: return method.invoke(serializer, new Object[] { bytes });
129: }
130:
131: private void compare(String name, Object obj1, Object obj2)
132: throws Exception {
133: // First check if the class has the equals method
134: try {
135: obj1.getClass().getDeclaredMethod("equals",
136: new Class[] { Object.class });
137: // It's present
138: if (!obj1.equals(obj2))
139: throw new RuntimeException();
140:
141: } catch (NoSuchMethodException x) {
142: // No equals(), create an instance of the Comparator
143: ClassLoader loader = Thread.currentThread()
144: .getContextClassLoader();
145: Object creator = loader.loadClass(comparator).newInstance();
146:
147: // Lookup the compare method
148: Method method = creator.getClass().getMethod(
149: "compare" + name,
150: new Class[] { Object.class, Object.class });
151: try {
152: method.invoke(creator, new Object[] { obj1, obj2 });
153: } catch (InvocationTargetException xx) {
154: Throwable t = xx.getTargetException();
155: if (t instanceof Exception)
156: throw (Exception) t;
157: else
158: throw (Error) t;
159: }
160: }
161: }
162: }
|