Source Code Cross Referenced for ClassAction.java in  » Test-Coverage » Quilt » org » quilt » cover » stmt » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Test Coverage » Quilt » org.quilt.cover.stmt 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* ClassAction.java */
002:        package org.quilt.cover.stmt;
003:
004:        import java.util.List;
005:        import java.util.Vector;
006:
007:        import org.apache.bcel.classfile.Field;
008:        import org.apache.bcel.classfile.Method;
009:        import org.apache.bcel.generic.*;
010:        import org.quilt.cl.ClassTransformer;
011:        import org.quilt.cl.CodeVertex;
012:        import org.apache.bcel.Constants;
013:
014:        /**
015:         * Add instrumentation at the class level, creating <clinit>
016:         * if necessary.  Three fields are added and initialized:
017:         * <ul>
018:         * <li><b>q$$q</b>, the int[] hit counts array
019:         * <li><b>q$$qID</b>, a class identifier unique within this run
020:         * <li><b>q$$qStmtReg</b>, reference to the StmtRegistry
021:         * <li><b>q$$qVer</b>, a Quilt class file format version
022:         * </ul>
023:         *
024:         * All of these fields are <em>public final static</em>.  They are
025:         * initialized by <code>clinit</code> when the class is loaded,
026:         * running bytecode inserted by Quilt.
027:         *
028:         * @author <a href="mailto:jddixon@users.sourceforge.net">Jim Dixon</a>
029:         */
030:
031:        public class ClassAction implements  org.quilt.cl.ClassXformer {
032:
033:            // XFORMER VARIABLES ////////////////////////////////////////////
034:            /** Name of the processor for use in reports. */
035:            private static String name_ = null;
036:
037:            /** The ClassTransformer that invoked this Xformer */
038:            private ClassTransformer classTrans;
039:
040:            /** The ClassGen we are working on. */
041:            private ClassGen clazz_;
042:
043:            /** its name */
044:            private String className;
045:
046:            /** the class name prefixed with "class$" XXX UNNECESSARY */
047:            private String prefixedClassName;
048:
049:            /** Its constant pool */
050:            private ConstantPoolGen cpGen_;
051:
052:            /** */
053:            private InstructionFactory factory;
054:
055:            /** Does a static initializer class exist? */
056:            boolean clinitExists = false;
057:
058:            /** Its index in the method array. */
059:            int clinitIndex = -1;
060:
061:            // COVERAGE-RELATED VARIABLES ///////////////////////////////////
062:            /** Current statement coverage registry */
063:            private static StmtRegistry stmtReg = null;
064:
065:            /** temporary data shared between xformers */
066:            private Ephemera eph;
067:
068:            // CONSTRUCTORS /////////////////////////////////////////////////
069:            public ClassAction() {
070:            }
071:
072:            public ClassAction(StmtRegistry reg) {
073:                stmtReg = reg;
074:                setName(this .getClass().getName()); // default name
075:            }
076:
077:            /**
078:             * Passes a reference to the controlling ClassTransformer.
079:             * XXX Inelegant - and unnecessary.  XXX REWORK TO USED stmtReg
080:             */
081:            public void setClassTransformer(ClassTransformer ct) {
082:                classTrans = ct;
083:            }
084:
085:            // PRE- AND POST-PROCESSING /////////////////////////////////////
086:            /**
087:             * Add a q$$q hit count field to the class using
088:             *   public static int [] q$$q;
089:             * If there is already a field of this name, do not instrument
090:             * the class.
091:             *
092:             * This is a preprocessor applied to the class before looking at
093:             * methods.  Any such preprocessors will be applied in the order of
094:             * the ClassXformer vector.
095:             *
096:             * @param clazz ClassGen for the class being transformed.
097:             */
098:            public void preMethods(ClassGen clazz) {
099:                clazz_ = clazz;
100:                cpGen_ = clazz.getConstantPool();
101:                className = clazz_.getClassName();
102:                // I have tried this with class_ ; still isn't found
103:                prefixedClassName = "class$QIC";
104:                eph = new Ephemera(className);
105:                if (!stmtReg.putEphemera(className, eph)) {
106:                    // XXX should throw exception
107:                    System.out
108:                            .println("ClassAction.preMethods INTERNAL ERRROR - "
109:                                    + " couldn't register ephemeral data");
110:                }
111:                FieldGen field;
112:                if (clazz.containsField("q$$q") != null) {
113:                    System.out.println("ClassAction.preMethods WARNING - "
114:                            + className + " already has q$$q field, aborting");
115:                    classTrans.abort();
116:                } else {
117:                    // ADD:  public static int [] q$$q
118:                    field = new FieldGen(Constants.ACC_PUBLIC
119:                            | Constants.ACC_STATIC, new ArrayType(Type.INT, 1),
120:                            "q$$q", cpGen_);
121:                    clazz.addField(field.getField());
122:                    // ADD: public static int q$$qID
123:                    field = new FieldGen(Constants.ACC_PUBLIC
124:                            | Constants.ACC_STATIC, Type.INT, "q$$qID", cpGen_);
125:                    clazz.addField(field.getField());
126:                    // ADD: public static final org.quilt.cover.stmt.StmtRegistry
127:                    field = new FieldGen(
128:                            Constants.ACC_PUBLIC | Constants.ACC_STATIC
129:                                    | Constants.ACC_FINAL,
130:                            new ObjectType("org.quilt.cover.stmt.StmtRegistry"),
131:                            "q$$qStmtReg", cpGen_);
132:                    clazz.addField(field.getField());
133:
134:                    // ADD: public static int q$$qVer
135:                    field = new FieldGen(Constants.ACC_PUBLIC
136:                            | Constants.ACC_STATIC, Type.INT, "q$$qVer", cpGen_);
137:                    clazz.addField(field.getField());
138:
139:                    // ADD: public static class class$QIC (for QIC.class value)
140:                    field = new FieldGen(Constants.ACC_PUBLIC
141:                            | Constants.ACC_STATIC, new ObjectType(
142:                            "java.lang.Class"), "class$QIC", cpGen_);
143:                    clazz.addField(field.getField());
144:
145:                    // do we have a <clinit> ?
146:                    Method[] m = clazz.getMethods();
147:                    for (int i = 0; i < m.length; i++) {
148:                        if (m[i].getName().equals("<clinit>")) {
149:                            clinitExists = true;
150:                            clinitIndex = i;
151:                            break;
152:                        }
153:                    }
154:                }
155:            }
156:
157:            private void dumpIList(InstructionList ilist, String where) {
158:                if (ilist != null) {
159:                    System.out.println(where + ": instruction list");
160:                    int i = 0;
161:                    for (InstructionHandle ih = ilist.getStart(); ih != null; ih = ih
162:                            .getNext()) {
163:                        System.out.println("  " + (i++) + "  " + ih);
164:                    }
165:                }
166:            }
167:
168:            // the class$ method added by the Java compiler do deal with 
169:            // NAME.class constructs 
170:            // VIRTUALLY IDENTICAL TO BCEL DUMP /////////////////////////////
171:            private void addClass$Method() {
172:                InstructionList il = new InstructionList();
173:                MethodGen method = new MethodGen(Constants.ACC_STATIC,
174:                        new ObjectType("java.lang.Class"),
175:                        new Type[] { Type.STRING }, new String[] { "arg0" },
176:                        "class$", className, il, cpGen_);
177:
178:                // TRY BLOCK
179:                InstructionHandle ih_0 = il.append(factory.createLoad(
180:                        Type.OBJECT, 0));
181:                InstructionHandle ih_1 = il.append(factory.createInvoke(
182:                        "java.lang.Class", "forName", new ObjectType(
183:                                "java.lang.Class"), new Type[] { Type.STRING },
184:                        Constants.INVOKESTATIC));
185:                il.append(factory.createReturn(Type.OBJECT));
186:
187:                // CATCH BLOCK
188:                InstructionHandle ih_5 = il.append(factory.createStore(
189:                        Type.OBJECT, 1));
190:                InstructionHandle ih_6 = il.append(factory
191:                        .createNew("java.lang.NoClassDefFoundError"));
192:                il.append(InstructionConstants.DUP);
193:                il.append(factory.createLoad(Type.OBJECT, 1));
194:                il.append(factory.createInvoke(
195:                        "java.lang.ClassNotFoundException", "getMessage",
196:                        Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
197:                il.append(factory.createInvoke(
198:                        "java.lang.NoClassDefFoundError", "<init>", Type.VOID,
199:                        new Type[] { Type.STRING }, Constants.INVOKESPECIAL));
200:                InstructionHandle ih_17 = il
201:                        .append(InstructionConstants.ATHROW);
202:
203:                // EXCEPTION HANDLERS
204:                method.addExceptionHandler(ih_0, ih_1, ih_5, new ObjectType(
205:                        "java.lang.ClassNotFoundException"));
206:                method.setMaxStack();
207:                method.setMaxLocals();
208:                clazz_.addMethod(method.getMethod());
209:                il.dispose();
210:            } // END class$
211:
212:            /**
213:             * Postprocessor applied to the class after looking at methods.
214:             * These will be applied in reverse order after completion of
215:             * method processing.
216:             */
217:            public void postMethods(ClassGen clazz) {
218:                int counterCount = eph.getCounterCount();
219:                List methodNames = eph.getMethodNames();
220:                List methodEnds = eph.getMethodEnds();
221:                if (clazz != clazz_) {
222:                    // XXX modify to throw exception
223:                    System.out
224:                            .println("ClassAction.postMethods: INTERNAL ERROR:"
225:                                    + " preMethods class different from postMethods");
226:                }
227:                factory = new InstructionFactory(clazz_, cpGen_);
228:                addClass$Method(); // uses factory
229:
230:                MethodGen mg;
231:                InstructionList ilist;
232:                InstructionHandle ih;
233:                if (clinitExists) {
234:                    mg = new MethodGen(clazz_.getMethodAt(clinitIndex),
235:                            className, clazz_.getConstantPool());
236:                    ilist = mg.getInstructionList();
237:                } else {
238:                    ilist = new InstructionList();
239:                    mg = new MethodGen(Constants.ACC_STATIC, Type.VOID,
240:                            Type.NO_ARGS, new String[] {}, "<clinit>",
241:                            className, ilist, clazz_.getConstantPool());
242:                }
243:                // //////////////////////////////////////////////////////////
244:                // q$$q = new int[counterCount];
245:                // //////////////////////////////////////////////////////////
246:
247:                // the first instruction MUST be insert
248:                ih = ilist.insert(new PUSH(cpGen_, counterCount));
249:
250:                // dunno why, but the following produces an array of references; also
251:                //      // the cast should not be necessary, according to the Javadocs,
252:                //      // but there is a compilation error without it
253:                //      ih = ilist.append(ih, (Instruction)factory.createNewArray(
254:                //                              new ArrayType(Type.INT, 1), (short)1));
255:
256:                ih = ilist.append(ih, new NEWARRAY(Type.INT));
257:
258:                ih = ilist.append(ih, factory
259:                        .createFieldAccess(className, "q$$q", new ArrayType(
260:                                Type.INT, 1), Constants.PUTSTATIC));
261:
262:                /////////////////////////////////////////////////////////////
263:                // q$$qVer = 0;
264:                /////////////////////////////////////////////////////////////
265:                ih = ilist.append(ih, new PUSH(cpGen_, 0));
266:                ih = ilist.append(ih, factory.createFieldAccess(className,
267:                        "q$$qVer", Type.INT, Constants.PUTSTATIC));
268:
269:                // //////////////////////////////////////////////////////////
270:                // public final static StmtRegistry q$$qStmtRegistry 
271:                //   = (StmtRegistry)
272:                //       (org.quilt.cl.QuiltClassLoader)QIC.class.getClassLoader())
273:                //           .getRegistry("org.quilt.cover.stmt.StmtRegistry");
274:                // //////////////////////////////////////////////////////////
275:
276:                // GET QIC.class //////////////////////////////////////
277:                ih = ilist.append(ih, new PUSH(cpGen_, "org.quilt.QIC"));
278:                ih = ilist.append(ih, factory.createInvoke(className, "class$",
279:                        new ObjectType("java.lang.Class"),
280:                        new Type[] { Type.STRING }, Constants.INVOKESTATIC));
281:                // this two instructions are unnecessary
282:                ih = ilist.append(ih, InstructionConstants.DUP);
283:                ih = ilist.append(ih, factory.createFieldAccess(className,
284:                        "class$QIC", new ObjectType("java.lang.Class"),
285:                        Constants.PUTSTATIC));
286:
287:                // get the class loader 
288:                ih = ilist.append(ih, factory.createInvoke("java.lang.Class",
289:                        "getClassLoader", new ObjectType(
290:                                "java.lang.ClassLoader"), Type.NO_ARGS,
291:                        Constants.INVOKEVIRTUAL));
292:                // cast to QuiltClassLoader
293:                ih = ilist.append(ih, factory.createCheckCast(new ObjectType(
294:                        "org.quilt.cl.QuiltClassLoader")));
295:                // put method name on stack ...
296:                ih = ilist.append(ih, new PUSH(cpGen_,
297:                        "org.quilt.cover.stmt.StmtRegistry"));
298:                // invoke QuiltClassLoader.getRegistry("org.quilt.cover.stmt.S...")
299:                ih = ilist.append(ih, factory.createInvoke(
300:                        "org.quilt.cl.QuiltClassLoader", "getRegistry",
301:                        new ObjectType("org.quilt.reg.QuiltRegistry"),
302:                        new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL));
303:                // cast to StmtRegistry
304:                ih = ilist.append(ih, factory.createCheckCast(new ObjectType(
305:                        "org.quilt.cover.stmt.StmtRegistry")));
306:                // save to q$$qStmtReg
307:                ih = ilist.append(ih, factory.createFieldAccess(className,
308:                        "q$$qStmtReg", new ObjectType(
309:                                "org.quilt.cover.stmt.StmtRegistry"),
310:                        Constants.PUTSTATIC));
311:
312:                /////////////////////////////////////////////////////////////
313:                // q$$qID = q$$qStmtRegistry.registerCounts(className, q$$q);
314:                /////////////////////////////////////////////////////////////
315:
316:                ih = ilist.append(ih, factory.createFieldAccess(className,
317:                        "q$$qStmtReg", new ObjectType(
318:                                "org.quilt.cover.stmt.StmtRegistry"),
319:                        Constants.GETSTATIC));
320:                ih = ilist.append(ih, new PUSH(cpGen_, className));
321:                ih = ilist.append(ih, factory
322:                        .createFieldAccess(className, "q$$q", new ArrayType(
323:                                Type.INT, 1), Constants.GETSTATIC));
324:                ih = ilist.append(ih, factory.createInvoke(
325:                        "org.quilt.cover.stmt.StmtRegistry", "registerCounts",
326:                        Type.INT, new Type[] { Type.STRING,
327:                                new ArrayType(Type.INT, 1) },
328:                        Constants.INVOKEVIRTUAL));
329:                ih = ilist.append(ih, factory.createFieldAccess(className,
330:                        "q$$qID", Type.INT, Constants.PUTSTATIC));
331:
332:                /////////////////////////////////////////////////////////////
333:                // return;
334:                /////////////////////////////////////////////////////////////
335:                if (!clinitExists) {
336:                    ih = ilist.append(ih, factory.createReturn(Type.VOID));
337:                }
338:                ilist.setPositions();
339:                mg.setMaxStack();
340:                mg.setMaxLocals();
341:
342:                boolean aborting = false;
343:                if (clinitExists) {
344:                    /////////////////////////////////////////////////////////
345:                    // XXX KNOWN PROBLEM: error in setMethod if clinitExists
346:                    // probably because line number table not corrected
347:                    /////////////////////////////////////////////////////////
348:                    // aborting = true;
349:                    // classTrans.abort();
350:                    clazz_.setMethodAt(mg.getMethod(), clinitIndex);
351:                } else {
352:                    clazz_.addMethod(mg.getMethod());
353:                }
354:                // ilist.dispose();     // when things are more stable ;-)
355:
356:                // REGISTER method names and ends ///////////////////////////
357:                if (!aborting) {
358:                    int len = methodNames.size();
359:                    String[] myNames = new String[len];
360:                    int[] myEndCounts = new int[len];
361:
362:                    for (int k = 0; k < len; k++) {
363:                        myNames[k] = (String) methodNames.get(k);
364:                        myEndCounts[k] = ((Integer) methodEnds.get(k))
365:                                .intValue();
366:                    }
367:                    stmtReg.registerMethods(className, myNames, myEndCounts);
368:                } // if not aborting
369:                stmtReg.removeEphemera(className);
370:            }
371:
372:            // OTHER METHODS ////////////////////////////////////////////////
373:            /** Get the preprocessor's report name. */
374:            public String getName() {
375:                return name_;
376:            }
377:
378:            /** Set the preprocessor's name for reports. */
379:            public void setName(String name) {
380:                name_ = name;
381:            }
382:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.