KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > test > javax > management > compliance > signature > support > SignatureVerifier


1 /*
2  * Copyright (C) The MX4J Contributors.
3  * All rights reserved.
4  *
5  * This software is distributed under the terms of the MX4J License version 1.0.
6  * See the terms of the MX4J License in the documentation provided with this software.
7  */

8
9 package test.javax.management.compliance.signature.support;
10
11 import java.io.Serializable JavaDoc;
12 import java.lang.reflect.Field JavaDoc;
13 import java.lang.reflect.Modifier JavaDoc;
14 import java.util.ArrayList JavaDoc;
15 import java.util.HashSet JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.Set JavaDoc;
18
19 /**
20  * @version $Revision: 1.5 $
21  */

22 public class SignatureVerifier
23 {
24    public void verifySignature(String JavaDoc className, ClassLoader JavaDoc jmxriLoader, ClassLoader JavaDoc mx4jLoader) throws Exception JavaDoc
25    {
26       Class JavaDoc jmxriClass = jmxriLoader.loadClass(className);
27       Class JavaDoc mx4jClass = mx4jLoader.loadClass(className);
28
29       int modifiers = jmxriClass.getModifiers();
30       boolean isPublic = Modifier.isPublic(modifiers);
31       boolean isProtected = Modifier.isProtected(modifiers);
32       boolean isPackage = !Modifier.isPrivate(modifiers) && !isProtected && !isPublic;
33       boolean isSerializable = Serializable JavaDoc.class.isAssignableFrom(jmxriClass);
34
35       NotCompliantWarningException warning = null;
36
37       try
38       {
39          checkSameClassModifiers(jmxriClass, mx4jClass);
40       }
41       catch (NotCompliantWarningException x)
42       {
43          warning = x;
44       }
45
46       try
47       {
48          checkSameInheritance(jmxriClass, mx4jClass);
49       }
50       catch (NotCompliantWarningException x)
51       {
52          warning = x;
53       }
54
55       if (!isPackage)
56       {
57          try
58          {
59             checkSameConstructors(jmxriClass, mx4jClass);
60          }
61          catch (NotCompliantWarningException x)
62          {
63             warning = x;
64          }
65          try
66          {
67             checkSameMethods(jmxriClass, mx4jClass);
68          }
69          catch (NotCompliantWarningException x)
70          {
71             warning = x;
72          }
73          try
74          {
75             checkSameFields(jmxriClass, mx4jClass);
76          }
77          catch (NotCompliantWarningException x)
78          {
79             warning = x;
80          }
81       }
82
83       if (isSerializable)
84       {
85          try
86          {
87             checkSameSerialVersionUID(jmxriClass, mx4jClass);
88          }
89          catch (NotCompliantWarningException x)
90          {
91             warning = x;
92          }
93       }
94
95       if (warning != null) throw warning;
96    }
97
98    private void checkSameClassModifiers(Class JavaDoc jmxri, Class JavaDoc mx4j) throws NotCompliantException
99    {
100       int jmxriModifiers = jmxri.getModifiers();
101       int mx4jModifers = mx4j.getModifiers();
102       if (jmxriModifiers != mx4jModifers)
103       {
104          int modifier = jmxriModifiers ^ mx4jModifers;
105          if ((modifier & jmxriModifiers) != 0)
106          {
107             throw new NotCompliantException("JMX class " + jmxri.getName() + " in MX4J implementation is not declared " + Modifier.toString(modifier) + " as it should be");
108          }
109          if ((modifier & mx4jModifers) != 0)
110          {
111             throw new NotCompliantWarningException("JMX class " + jmxri.getName() + " in MX4J implementation is declared " + Modifier.toString(modifier) + ", it is not in JMXRI");
112          }
113       }
114    }
115
116    private void checkSameInheritance(Class JavaDoc jmxri, Class JavaDoc mx4j) throws NotCompliantException
117    {
118       // I have to walk the inheritance hierarchy
119

120       Set JavaDoc jmxriInterfaces = new HashSet JavaDoc();
121       Set JavaDoc mx4jInterfaces = new HashSet JavaDoc();
122       for (Class JavaDoc jmxriParent = jmxri, mx4jParent = mx4j; jmxriParent != null; jmxriParent = jmxriParent.getSuperclass(), mx4jParent = mx4jParent.getSuperclass())
123       {
124          findInterfaces(jmxriParent, jmxriInterfaces);
125
126          findInterfaces(mx4jParent, mx4jInterfaces);
127
128          if (!jmxriParent.getName().equals(mx4jParent.getName()))
129          {
130             throw new NotCompliantException("JMX class " + jmxri.getName() + " in MX4J implementation does not have the same hierarchy as JMXRI: " + mx4jParent.getName() + ", should be " + jmxriParent.getName());
131          }
132       }
133
134       if (!jmxriInterfaces.containsAll(mx4jInterfaces))
135       {
136          mx4jInterfaces.removeAll(jmxriInterfaces);
137          checkInterfacesHaveMethods(jmxri, mx4jInterfaces);
138       }
139       if (!mx4jInterfaces.containsAll(jmxriInterfaces))
140       {
141          jmxriInterfaces.removeAll(mx4jInterfaces);
142          throw new NotCompliantException("JMX class " + jmxri.getName() + " in MX4J implementation does not implement the required interfaces: " + jmxriInterfaces);
143       }
144    }
145
146    private void findInterfaces(Class JavaDoc cls, Set JavaDoc interfaces)
147    {
148       Class JavaDoc[] intfs = cls.getInterfaces();
149       for (int i = 0; i < intfs.length; ++i)
150       {
151          Class JavaDoc intf = intfs[i];
152          boolean added = interfaces.add(intf.getName());
153          if (added) findInterfaces(intf, interfaces);
154       }
155    }
156
157    private void checkInterfacesHaveMethods(Class JavaDoc cls, Set JavaDoc interfaces) throws NotCompliantException
158    {
159       boolean warning = false;
160       for (Iterator JavaDoc i = interfaces.iterator(); i.hasNext();)
161       {
162          String JavaDoc name = (String JavaDoc)i.next();
163          if (name.equals("java.lang.Cloneable"))
164             warning = true;
165          else
166             warning = false;
167       }
168
169       if (warning)
170          throw new NotCompliantWarningException("JMX class " + cls.getName() + " in MX4J implementation implements too many tag interfaces: " + interfaces);
171       else
172          throw new NotCompliantException("JMX class " + cls.getName() + " in MX4J implementation implements too many interfaces: " + interfaces);
173    }
174
175    private void checkSameConstructors(final Class JavaDoc jmxri, Class JavaDoc mx4j) throws NotCompliantException
176    {
177       checkSameObjectMethod(new ObjectClass.Constructor(jmxri), new ObjectClass.Constructor(mx4j));
178    }
179
180    private void checkSameMethods(Class JavaDoc jmxri, Class JavaDoc mx4j) throws NotCompliantException
181    {
182       checkSameObjectMethod(new ObjectClass.Method(jmxri), new ObjectClass.Method(mx4j));
183    }
184
185    private void checkSameObjectMethod(ObjectClass jmxri, ObjectClass mx4j) throws NotCompliantException
186    {
187       // Public methods first
188
Set JavaDoc jmxriMethods = wrapMethods(jmxri.getMethods());
189       Set JavaDoc mx4jMethods = wrapMethods(mx4j.getMethods());
190       checkSameMethods(jmxri.getName(), jmxriMethods, mx4jMethods);
191
192       // Protected methods now. I should walk the inheritance hierarchy.
193
jmxriMethods.clear();
194       mx4jMethods.clear();
195       for (ObjectClass jmxriParent = jmxri, mx4jParent = mx4j; jmxriParent != null; jmxriParent = jmxriParent.getSuperclass(), mx4jParent = mx4jParent.getSuperclass())
196       {
197          ObjectMethod[] methods = jmxriParent.getDeclaredMethods();
198          for (int i = 0; i < methods.length; ++i)
199          {
200             if (Modifier.isProtected(methods[i].getModifiers()))
201             {
202                jmxriMethods.add(wrapMethod(methods[i]));
203             }
204          }
205
206          methods = mx4jParent.getDeclaredMethods();
207          for (int i = 0; i < methods.length; ++i)
208          {
209             if (Modifier.isProtected(methods[i].getModifiers()))
210             {
211                mx4jMethods.add(wrapMethod(methods[i]));
212             }
213          }
214       }
215       checkSameMethods(jmxri.getName(), jmxriMethods, mx4jMethods);
216    }
217
218    private void checkSameFields(Class JavaDoc jmxri, Class JavaDoc mx4j) throws NotCompliantException
219    {
220       // Public fields first
221
Set JavaDoc jmxriFields = wrapFields(jmxri.getFields());
222       Set JavaDoc mx4jFields = wrapFields(mx4j.getFields());
223       checkSameFields(jmxri.getName(), jmxriFields, mx4jFields);
224
225       // Protected fields now. I should walk the inheritance hierarchy.
226
jmxriFields.clear();
227       mx4jFields.clear();
228       for (Class JavaDoc jmxriParent = jmxri, mx4jParent = mx4j; jmxriParent != null; jmxriParent = jmxriParent.getSuperclass(), mx4jParent = mx4jParent.getSuperclass())
229       {
230          Field JavaDoc[] fields = jmxriParent.getDeclaredFields();
231          for (int i = 0; i < fields.length; ++i)
232          {
233             if (Modifier.isProtected(fields[i].getModifiers()))
234             {
235                jmxriFields.add(wrapField(fields[i]));
236             }
237          }
238
239          fields = mx4jParent.getDeclaredFields();
240          for (int i = 0; i < fields.length; ++i)
241          {
242             if (Modifier.isProtected(fields[i].getModifiers()))
243             {
244                mx4jFields.add(wrapField(fields[i]));
245             }
246          }
247       }
248       checkSameFields(jmxri.getName(), jmxriFields, mx4jFields);
249    }
250
251    private void checkSameSerialVersionUID(Class JavaDoc jmxriClass, Class JavaDoc mx4jClass) throws NotCompliantException
252    {
253       try
254       {
255          Field JavaDoc jmxriField = jmxriClass.getField("serialVersionUID");
256          jmxriField.setAccessible(true);
257          Field JavaDoc mx4jField = mx4jClass.getField("serialVersionUID");
258          mx4jField.setAccessible(true);
259          long jmxriValue = jmxriField.getLong(null);
260          long mx4jValue = jmxriField.getLong(null);
261          if (jmxriValue != mx4jValue) throw new NotCompliantException("JMX class " + jmxriClass.getName() + " in MX4J implementation does not have the same serialVersionUID: expecting " + jmxriValue + ", found " + mx4jValue);
262       }
263       catch (NoSuchFieldException JavaDoc ignored)
264       {
265          // If the class did not change between JMX 1.0 and JMX 1.1, then the serialVersionUID is not present
266
}
267       catch (NotCompliantException x)
268       {
269          throw x;
270       }
271       catch (Exception JavaDoc x)
272       {
273          x.printStackTrace();
274          throw new NotCompliantException("Unknown problems in checking serialVersionUID: " + x);
275       }
276    }
277
278    private Set JavaDoc wrapMethods(ObjectMethod[] methods)
279    {
280       Set JavaDoc set = new HashSet JavaDoc();
281       for (int i = 0; i < methods.length; ++i)
282       {
283          set.add(wrapMethod(methods[i]));
284       }
285       return set;
286    }
287
288    private MethodWrapper wrapMethod(ObjectMethod method)
289    {
290       return new MethodWrapper(method);
291    }
292
293    private Set JavaDoc wrapFields(Field JavaDoc[] fields)
294    {
295       HashSet JavaDoc set = new HashSet JavaDoc();
296       for (int i = 0; i < fields.length; ++i)
297       {
298          set.add(wrapField(fields[i]));
299       }
300       return set;
301    }
302
303    private FieldWrapper wrapField(Field JavaDoc field)
304    {
305       return new FieldWrapper(field);
306    }
307
308    private void checkSameMethods(String JavaDoc name, Set JavaDoc jmxri, Set JavaDoc mx4j) throws NotCompliantException
309    {
310       if (!jmxri.containsAll(mx4j))
311       {
312          checkDifferentMethods(name, mx4j, jmxri);
313       }
314
315       if (!mx4j.containsAll(jmxri))
316       {
317          checkDifferentMethods(name, jmxri, mx4j);
318       }
319    }
320
321    private void checkDifferentMethods(String JavaDoc name, Set JavaDoc set1, Set JavaDoc set2) throws NotCompliantException
322    {
323       set1.removeAll(set2);
324
325       boolean warning = false;
326       boolean error = false;
327       ArrayList JavaDoc warnings = new ArrayList JavaDoc();
328       ArrayList JavaDoc errors = new ArrayList JavaDoc();
329       for (Iterator JavaDoc i = set1.iterator(); i.hasNext();)
330       {
331          MethodWrapper method1 = (MethodWrapper)i.next();
332          boolean found = false;
333          for (Iterator JavaDoc j = set2.iterator(); j.hasNext();)
334          {
335             MethodWrapper method2 = (MethodWrapper)j.next();
336             if (method1.isSameMethod(method2))
337             {
338                if (!method1.sameSignatureModifiers(method2))
339                {
340                   warning = true;
341                   warnings.add(method1);
342                   warnings.add(method2);
343                }
344                else
345                {
346                   if (method1.throwsClauseDifferForRuntimeExceptionsOnly(method2))
347                   {
348                      warning = true;
349                      warnings.add(method1);
350                      warnings.add(method2);
351                   }
352                   else
353                   {
354                      error = true;
355                      errors.add(method1);
356                      errors.add(method2);
357                   }
358                }
359                found = true;
360                break;
361             }
362          }
363          if (!found) throw new NotCompliantException("JMX class " + name + " in MX4J implementation has different interface: " + set1);
364       }
365
366       if (error) throw new NotCompliantException("JMX class " + name + " in MX4J implementation has different signature: " + errors);
367       if (warning) throw new NotCompliantWarningException("JMX class " + name + " in MX4J implementation has different signature: " + warnings);
368       throw new IllegalStateException JavaDoc();
369    }
370
371    private void checkSameFields(String JavaDoc name, Set JavaDoc jmxri, Set JavaDoc mx4j) throws NotCompliantException
372    {
373       if (!jmxri.containsAll(mx4j))
374       {
375          mx4j.removeAll(jmxri);
376          throw new NotCompliantException("JMX class " + name + " in MX4J implementation has too many fields: " + mx4j);
377       }
378       if (!mx4j.containsAll(jmxri))
379       {
380          jmxri.removeAll(mx4j);
381          throw new NotCompliantException("JMX class " + name + " in MX4J implementation does not have the required fields: " + jmxri);
382       }
383    }
384 }
385
Popular Tags