Source Code Cross Referenced for JGrep.java in  » Scripting » jacl » org » codehaus » janino » tools » 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 » Scripting » jacl » org.codehaus.janino.tools 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Janino - An embedded Java[TM] compiler
003:         *
004:         * Copyright (c) 2006, Arno Unkrig
005:         * All rights reserved.
006:         *
007:         * Redistribution and use in source and binary forms, with or without
008:         * modification, are permitted provided that the following conditions
009:         * are met:
010:         *
011:         *    1. Redistributions of source code must retain the above copyright
012:         *       notice, this list of conditions and the following disclaimer.
013:         *    2. Redistributions in binary form must reproduce the above
014:         *       copyright notice, this list of conditions and the following
015:         *       disclaimer in the documentation and/or other materials
016:         *       provided with the distribution.
017:         *    3. The name of the author may not be used to endorse or promote
018:         *       products derived from this software without specific prior
019:         *       written permission.
020:         *
021:         * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
022:         * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
023:         * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
024:         * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
025:         * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
026:         * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
027:         * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
028:         * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
029:         * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
030:         * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
031:         * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
032:         */
033:
034:        package org.codehaus.janino.tools;
035:
036:        import java.util.List;
037:        import java.util.ArrayList;
038:        import java.util.Iterator;
039:
040:        import java.io.*;
041:
042:        import org.codehaus.janino.*;
043:        import org.codehaus.janino.util.*;
044:        import org.codehaus.janino.util.enumerator.*;
045:        import org.codehaus.janino.util.iterator.*;
046:        import org.codehaus.janino.util.resource.*;
047:
048:        /**
049:         * Reads a set of compilation units from the file system and searches it for specific
050:         * Java<sup>TM</sup> constructs, e.g. invocations of a particular method.
051:         *
052:         * Usage:
053:         * <pre>
054:         * java org.codehaus.janino.JGrep \
055:         *           [ -dirs <i>directory-name-patterns</i> ] \
056:         *           [ -files <i>file-name-patterns</i> ] \
057:         *           { <i>directory-path</i> } \
058:         *           -method-invocation <i>class.method(arg-types)</i>
059:         * java org.codehaus.janino.JGrep -help
060:         * </pre>
061:         * 
062:         * If "-dirs" is not given, then all <i>directory-path</i>es are scanned for files.
063:         * The <i>directory-name-patterns</i> work as described in
064:         * {@link org.codehaus.janino.util.StringPattern#parseCombinedPattern(String)}.
065:         * <p>
066:         * If "-files" is not given, then all files ending in ".java" are read. The
067:         * <i>file-name-patterns</i> work as described in
068:         * {@link org.codehaus.janino.util.StringPattern#parseCombinedPattern(String)}.
069:         */
070:        public class JGrep {
071:            private static final boolean DEBUG = false;
072:            private List parsedCompilationUnits = new ArrayList(); // UnitCompiler
073:
074:            /**
075:             * Command line interface.
076:             */
077:            public static void main(String[] args) {
078:                int idx = 0;
079:
080:                StringPattern[] directoryNamePatterns = StringPattern.PATTERNS_ALL;
081:                StringPattern[] fileNamePatterns = new StringPattern[] { new StringPattern(
082:                        "*.java") };
083:                File[] classPath = new File[] { new File(".") };
084:                File[] optionalExtDirs = null;
085:                File[] optionalBootClassPath = null;
086:                String optionalCharacterEncoding = null;
087:                boolean verbose = false;
088:
089:                for (; idx < args.length; ++idx) {
090:                    String arg = args[idx];
091:                    if (arg.charAt(0) != '-')
092:                        break;
093:                    if (arg.equals("-dirs")) {
094:                        directoryNamePatterns = StringPattern
095:                                .parseCombinedPattern(args[++idx]);
096:                    } else if (arg.equals("-files")) {
097:                        fileNamePatterns = StringPattern
098:                                .parseCombinedPattern(args[++idx]);
099:                    } else if (arg.equals("-classpath")) {
100:                        classPath = PathResourceFinder.parsePath(args[++idx]);
101:                    } else if (arg.equals("-extdirs")) {
102:                        optionalExtDirs = PathResourceFinder
103:                                .parsePath(args[++idx]);
104:                    } else if (arg.equals("-bootclasspath")) {
105:                        optionalBootClassPath = PathResourceFinder
106:                                .parsePath(args[++idx]);
107:                    } else if (arg.equals("-encoding")) {
108:                        optionalCharacterEncoding = args[++idx];
109:                    } else if (arg.equals("-verbose")) {
110:                        verbose = true;
111:                    } else if (arg.equals("-help")) {
112:                        for (int j = 0; j < JGrep.USAGE.length; ++j)
113:                            System.out.println(JGrep.USAGE[j]);
114:                        System.exit(1);
115:                    } else {
116:                        System.err
117:                                .println("Unexpected command-line argument \""
118:                                        + arg + "\", try \"-help\".");
119:                        System.exit(1);
120:                        /* NEVER REACHED */return;
121:                    }
122:                }
123:
124:                // { directory-path }
125:                File[] rootDirectories;
126:                {
127:                    int first = idx;
128:                    for (; idx < args.length && args[idx].charAt(0) != '-'; ++idx)
129:                        ;
130:                    if (idx == first) {
131:                        System.err
132:                                .println("No <directory-path>es given, try \"-help\".");
133:                        System.exit(1);
134:                        /* NEVER REACHED */return;
135:                    }
136:                    rootDirectories = new File[idx - first];
137:                    for (int i = first; i < idx; ++i)
138:                        rootDirectories[i - first] = new File(args[i]);
139:                }
140:
141:                // Create the JGrep object.
142:                final JGrep jGrep = new JGrep(classPath, optionalExtDirs,
143:                        optionalBootClassPath, optionalCharacterEncoding,
144:                        verbose);
145:
146:                List mits = new ArrayList();
147:                for (; idx < args.length; ++idx) {
148:                    String arg = args[idx];
149:                    if (arg.equals("-method-invocation")) {
150:                        MethodInvocationTarget mit;
151:                        try {
152:                            mit = JGrep
153:                                    .parseMethodInvocationPattern(args[++idx]);
154:                        } catch (Exception ex) {
155:                            System.err
156:                                    .println("Parsing method invocation pattern \""
157:                                            + args[idx]
158:                                            + "\": "
159:                                            + ex.getMessage());
160:                            System.exit(1);
161:                            /* NEVER REACHED */return;
162:                        }
163:                        while (idx < args.length - 1) {
164:                            arg = args[idx + 1];
165:                            if (arg.startsWith("predicate:")) {
166:                                String predicateExpression = arg.substring(10);
167:                                try {
168:                                    mit.predicates
169:                                            .add(ExpressionEvaluator
170:                                                    .createFastExpressionEvaluator(
171:                                                            new Scanner(
172:                                                                    null,
173:                                                                    new StringReader(
174:                                                                            predicateExpression)), // expression
175:                                                            JGrep.class
176:                                                                    .getName()
177:                                                                    + "PE", // className
178:                                                            null, // optionalExtendedType
179:                                                            MethodInvocationPredicate.class, // interfaceToImplement
180:                                                            new String[] {
181:                                                                    "uc",
182:                                                                    "invocation",
183:                                                                    "method" }, // parameterNames
184:                                                            null // optionalClassLoader
185:                                                    ));
186:                                } catch (Exception ex) {
187:                                    System.err
188:                                            .println("Compiling predicate expression \""
189:                                                    + predicateExpression
190:                                                    + "\": " + ex.getMessage());
191:                                    System.exit(1);
192:                                    /* NEVER REACHED */return;
193:                                }
194:                            } else if (arg.startsWith("action:")) {
195:                                String action = arg.substring(7);
196:                                try {
197:                                    mit.actions.add(Action
198:                                            .getMethodInvocationAction(action));
199:                                } catch (Exception ex) {
200:                                    System.err
201:                                            .println("Compiling method invocation action \""
202:                                                    + action
203:                                                    + "\": "
204:                                                    + ex.getMessage());
205:                                    System.exit(1);
206:                                    /* NEVER REACHED */return;
207:                                }
208:                            } else {
209:                                break;
210:                            }
211:                            ++idx;
212:                        }
213:                        mits.add(mit);
214:                    } else {
215:                        System.err
216:                                .println("Unexpected command-line argument \""
217:                                        + arg + "\", try \"-help\".");
218:                        System.exit(1);
219:                        /* NEVER REACHED */return;
220:                    }
221:                }
222:
223:                // JGrep the root directories.
224:                try {
225:                    jGrep.jGrep(rootDirectories, directoryNamePatterns,
226:                            fileNamePatterns, mits // methodInvocationTargets
227:                            );
228:                } catch (Exception e) {
229:                    System.err.println(e.toString());
230:                    System.exit(1);
231:                }
232:            }
233:
234:            private static final class Action extends Enumerator {
235:                public static final Action PRINT_LOCATION_AND_MATCH = new Action(
236:                        "print-location-and-match");
237:                public static final Action PRINT_LOCATION = new Action(
238:                        "print-location");
239:
240:                private Action(String name) {
241:                    super (name);
242:                }
243:
244:                public static Action fromString(String name)
245:                        throws EnumeratorFormatException {
246:                    return (Action) Enumerator.fromString(name, Action.class);
247:                }
248:
249:                static MethodInvocationAction getMethodInvocationAction(
250:                        String action) throws CompileException,
251:                        Parser.ParseException, Scanner.ScanException {
252:                    if ("print-location-and-match".equals(action)) {
253:                        return new MethodInvocationAction() {
254:                            public void execute(UnitCompiler uc,
255:                                    Java.Invocation invocation,
256:                                    IClass.IMethod method) {
257:                                System.out.println(invocation.getLocation()
258:                                        + ": " + method);
259:                            }
260:                        };
261:                    } else if ("print-location".equals(action)) {
262:                        return new MethodInvocationAction() {
263:                            public void execute(UnitCompiler uc,
264:                                    Java.Invocation invocation,
265:                                    IClass.IMethod method) {
266:                                System.out.println(invocation.getLocation());
267:                            }
268:                        };
269:                    } else {
270:                        return (MethodInvocationAction) ScriptEvaluator
271:                                .createFastScriptEvaluator(action, // script
272:                                        MethodInvocationAction.class, // interfaceToImplement
273:                                        new String[] { "uc", "invocation",
274:                                                "method" } // parameterNames
275:                                );
276:                    }
277:                }
278:            }
279:
280:            private static MethodInvocationTarget parseMethodInvocationPattern(
281:                    String mip) throws Scanner.ScanException, IOException,
282:                    Parser.ParseException {
283:                MethodInvocationTarget mit = new MethodInvocationTarget();
284:                Scanner scanner = new Scanner(null, new StringReader(mip));
285:                Parser parser = new Parser(scanner);
286:
287:                for (;;) {
288:                    String s = JGrep.readIdentifierPattern(parser);
289:                    if (parser.peekOperator("(")) {
290:                        mit.methodNamePattern = s;
291:                        parser.eatToken();
292:                        List l = new ArrayList();
293:                        if (!parser.peekOperator(")")) {
294:                            for (;;) {
295:                                l.add(JGrep.readIdentifierPattern(parser));
296:                                if (parser.peekOperator(")"))
297:                                    break;
298:                                parser.readOperator(",");
299:                            }
300:                        }
301:                        mit.optionalArgumentTypeNamePatterns = (String[]) l
302:                                .toArray(new String[l.size()]);
303:                        return mit;
304:                    } else if (parser.peekOperator(".")) {
305:                        if (mit.optionalClassNamePattern == null) {
306:                            mit.optionalClassNamePattern = s;
307:                        } else {
308:                            mit.optionalClassNamePattern += '.' + s;
309:                        }
310:                        parser.eatToken();
311:                    } else if (scanner.peek().isEOF()) {
312:                        mit.methodNamePattern = s;
313:                        return mit;
314:                    }
315:                }
316:            }
317:
318:            private static String readIdentifierPattern(Parser p)
319:                    throws Parser.ParseException, Scanner.ScanException,
320:                    IOException {
321:                StringBuffer sb = new StringBuffer();
322:                if (p.peekOperator("*")) {
323:                    sb.append('*');
324:                    p.eatToken();
325:                } else {
326:                    sb.append(p.readIdentifier());
327:                }
328:                for (;;) {
329:                    if (p.peekOperator("*")) {
330:                        sb.append('*');
331:                        p.eatToken();
332:                    } else if (p.peekIdentifier()) {
333:                        sb.append(p.readIdentifier());
334:                    } else {
335:                        return sb.toString();
336:                    }
337:                }
338:            }
339:
340:            private static class MethodInvocationTarget {
341:                String optionalClassNamePattern = null;
342:                String methodNamePattern = null;
343:                String[] optionalArgumentTypeNamePatterns = null;
344:                List predicates = new ArrayList(); // MethodInvocationPredicate
345:                List actions = new ArrayList(); // MethodInvocationAction
346:
347:                void apply(UnitCompiler uc, Java.Invocation invocation,
348:                        IClass.IMethod method) throws CompileException {
349:                    if (this .optionalClassNamePattern != null) {
350:                        if (!typeMatches(this .optionalClassNamePattern,
351:                                Descriptor.toClassName(method
352:                                        .getDeclaringIClass().getDescriptor())))
353:                            return;
354:                    }
355:                    if (!new StringPattern(this .methodNamePattern)
356:                            .matches(method.getName()))
357:                        return;
358:                    IClass[] fpts = method.getParameterTypes();
359:                    if (this .optionalArgumentTypeNamePatterns != null) {
360:                        String[] atnps = this .optionalArgumentTypeNamePatterns;
361:                        if (atnps.length != fpts.length)
362:                            return;
363:                        for (int i = 0; i < atnps.length; ++i) {
364:                            if (!new StringPattern(atnps[i]).matches(Descriptor
365:                                    .toClassName(fpts[i].getDescriptor())))
366:                                ;
367:                        }
368:                    }
369:                    for (Iterator it = this .predicates.iterator(); it.hasNext();) {
370:                        MethodInvocationPredicate mip = (MethodInvocationPredicate) it
371:                                .next();
372:                        try {
373:                            if (!mip.evaluate(uc, invocation, method))
374:                                return;
375:                        } catch (Exception ex) {
376:                            return; // Treat exception as a "false" predicate.
377:                        }
378:                    }
379:                    for (Iterator it = this .actions.iterator(); it.hasNext();) {
380:                        MethodInvocationAction mia = (MethodInvocationAction) it
381:                                .next();
382:                        try {
383:                            mia.execute(uc, invocation, method);
384:                        } catch (Exception ex) {
385:                            ; // Ignore action throwing an exception.
386:                        }
387:                    }
388:                }
389:            }
390:
391:            public interface MethodInvocationPredicate {
392:                boolean evaluate(UnitCompiler uc, Java.Invocation invocation,
393:                        IClass.IMethod method) throws Exception;
394:            }
395:
396:            public interface MethodInvocationAction {
397:                void execute(UnitCompiler uc, Java.Invocation invocation,
398:                        IClass.IMethod method) throws Exception;
399:            }
400:
401:            static boolean typeMatches(String pattern, String typeName) {
402:                return new StringPattern(pattern)
403:                        .matches(pattern.indexOf('.') == -1 ? typeName
404:                                .substring(typeName.lastIndexOf('.') + 1)
405:                                : typeName);
406:            }
407:
408:            private static final String[] USAGE = { "To be written.", // TODO
409:            /*
410:             "Usage:",
411:             "",
412:             "  java org.codehaus.janino.Compiler [ <option> ] ... <source-file> ...",
413:             "",
414:             "Supported <option>s are:",
415:             "  -d <output-dir>           Where to save class files",
416:             "  -sourcepath <dirlist>     Where to look for other source files",
417:             "  -classpath <dirlist>      Where to look for other class files",
418:             "  -extdirs <dirlist>        Where to look for other class files",
419:             "  -bootclasspath <dirlist>  Where to look for other class files",
420:             "  -encoding <encoding>      Encoding of source files, e.g. \"UTF-8\" or \"ISO-8859-1\"",
421:             "  -verbose",
422:             "  -g                        Generate all debugging info",
423:             "  -g:none                   Generate no debugging info",
424:             "  -g:{lines,vars,source}    Generate only some debugging info",
425:             "  -warn:<pattern-list>      Issue certain warnings; examples:",
426:             "    -warn:*                 Enables all warnings",
427:             "    -warn:IASF              Only warn against implicit access to static fields",
428:             "    -warn:*-IASF            Enables all warnings, except those against implicit",
429:             "                            access to static fields",
430:             "    -warn:*-IA*+IASF        Enables all warnings, except those against implicit",
431:             "                            accesses, but do warn against implicit access to",
432:             "                            static fields",
433:             "  -rebuild                  Compile all source files, even if the class files",
434:             "                            seems up-to-date",
435:             "  -help",
436:             "",
437:             "The default encoding in this environment is \"" + new InputStreamReader(new ByteArrayInputStream(new byte[0])).getEncoding() + "\".",
438:             */
439:
440:            };
441:
442:            private/*final*/IClassLoader iClassLoader;
443:            private/*final*/String optionalCharacterEncoding;
444:            private/*final*/Benchmark benchmark;
445:
446:            public JGrep(File[] classPath, File[] optionalExtDirs,
447:                    File[] optionalBootClassPath,
448:                    String optionalCharacterEncoding, boolean verbose) {
449:                this (JGrep.createJavacLikePathIClassLoader( // iClassLoader
450:                        optionalBootClassPath, optionalExtDirs, classPath),
451:                        optionalCharacterEncoding, // optionalCharacterEncoding
452:                        verbose // verbose
453:                );
454:
455:                this .benchmark
456:                        .report("*** JGrep - search Java(TM) source files for specific language constructs");
457:                this .benchmark
458:                        .report("*** For more information visit http://janino.codehaus.org");
459:                this .benchmark.report("Class path", classPath);
460:                this .benchmark.report("Ext dirs", optionalExtDirs);
461:                this .benchmark.report("Boot class path", optionalBootClassPath);
462:                this .benchmark.report("Character encoding",
463:                        optionalCharacterEncoding);
464:            }
465:
466:            public JGrep(IClassLoader iClassLoader,
467:                    final String optionalCharacterEncoding, boolean verbose) {
468:                this .iClassLoader = new JGrepIClassLoader(iClassLoader);
469:                this .optionalCharacterEncoding = optionalCharacterEncoding;
470:                this .benchmark = new Benchmark(verbose);
471:            }
472:
473:            /**
474:             * Create an {@link IClassLoader} that looks for classes in the given "boot class
475:             * path", then in the given "extension directories", and then in the given
476:             * "class path".
477:             * <p>
478:             * The default for the <code>optionalBootClassPath</code> is the path defined in
479:             * the system property "sun.boot.class.path", and the default for the
480:             * <code>optionalExtensionDirs</code> is the path defined in the "java.ext.dirs"
481:             * system property.
482:             */
483:            private static IClassLoader createJavacLikePathIClassLoader(
484:                    final File[] optionalBootClassPath,
485:                    final File[] optionalExtDirs, final File[] classPath) {
486:                ResourceFinder bootClassPathResourceFinder = new PathResourceFinder(
487:                        optionalBootClassPath == null ? PathResourceFinder
488:                                .parsePath(System
489:                                        .getProperty("sun.boot.class.path"))
490:                                : optionalBootClassPath);
491:                ResourceFinder extensionDirectoriesResourceFinder = new JarDirectoriesResourceFinder(
492:                        optionalExtDirs == null ? PathResourceFinder
493:                                .parsePath(System.getProperty("java.ext.dirs"))
494:                                : optionalExtDirs);
495:                ResourceFinder classPathResourceFinder = new PathResourceFinder(
496:                        classPath);
497:
498:                // We can load classes through "ResourceFinderIClassLoader"s, which means
499:                // they are read into "ClassFile" objects, or we can load classes through
500:                // "ClassLoaderIClassLoader"s, which means they are loaded into the JVM.
501:                //
502:                // In my environment, the latter is slightly faster. No figures about
503:                // resource usage yet.
504:                //
505:                // In applications where the generated classes are not loaded into the
506:                // same JVM instance, we should avoid to use the
507:                // ClassLoaderIClassLoader, because that assumes that final fields have
508:                // a constant value, even if not compile-time-constant but only
509:                // initialization-time constant. The classical example is
510:                // "File.separator", which is non-blank final, but not compile-time-
511:                // constant.
512:                if (true) {
513:                    IClassLoader icl;
514:                    icl = new ResourceFinderIClassLoader(
515:                            bootClassPathResourceFinder, null);
516:                    icl = new ResourceFinderIClassLoader(
517:                            extensionDirectoriesResourceFinder, icl);
518:                    icl = new ResourceFinderIClassLoader(
519:                            classPathResourceFinder, icl);
520:                    return icl;
521:                } else {
522:                    ClassLoader cl;
523:
524:                    // This is the only way to instantiate a "bootstrap" class loader, i.e. a class loader
525:                    // that finds the bootstrap classes like "Object", "String" and "Throwable", but not
526:                    // the classes on the JVM's class path.
527:                    cl = new ClassLoader(null) {
528:                    };
529:                    cl = new ResourceFinderClassLoader(
530:                            bootClassPathResourceFinder, cl);
531:                    cl = new ResourceFinderClassLoader(
532:                            extensionDirectoriesResourceFinder, cl);
533:                    cl = new ResourceFinderClassLoader(classPathResourceFinder,
534:                            cl);
535:
536:                    return new ClassLoaderIClassLoader(cl);
537:                }
538:            }
539:
540:            public void jGrep(File[] rootDirectories,
541:                    final StringPattern[] directoryNamePatterns,
542:                    final StringPattern[] fileNamePatterns,
543:                    List methodInvocationTargets // MethodInvocationTarget
544:            ) throws Scanner.ScanException, Parser.ParseException,
545:                    CompileException, IOException {
546:                this .benchmark.report("Root dirs", rootDirectories);
547:                this .benchmark.report("Directory name patterns",
548:                        directoryNamePatterns);
549:                this .benchmark.report("File name patterns", fileNamePatterns);
550:
551:                this .jGrep(DirectoryIterator.traverseDirectories(
552:                        rootDirectories, // rootDirectories
553:                        new FilenameFilter() { // directoryNameFilter
554:                            public boolean accept(File dir, String name) {
555:                                return StringPattern.matches(
556:                                        directoryNamePatterns, name);
557:                            }
558:                        }, new FilenameFilter() { // fileNameFilter
559:                            public boolean accept(File dir, String name) {
560:                                return StringPattern.matches(fileNamePatterns,
561:                                        name);
562:                            }
563:                        }), methodInvocationTargets);
564:            }
565:
566:            public void jGrep(Iterator sourceFilesIterator,
567:                    final List methodInvocationTargets)
568:                    throws Scanner.ScanException, Parser.ParseException,
569:                    CompileException, IOException {
570:
571:                // Parse the given source files.
572:                this .benchmark.beginReporting();
573:                int sourceFileCount = 0;
574:                try {
575:
576:                    // Parse all source files.
577:                    while (sourceFilesIterator.hasNext()) {
578:                        File sourceFile = (File) sourceFilesIterator.next();
579:                        UnitCompiler uc = new UnitCompiler(this 
580:                                .parseCompilationUnit(sourceFile, // sourceFile
581:                                        this .optionalCharacterEncoding // optionalCharacterEncoding
582:                                ), this .iClassLoader);
583:                        this .parsedCompilationUnits.add(uc);
584:                        ++sourceFileCount;
585:                    }
586:                } finally {
587:                    this .benchmark.endReporting("Parsed " + sourceFileCount
588:                            + " source file(s)");
589:                }
590:
591:                // Traverse the parsed compilation units.
592:                this .benchmark.beginReporting();
593:                try {
594:                    for (Iterator it = this .parsedCompilationUnits.iterator(); it
595:                            .hasNext();) {
596:                        final UnitCompiler uc = (UnitCompiler) it.next();
597:                        this .benchmark.beginReporting("Grepping \""
598:                                + uc.compilationUnit.optionalFileName + "\"");
599:                        class UCE extends RuntimeException {
600:                            final CompileException ce;
601:
602:                            UCE(CompileException ce) {
603:                                this .ce = ce;
604:                            }
605:                        }
606:                        try {
607:                            new Traverser() {
608:
609:                                // "method(...)", "x.method(...)"
610:                                public void traverseMethodInvocation(
611:                                        Java.MethodInvocation mi) {
612:                                    try {
613:                                        this .match(mi, uc.findIMethod(mi));
614:                                    } catch (CompileException ex) {
615:                                        throw new UCE(ex);
616:                                    }
617:                                    super .traverseMethodInvocation(mi);
618:                                }
619:
620:                                // "super.method(...)"
621:                                public void traverseSuperclassMethodInvocation(
622:                                        Java.SuperclassMethodInvocation scmi) {
623:                                    try {
624:                                        this .match(scmi, uc.findIMethod(scmi));
625:                                    } catch (CompileException ex) {
626:                                        throw new UCE(ex);
627:                                    }
628:                                    super 
629:                                            .traverseSuperclassMethodInvocation(scmi);
630:                                }
631:
632:                                // new Xyz(...)
633:                                public void traverseNewClassInstance(
634:                                        Java.NewClassInstance nci) {
635:                                    //                        System.out.println(nci.getLocation() + ": " + nci);
636:                                    super .traverseNewClassInstance(nci);
637:                                }
638:
639:                                // new Xyz(...) {}
640:                                public void traverseNewAnonymousClassInstance(
641:                                        Java.NewAnonymousClassInstance naci) {
642:                                    //                        System.out.println(naci.getLocation() + ": " + naci);
643:                                    super 
644:                                            .traverseNewAnonymousClassInstance(naci);
645:                                }
646:
647:                                // Explicit constructor invocation ("this(...)", "super(...)").
648:                                public void traverseConstructorInvocation(
649:                                        Java.ConstructorInvocation ci) {
650:                                    //                        System.out.println(ci.getLocation() + ": " + ci);
651:                                    super .traverseConstructorInvocation(ci);
652:                                }
653:
654:                                private void match(Java.Invocation invocation,
655:                                        IClass.IMethod method)
656:                                        throws CompileException {
657:                                    for (Iterator it2 = methodInvocationTargets
658:                                            .iterator(); it2.hasNext();) {
659:                                        MethodInvocationTarget mit = (MethodInvocationTarget) it2
660:                                                .next();
661:                                        mit.apply(uc, invocation, method);
662:                                    }
663:                                }
664:                            }.traverseCompilationUnit(uc.compilationUnit);
665:                        } catch (UCE uce) {
666:                            throw uce.ce;
667:                        } finally {
668:                            this .benchmark.endReporting();
669:                        }
670:                    }
671:                } finally {
672:                    this .benchmark.endReporting("Traversed " + sourceFileCount
673:                            + " compilation units");
674:                }
675:            }
676:
677:            /**
678:             * Read one compilation unit from a file and parse it.
679:             * <p>
680:             * The <code>inputStream</code> is closed before the method returns.
681:             * @return the parsed compilation unit
682:             */
683:            private Java.CompilationUnit parseCompilationUnit(File sourceFile,
684:                    String optionalCharacterEncoding)
685:                    throws Scanner.ScanException, Parser.ParseException,
686:                    IOException {
687:                InputStream is = new BufferedInputStream(new FileInputStream(
688:                        sourceFile));
689:                try {
690:                    Parser parser = new Parser(
691:                            new Scanner(sourceFile.getPath(), is,
692:                                    optionalCharacterEncoding));
693:
694:                    this .benchmark.beginReporting("Parsing \"" + sourceFile
695:                            + "\"");
696:                    try {
697:                        return parser.parseCompilationUnit();
698:                    } finally {
699:                        this .benchmark.endReporting();
700:                    }
701:                } finally {
702:                    try {
703:                        is.close();
704:                    } catch (IOException ex) {
705:                    }
706:                }
707:            }
708:
709:            /**
710:             * Construct the name of a file that could store the byte code of the class with the given
711:             * name.
712:             * <p>
713:             * If <code>optionalDestinationDirectory</code> is non-null, the returned path is the
714:             * <code>optionalDestinationDirectory</code> plus the package of the class (with dots replaced
715:             * with file separators) plus the class name plus ".class". Example:
716:             * "destdir/pkg1/pkg2/Outer$Inner.class"
717:             * <p>
718:             * If <code>optionalDestinationDirectory</code> is null, the returned path is the
719:             * directory of the <code>sourceFile</code> plus the class name plus ".class". Example:
720:             * "srcdir/Outer$Inner.class"
721:             * @param className E.g. "pkg1.pkg2.Outer$Inner"
722:             * @param sourceFile E.g. "srcdir/Outer.java"
723:             * @param optionalDestinationDirectory E.g. "destdir"
724:             */
725:            public static File getClassFile(String className, File sourceFile,
726:                    File optionalDestinationDirectory) {
727:                if (optionalDestinationDirectory != null) {
728:                    return new File(optionalDestinationDirectory, ClassFile
729:                            .getClassFileResourceName(className));
730:                } else {
731:                    int idx = className.lastIndexOf('.');
732:                    return new File(sourceFile.getParentFile(), ClassFile
733:                            .getClassFileResourceName(className
734:                                    .substring(idx + 1)));
735:                }
736:            }
737:
738:            /**
739:             * A specialized {@link IClassLoader} that loads {@link IClass}es from the following
740:             * sources:
741:             * <ol>
742:             *   <li>An already-parsed compilation unit
743:             *   <li>A class file in the output directory (if existant and younger than source file)
744:             *   <li>A source file in any of the source path directories
745:             *   <li>The parent class loader
746:             * </ol>
747:             * Notice that the {@link JGrepIClassLoader} is an inner class of {@link JGrep} and
748:             * heavily uses {@link JGrep}'s members.
749:             */
750:            private class JGrepIClassLoader extends IClassLoader {
751:
752:                /**
753:                 * @param optionalParentIClassLoader {@link IClassLoader} through which {@link IClass}es are to be loaded
754:                 */
755:                public JGrepIClassLoader(IClassLoader optionalParentIClassLoader) {
756:                    super (optionalParentIClassLoader);
757:                    super .postConstruct();
758:                }
759:
760:                /**
761:                 * @param type field descriptor of the {@IClass} to load, e.g. "Lpkg1/pkg2/Outer$Inner;"
762:                 */
763:                protected IClass findIClass(final String type) {
764:                    if (JGrep.DEBUG)
765:                        System.out.println("type = " + type);
766:
767:                    // Class type.
768:                    String className = Descriptor.toClassName(type); // E.g. "pkg1.pkg2.Outer$Inner"
769:                    if (JGrep.DEBUG)
770:                        System.out.println("2 className = \"" + className
771:                                + "\"");
772:
773:                    // Do not attempt to load classes from package "java".
774:                    if (className.startsWith("java."))
775:                        return null;
776:
777:                    // Check the already-parsed compilation units.
778:                    for (int i = 0; i < JGrep.this .parsedCompilationUnits
779:                            .size(); ++i) {
780:                        UnitCompiler uc = (UnitCompiler) JGrep.this .parsedCompilationUnits
781:                                .get(i);
782:                        IClass res = uc.findClass(className);
783:                        if (res != null) {
784:                            this.defineIClass(res);
785:                            return res;
786:                        }
787:                    }
788:                    return null;
789:                }
790:            }
791:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.