KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jdo > api > persistence > support > util > AugmentationTest


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 /*
25  * AugmentationTest.java
26  *
27  * Create on April 19, 2001
28  */

29
30 package com.sun.jdo.api.persistence.support.util;
31
32
33 import java.lang.reflect.*;
34 import java.util.List JavaDoc;
35 import java.util.ArrayList JavaDoc;
36 import java.io.PrintStream JavaDoc;
37
38 // note the use of the public vs. the internal interfaces by this class
39
import com.sun.jdo.api.persistence.support.PersistenceManager;
40 import com.sun.jdo.spi.persistence.support.sqlstore.PersistenceCapable;
41 import com.sun.jdo.spi.persistence.support.sqlstore.StateManager;
42
43 /**
44  * Utility class for testing a class file for correct augmentation.
45  */

46 public class AugmentationTest
47 {
48     static boolean debug = false;
49     static final PrintStream JavaDoc out = System.out;
50
51     static final void affirm(boolean cond)
52     {
53         if (debug && !cond)
54             throw new RuntimeException JavaDoc("affirmion failed.");
55     }
56
57     static final void affirm(Object JavaDoc obj)
58     {
59         if (debug && obj == null)
60             throw new RuntimeException JavaDoc("affirmion failed: obj = null");
61     }
62
63     static String JavaDoc toString(int mods,
64                            Class JavaDoc type,
65                            String JavaDoc name)
66     {
67         final StringBuffer JavaDoc s = new StringBuffer JavaDoc();
68         s.append(Modifier.toString(mods));
69         s.append(" ");
70         s.append(type.getName());
71         s.append(" ");
72         s.append(name);
73         return s.toString();
74     }
75
76     static String JavaDoc toString(int mods,
77                            String JavaDoc name,
78                            Class JavaDoc[] params)
79     {
80         final StringBuffer JavaDoc s = new StringBuffer JavaDoc();
81         s.append(Modifier.toString(mods));
82         s.append(" ");
83         s.append(name);
84         s.append("(");
85         final int j = params.length - 1;
86         for (int i = 0; i <= j; i++) {
87             s.append(params[i].getName());
88             if (i < j)
89                 s.append(",");
90         }
91         s.append(")");
92         return s.toString();
93     }
94
95     static String JavaDoc toString(int mods,
96                            Class JavaDoc result,
97                            String JavaDoc name,
98                            Class JavaDoc[] params)
99     {
100         final StringBuffer JavaDoc s = new StringBuffer JavaDoc();
101         s.append(Modifier.toString(mods));
102         s.append(" ");
103         s.append(result.getName());
104         s.append(" ");
105         s.append(name);
106         s.append("(");
107         final int j = params.length - 1;
108         for (int i = 0; i <= j; i++) {
109             s.append(params[i].getName());
110             if (i < j)
111                 s.append(",");
112         }
113         s.append(")");
114         return s.toString();
115     }
116
117     public final int AFFIRMATIVE = 1;
118     public final int NEGATIVE = 0;
119     public final int ERROR = -1;
120
121     boolean verbose;
122     boolean requirePC;
123     List JavaDoc classes;
124     String JavaDoc className;
125     Class JavaDoc classClass;
126
127     public AugmentationTest()
128     {}
129
130     final void println()
131     {
132         out.println();
133     }
134
135     final void println(String JavaDoc msg)
136     {
137         out.println(msg);
138     }
139
140     final void verbose()
141     {
142         if (verbose)
143             out.println();
144     }
145
146     final void verbose(String JavaDoc msg)
147     {
148         if (verbose)
149             out.println(msg);
150     }
151
152     public int testLoadingClass()
153     {
154         verbose();
155         verbose("Test loading class: " + className + " ...");
156
157         try {
158             classClass = Class.forName(className);
159             verbose("+++ loaded class");
160             return AFFIRMATIVE;
161         } catch (LinkageError JavaDoc err) {
162             println("!!! ERROR: linkage error when loading class: "
163                     + className);
164             println(" error: " + err);
165             println("!!! failed loading class");
166             return ERROR;
167         } catch (ClassNotFoundException JavaDoc ex) {
168             println("!!! ERROR: class not found: " + className);
169             println(" exception: " + ex);
170             println("!!! failed loading class");
171             return ERROR;
172         }
173     }
174
175     int implementsInterface(Class JavaDoc intf)
176     {
177         final Class JavaDoc[] interfaces = classClass.getInterfaces();
178         for (int i = interfaces.length - 1; i >= 0; i--) {
179             if (interfaces[i].equals(intf)) {
180                 verbose("+++ implements interface: " + intf.getName());
181                 return AFFIRMATIVE;
182             }
183         }
184         verbose("--- not implementing interface: " + intf.getName());
185         return NEGATIVE;
186     }
187
188     int hasField(int mods,
189                  Class JavaDoc type,
190                  String JavaDoc name)
191     {
192         try {
193             final Field field = classClass.getField(name);
194
195             if (field.getModifiers() != mods
196                 || !field.getType().equals(type)) {
197                 println("!!! ERROR: field declaration: ");
198                 println(" expected: " + toString(mods, type, name));
199                 println(" found: " + field.toString());
200                 return ERROR;
201             }
202
203             verbose("+++ has field: " + field.toString());
204             return AFFIRMATIVE;
205
206         } catch (NoSuchFieldException JavaDoc ex) {
207             verbose("--- no field: " + toString(mods, type, name));
208             return NEGATIVE;
209         }
210     }
211
212     int hasConstructor(int mods,
213                        Class JavaDoc[] params)
214     {
215         try {
216             final Constructor ctor = classClass.getConstructor(params);
217
218             if (ctor.getModifiers() != mods) {
219                 println("!!! ERROR: constructor declaration: ");
220                 println(" expected: " + toString(mods, className, params));
221                 println(" found: " + ctor.toString());
222                 return ERROR;
223             }
224
225             verbose("+++ has constructor: " + ctor.toString());
226             return AFFIRMATIVE;
227
228         } catch (NoSuchMethodException JavaDoc ex) {
229             verbose("--- no constructor: "
230                     + toString(mods, className, params));
231             return NEGATIVE;
232         }
233     }
234
235     int hasMethod(int mods,
236                   Class JavaDoc result,
237                   String JavaDoc name,
238                   Class JavaDoc[] params)
239     {
240         try {
241             final Method method = classClass.getMethod(name, params);
242
243             if (method.getModifiers() != mods
244                 || !method.getReturnType().equals(result)) {
245                 println("!!! ERROR: method declaration: ");
246                 println(" expected: " + toString(mods, result, name, params));
247                 println(" found: " + method.toString());
248                 return ERROR;
249             }
250
251             verbose("+++ has method: " + method.toString());
252             return AFFIRMATIVE;
253
254         } catch (NoSuchMethodException JavaDoc ex) {
255             verbose("--- no method: "
256                     + toString(mods, result, name, params));
257             return NEGATIVE;
258         }
259     }
260
261     public int hasGenericAugmentation()
262     {
263         affirm(ERROR < NEGATIVE && NEGATIVE < AFFIRMATIVE);
264
265         verbose();
266         verbose("Check for \"generic\" augmentation ...");
267         affirm(classClass);
268
269         final int nofFeatures = 15;
270         final int[] r = new int[nofFeatures];
271         {
272             int i = 0;
273             r[i++] = implementsInterface(PersistenceCapable.class);
274
275             r[i++] = hasField(Modifier.PUBLIC | Modifier.TRANSIENT,
276                               StateManager.class,
277                               "jdoStateManager");
278             r[i++] = hasField(Modifier.PUBLIC | Modifier.TRANSIENT,
279                               byte.class,
280                               "jdoFlags");
281
282             r[i++] = hasMethod(Modifier.PUBLIC | Modifier.FINAL,
283                                StateManager.class,
284                                "jdoGetStateManager",
285                                new Class JavaDoc[]{});
286             r[i++] = hasMethod(Modifier.PUBLIC | Modifier.FINAL,
287                                void.class,
288                                "jdoSetStateManager",
289                                new Class JavaDoc[]{StateManager.class});
290
291             r[i++] = hasMethod(Modifier.PUBLIC | Modifier.FINAL,
292                                byte.class,
293                                "jdoGetFlags",
294                                new Class JavaDoc[]{});
295             r[i++] = hasMethod(Modifier.PUBLIC | Modifier.FINAL,
296                                void.class,
297                                "jdoSetFlags",
298                                new Class JavaDoc[]{byte.class});
299
300             r[i++] = hasMethod(Modifier.PUBLIC | Modifier.FINAL,
301                                PersistenceManager.class,
302                                "jdoGetPersistenceManager",
303                                new Class JavaDoc[]{});
304
305             r[i++] = hasMethod(Modifier.PUBLIC | Modifier.FINAL,
306                                Object JavaDoc.class,
307                                "jdoGetObjectId",
308                                new Class JavaDoc[]{});
309
310             r[i++] = hasMethod(Modifier.PUBLIC | Modifier.FINAL,
311                                boolean.class,
312                                "jdoIsDirty",
313                                new Class JavaDoc[]{});
314             r[i++] = hasMethod(Modifier.PUBLIC | Modifier.FINAL,
315                                boolean.class,
316                                "jdoIsTransactional",
317                                new Class JavaDoc[]{});
318             r[i++] = hasMethod(Modifier.PUBLIC | Modifier.FINAL,
319                                boolean.class,
320                                "jdoIsPersistent",
321                                new Class JavaDoc[]{});
322             r[i++] = hasMethod(Modifier.PUBLIC | Modifier.FINAL,
323                                boolean.class,
324                                "jdoIsNew",
325                                new Class JavaDoc[]{});
326             r[i++] = hasMethod(Modifier.PUBLIC | Modifier.FINAL,
327                                boolean.class,
328                                "jdoIsDeleted",
329                                new Class JavaDoc[]{});
330
331             r[i++] = hasMethod(Modifier.PUBLIC | Modifier.FINAL,
332                                void.class,
333                                "jdoMakeDirty",
334                                new Class JavaDoc[]{String JavaDoc.class});
335             affirm(i == nofFeatures);
336         }
337
338         int res = 0;
339         for (int i = 0; i < nofFeatures; i ++) {
340             final int j = r[i];
341             affirm(ERROR <= j && j <= AFFIRMATIVE);
342
343             if (j < res) {
344                 println("!!! ERROR: inconsistent \"generic\" augmentation of class: "
345                       + className);
346                 return ERROR;
347             }
348
349             if (j > NEGATIVE)
350                 res = j;
351         }
352
353         if (res > NEGATIVE) {
354             verbose("+++ has \"generic\" augmentation");
355             return AFFIRMATIVE;
356         }
357
358         verbose("--- no \"generic\" augmentation");
359         return NEGATIVE;
360     }
361
362     public int hasSpecificAugmentation()
363     {
364         affirm(ERROR < NEGATIVE && NEGATIVE < AFFIRMATIVE);
365
366         verbose();
367         verbose("Check for \"class-specific\" augmentation ...");
368         affirm(classClass);
369
370         final int nofFeatures = 5;
371         final int[] r = new int[nofFeatures];
372         {
373             int i = 0;
374             r[i++] = hasConstructor(Modifier.PUBLIC,
375                                     new Class JavaDoc[]{StateManager.class});
376             r[i++] = hasMethod(Modifier.PUBLIC,
377                                Object JavaDoc.class,
378                                "jdoGetField",
379                                new Class JavaDoc[]{int.class});
380             r[i++] = hasMethod(Modifier.PUBLIC,
381                                void.class,
382                                "jdoSetField",
383                                new Class JavaDoc[]{int.class, Object JavaDoc.class});
384
385             r[i++] = hasMethod(Modifier.PUBLIC,
386                                void.class,
387                                "jdoClear",
388                                new Class JavaDoc[]{});
389             r[i++] = hasMethod(Modifier.PUBLIC,
390                                Object JavaDoc.class,
391                                "jdoNewInstance",
392                                new Class JavaDoc[]{StateManager.class});
393             affirm(i == nofFeatures);
394         }
395
396         //@olsen: todo
397
// + clone()
398

399         int res = 0;
400         for (int i = 0; i < nofFeatures; i++) {
401             final int j = r[i];
402             affirm(ERROR <= j && j <= AFFIRMATIVE);
403
404             if (j < res) {
405                 println("!!! ERROR: inconsistent \"class-specific\" augmentation of class: "
406                       + className);
407                 return ERROR;
408             }
409
410             if (j > NEGATIVE)
411                 res = j;
412         }
413
414         if (res > NEGATIVE) {
415             verbose("+++ has \"class-specific\" augmentation");
416             return AFFIRMATIVE;
417         }
418
419         verbose("--- no \"class-specific\" augmentation");
420         return NEGATIVE;
421     }
422
423     static private final String JavaDoc[] transientPrefixes
424         = {"java.",
425            "javax.",
426            "com.sun.jdo."};
427
428     public int testPCFeasibility()
429     {
430         verbose();
431         verbose("Test feasibility of class: " + className + " ...");
432
433         int status = AFFIRMATIVE;
434
435         final int mods = classClass.getModifiers();
436
437         if (classClass.isPrimitive()) {
438             println("!!! ERROR: specified class is primitive type");
439             status = ERROR;
440         }
441
442         if (classClass.isArray()) {
443             println("!!! ERROR: specified class is array");
444             status = ERROR;
445         }
446
447         if (classClass.isInterface()) {
448             println("!!! ERROR: specified class is interface");
449             status = ERROR;
450         }
451
452         if (Modifier.isAbstract(mods)) {
453             println("!!! ERROR: specified class is abstract");
454             status = ERROR;
455         }
456
457         if (!Modifier.isPublic(mods)) {
458             println("!!! ERROR: specified class is not public");
459             status = ERROR;
460         }
461
462         //if (classClass.getDeclaringClass() != null
463
// && !isStatic(classClass.getModifiers())) {
464
if (classClass.getDeclaringClass() != null) {
465             println("!!! ERROR: specified class is inner class");
466             status = ERROR;
467         }
468
469         if (Throwable JavaDoc.class.isAssignableFrom(classClass)) {
470             println("!!! ERROR: specified class extends Throwable");
471             status = ERROR;
472         }
473
474         // check for transient package prefixes
475
// precludes SCO types from lang.*, math.*, util.*, sql.*
476
for (int i = 0; i < transientPrefixes.length; i++) {
477             final String JavaDoc typePrefix = transientPrefixes[i];
478             if (className.startsWith(typePrefix)) {
479                 println("!!! ERROR: specified class starts with package prefix: "
480                       + typePrefix);
481                 status = ERROR;
482             }
483         }
484
485         //verbose("get superclass ...");
486
final Class JavaDoc superClass = classClass.getSuperclass();
487         if (superClass == null) {
488             println("!!! ERROR: specified class doesn't have super class");
489             status = ERROR;
490         } else {
491             try {
492                 //verbose("get superclass' default constructor ...");
493
final Class JavaDoc[] params = new Class JavaDoc[]{};
494                 Constructor sctor = superClass.getConstructor(params);
495             } catch (NoSuchMethodException JavaDoc ex) {
496                 println("!!! ERROR: super class '" + superClass.getName()
497                       + "' doesn't provide default constructor");
498                 status = ERROR;
499             }
500         }
501
502         verbose(status == AFFIRMATIVE
503                 ? "+++ is feasible for persistence-capability"
504                 : "!!! not feasible for persistence-capability");
505         return status;
506     }
507
508     public int testJdoConstructor()
509     {
510         verbose();
511         verbose("Test JDO constructor ...");
512         affirm(classClass);
513
514         try {
515             //verbose("get jdo constructor ...");
516
final Class JavaDoc[] params = new Class JavaDoc[]{StateManager.class};
517             final Constructor ctor = classClass.getConstructor(params);
518
519             //verbose("create new instance by jdo constructor ...");
520
final Object JavaDoc[] args = new Object JavaDoc[]{null};
521             final Object JavaDoc instance = ctor.newInstance(args);
522
523             //verbose("cast instance to PersistenceCapable ...");
524
PersistenceCapable pc = (PersistenceCapable)instance;
525
526             //verbose("check jdoStateManager ...");
527
if (pc.jdoGetStateManager() != null) {
528                 println("!!! ERROR: invokation of JDO constructor:");
529                 println(" pc.jdoStateManager != null");
530                 println("!!! failed testing JDO constructor");
531                 return ERROR;
532             }
533
534             //verbose("check jdoFlags ...");
535
if (pc.jdoGetFlags() != 1) {
536                 println("!!! ERROR: invokation of JDO constructor:");
537                 println(" pc.jdoFlags != 0");
538                 println("!!! failed testing JDO constructor");
539                 return ERROR;
540             }
541         } catch (NoSuchMethodException JavaDoc ex) {
542             println("!!! ERROR: no JDO constructor");
543             println("!!! failed testing JDO constructor");
544             return ERROR;
545         } catch (InstantiationException JavaDoc ex) {
546             println("!!! ERROR: invokation of JDO constructor:");
547             println(" exception: " + ex);
548             println("!!! failed testing JDO constructor");
549             return ERROR;
550         } catch (IllegalAccessException JavaDoc ex) {
551             println("!!! ERROR: invokation of JDO constructor:");
552             println(" exception: " + ex);
553             println("!!! failed testing JDO constructor");
554             return ERROR;
555         } catch (InvocationTargetException ex) {
556             println("!!! ERROR: invokation of JDO constructor:");
557             println(" exception: " + ex);
558             println(" nested: " + ex.getTargetException());
559             println("!!! failed testing JDO constructor");
560             return ERROR;
561         }
562
563         verbose("+++ tested JDO constructor");
564         return AFFIRMATIVE;
565     }
566
567     public int test(String JavaDoc className)
568     {
569         affirm(className);
570         this.className = className;
571
572         verbose();
573         verbose("-------------------------------------------------------------------------------");
574         verbose();
575         verbose("Test class for augmentation: "
576                 + className + " ...");
577
578         if (testLoadingClass() < AFFIRMATIVE) {
579             return ERROR;
580         }
581
582         final int r0 = hasGenericAugmentation();
583         final int r1 = hasSpecificAugmentation();
584
585         if (r1 < NEGATIVE || r0 < NEGATIVE) {
586             return ERROR;
587         }
588         affirm(r1 >= NEGATIVE && r0 >= NEGATIVE);
589
590         if (r1 == NEGATIVE && r0 == NEGATIVE) {
591             if (requirePC) {
592                 println();
593                 println("!!! ERROR: class not augmented: " + className);
594                 return ERROR;
595             }
596
597             println();
598             println("--- not augmented: " + className);
599             return NEGATIVE;
600         }
601
602         if (r0 == NEGATIVE) {
603             println();
604             println("!!! ERROR: class lacking \"generic\" augmentation: "
605                     + className);
606             return ERROR;
607         }
608
609         if (r1 == NEGATIVE) {
610             println();
611             println("!!! ERROR: class lacking \"class-specific\" augmentation: "
612                     + className);
613             return ERROR;
614         }
615         affirm(r1 > NEGATIVE && r0 > NEGATIVE);
616
617         final int r2 = testPCFeasibility();
618         if (r2 < AFFIRMATIVE) {
619             return ERROR;
620         }
621
622         final int r3 = testJdoConstructor();
623         if (r3 < AFFIRMATIVE) {
624             return ERROR;
625         }
626
627         println();
628         println("+++ augmented: " + className);
629         return AFFIRMATIVE;
630     }
631
632     public int test(boolean verbose,
633                     boolean requirePC,
634                     List JavaDoc classes)
635     {
636         affirm(classes);
637         this.verbose = verbose;
638         this.requirePC = requirePC;
639
640         final int all = classes.size();
641
642         println();
643         println("AugmentationTest: Testing classes for being enhanced for persistence-capability");
644
645         int failed = 0;
646         for (int i = 0; i < all; i++) {
647             if (test((String JavaDoc)classes.get(i)) < NEGATIVE) {
648                 failed++;
649             }
650         }
651         final int passed = all - failed;
652
653         println();
654         println("AugmentationTest: Summary: TESTED: " + all
655                 + " PASSED: " + passed
656                 + " FAILED: " + failed);
657         return failed;
658     }
659
660
661     /**
662      * Prints usage message.
663      */

664     static void usage()
665     {
666         out.println();
667         out.println("Usage: AugmentationTest <options> <classes>...");
668         out.println();
669         out.println("This class tests if classes have been correctly enhanced");
670         out.println("for persistence-capability (\"augmented\").");
671         out.println();
672         out.println("Options include:");
673         out.println(" -h, --help print usage");
674         out.println(" -v, --verbose enable verbose output");
675         out.println(" -pc, --requirePC require all classes to be augmented");
676         out.println();
677         out.println("A non-zero value is returned in case of any errors.");
678         out.println();
679     }
680
681     static public void main(String JavaDoc[] argv)
682     {
683         // parse args
684
boolean verbose = false;
685         boolean requirePC = false;
686         List JavaDoc classes = new ArrayList JavaDoc();
687         for (int i = 0; i < argv.length; i++) {
688             String JavaDoc arg = argv[i];
689             if (arg.equals("-h") || arg.equals("--help")) {
690                 usage();
691                 return;
692             }
693             if (arg.equals("-v") || arg.equals("--verbose")) {
694                 verbose = true;
695                 continue;
696             }
697             if (arg.equals("-pc") || arg.equals("--requirePC")) {
698                 requirePC = true;
699                 continue;
700             }
701             if (arg.equals("--debug")) {
702                 debug = true;
703                 continue;
704             }
705             if (arg.startsWith("-")) {
706                 out.println();
707                 out.println("Unrecognized option: " + arg);
708                 usage();
709                 return;
710             }
711             classes.add(arg);
712         }
713
714         // check arguments
715
if (classes.isEmpty()) {
716             out.println();
717             out.println("Missing classes argument");
718             usage();
719             return;
720         }
721
722         if (debug) {
723             out.println("options:");
724             out.println(" verbose = " + verbose);
725             out.println(" requirePC = " + requirePC);
726             out.print(" classes =");
727             for (int i = 0; i < classes.size(); i++)
728                 out.print(" " + classes.get(i));
729             out.println();
730         }
731
732         final AugmentationTest test = new AugmentationTest();
733         final int r = test.test(verbose, requirePC, classes);
734         System.exit(r);
735     }
736 }
737
Popular Tags