Source Code Cross Referenced for ConstructorCallsOverridableMethodRule.java in  » UML » jrefactory » org » acm » seguin » pmd » rules » 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 » UML » jrefactory » org.acm.seguin.pmd.rules 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  ConstructorCallsOverridableMethodRule.java
0003:         *  dnoyeb@users.sourceforge.net
0004:         *  Created on February 5, 2003, 1:54 PM
0005:         */
0006:        package org.acm.seguin.pmd.rules;
0007:
0008:        import org.acm.seguin.pmd.RuleContext;
0009:        import net.sourceforge.jrefactory.ast.ASTArguments;
0010:        import net.sourceforge.jrefactory.ast.ASTClassDeclaration;
0011:        import net.sourceforge.jrefactory.ast.ASTCompilationUnit;
0012:        import net.sourceforge.jrefactory.ast.ASTConstructorDeclaration;
0013:        import net.sourceforge.jrefactory.ast.ASTExplicitConstructorInvocation;
0014:        import net.sourceforge.jrefactory.ast.ASTInterfaceDeclaration;
0015:        import net.sourceforge.jrefactory.ast.ASTLiteral;
0016:        import net.sourceforge.jrefactory.ast.ASTMethodDeclarator;
0017:        import net.sourceforge.jrefactory.ast.ASTName;
0018:        import net.sourceforge.jrefactory.ast.ASTNestedClassDeclaration;
0019:        import net.sourceforge.jrefactory.ast.ASTNestedInterfaceDeclaration;
0020:        import net.sourceforge.jrefactory.ast.ASTPrimaryExpression;
0021:        import net.sourceforge.jrefactory.ast.ASTPrimaryPrefix;
0022:        import net.sourceforge.jrefactory.ast.ASTPrimarySuffix;
0023:        import net.sourceforge.jrefactory.ast.ASTUnmodifiedClassDeclaration;
0024:        import net.sourceforge.jrefactory.ast.ASTExpression;
0025:        import net.sourceforge.jrefactory.ast.AccessNode;
0026:        import net.sourceforge.jrefactory.ast.Node;
0027:        import net.sourceforge.jrefactory.ast.SimpleNode;
0028:
0029:        import java.util.ArrayList;
0030:        import java.util.Collections;
0031:        import java.util.HashMap;
0032:        import java.util.Iterator;
0033:        import java.util.List;
0034:        import java.util.Map;
0035:        import java.util.Set;
0036:
0037:        /**
0038:         *  Searches through all methods and constructors called from constructors. It marks as dangerous any call to
0039:         *  overridable methods from non-private constructors. It marks as dangerous any calls to dangerous private constructors
0040:         *  from non-private constructors.
0041:         *
0042:         *@author    CL Gilbert (dnoyeb@users.sourceforge.net)
0043:         *@todo      match parameter types. Agressive strips off any package names. Normal compares the names as is.
0044:         *@todo      What about interface declarations which can have internal classes
0045:         */
0046:        public final class ConstructorCallsOverridableMethodRule extends
0047:                org.acm.seguin.pmd.AbstractRule {
0048:
0049:            /**  1 package per class.  */
0050:            private final List evalPackages = new ArrayList();
0051:
0052:            private final static NullEvalPackage nullEvalPackage = new NullEvalPackage();
0053:
0054:            ////////////////////////////////////////////////////////////////////////////////
0055:            ////////////////////////////////////////////////////////////////////////////////
0056:            ////////////////////////////////////////////////////////////////////////////////
0057:            //The Visited Methods
0058:
0059:            /**
0060:             *  Work on each file independently.
0061:             *
0062:             *@param  node  Description of Parameter
0063:             *@param  data  Description of Parameter
0064:             *@return       Description of the Returned Value
0065:             */
0066:            public Object visit(ASTCompilationUnit node, Object data) {
0067:                clearEvalPackages();
0068:                //		try {
0069:                return super .visit(node, data);
0070:                //		}
0071:                //		catch(Exception e){
0072:                //			e.printStackTrace();
0073:                //		}
0074:            }
0075:
0076:            //for testing only
0077:
0078:            //	public Object visit(ASTPackageDeclaration node, Object data){
0079:            //		System.out.println("package= " + ((ASTName)node.jjtGetFirstChild()).getImage());
0080:            //		return super.visit(node,data);
0081:            //	}
0082:
0083:            /**
0084:             *  This check must be evaluated independelty for each class. Inner classses get their own EvalPackage in order to
0085:             *  perform independent evaluation.
0086:             *
0087:             *@param  node  Description of Parameter
0088:             *@param  data  Description of Parameter
0089:             *@return       Description of the Returned Value
0090:             */
0091:            public Object visit(ASTClassDeclaration node, Object data) {
0092:                return visitClassDec(node, data);
0093:            }
0094:
0095:            /**
0096:             *  Description of the Method
0097:             *
0098:             *@param  node  Description of Parameter
0099:             *@param  data  Description of Parameter
0100:             *@return       Description of the Returned Value
0101:             */
0102:            public Object visit(ASTNestedClassDeclaration node, Object data) {
0103:                return visitClassDec(node, data);
0104:            }
0105:
0106:            /**
0107:             *  Description of the Method
0108:             *
0109:             *@param  node  Description of Parameter
0110:             *@param  data  Description of Parameter
0111:             *@return       Description of the Returned Value
0112:             */
0113:            public Object visit(ASTInterfaceDeclaration node, Object data) {
0114:                putEvalPackage(nullEvalPackage);
0115:                Object o = super .visit(node, data);
0116:                //interface may have inner classes, possible? if not just skip whole interface
0117:                removeCurrentEvalPackage();
0118:                return o;
0119:            }
0120:
0121:            /**
0122:             *  Description of the Method
0123:             *
0124:             *@param  node  Description of Parameter
0125:             *@param  data  Description of Parameter
0126:             *@return       Description of the Returned Value
0127:             */
0128:            public Object visit(ASTNestedInterfaceDeclaration node, Object data) {
0129:                putEvalPackage(nullEvalPackage);
0130:                Object o = super .visit(node, data);
0131:                //interface may have inner classes, possible? if not just skip whole interface
0132:                removeCurrentEvalPackage();
0133:                return o;
0134:            }
0135:
0136:            /**
0137:             *  Non-private constructor's methods are added to a list for later safety evaluation. Non-private constructor's
0138:             *  calls on private constructors are added to a list for later safety evaluation. Private constructors are added to
0139:             *  a list so their safety to be called can be later evaluated. Note: We are not checking private constructor's calls
0140:             *  on non-private constructors because all non-private constructors will be evaluated for safety anyway. This means
0141:             *  we wont flag a private constructor as unsafe just because it calls an unsafe public constructor. We want to show
0142:             *  only 1 instance of an error, and this would be 2 instances of the same error.
0143:             *
0144:             *@param  node  Description of Parameter
0145:             *@param  data  Description of Parameter
0146:             *@return       Description of the Returned Value
0147:             *@todo         eliminate the redundency
0148:             */
0149:            public Object visit(ASTConstructorDeclaration node, Object data) {
0150:                if (!(getCurrentEvalPackage() instanceof  NullEvalPackage)) {
0151:                    //only evaluate if we have an eval package for this class
0152:                    List calledMethodsOfConstructor = new ArrayList();
0153:                    ConstructorHolder ch = new ConstructorHolder(node);
0154:                    addCalledMethodsOfNode(node, calledMethodsOfConstructor,
0155:                            getCurrentEvalPackage().m_ClassName);
0156:                    if (!node.isPrivate()) {
0157:                        //these calledMethods are what we will evaluate for being called badly
0158:                        getCurrentEvalPackage().calledMethods
0159:                                .addAll(calledMethodsOfConstructor);
0160:                        //these called private constructors are what we will evaluate for being called badly
0161:                        //we add all constructors invoked by non-private constructors
0162:                        //but we are only interested in the private ones.  We just can't tell the difference here
0163:                        ASTExplicitConstructorInvocation eci = ch
0164:                                .getASTExplicitConstructorInvocation();
0165:                        if (eci != null && "this".equals(eci.getImage())) {
0166:                            //&& eci.isThis()) {
0167:                            getCurrentEvalPackage().calledConstructors.add(ch
0168:                                    .getCalledConstructor());
0169:                        }
0170:                    } else {
0171:                        //add all private constructors to list for later evaluation on if they are safe to call from another constructor
0172:                        //store this constructorHolder for later evaluation
0173:                        getCurrentEvalPackage().allPrivateConstructorsOfClass
0174:                                .put(ch, calledMethodsOfConstructor);
0175:                    }
0176:                }
0177:                return super .visit(node, data);
0178:            }
0179:
0180:            /**
0181:             *  Create a MethodHolder to hold the method. Store the MethodHolder in the Map as the key Store each method called
0182:             *  by the current method as a List in the Map as the Object
0183:             *
0184:             *@param  node  Description of Parameter
0185:             *@param  data  Description of Parameter
0186:             *@return       Description of the Returned Value
0187:             */
0188:            public Object visit(ASTMethodDeclarator node, Object data) {
0189:                if (!(getCurrentEvalPackage() instanceof  NullEvalPackage)) {
0190:                    //only evaluate if we have an eval package for this class
0191:                    AccessNode parent = (AccessNode) node.jjtGetParent();
0192:                    MethodHolder h = new MethodHolder(node);
0193:                    if (!parent.isPrivate() && !parent.isStatic()
0194:                            && !parent.isFinal()) {
0195:                        h.setDangerous(true);
0196:                        //this method is overridable
0197:                    }
0198:                    List l = new ArrayList();
0199:                    addCalledMethodsOfNode((SimpleNode) parent, l,
0200:                            getCurrentEvalPackage().m_ClassName);
0201:                    getCurrentEvalPackage().allMethodsOfClass.put(h, l);
0202:                }
0203:                return super .visit(node, data);
0204:            }
0205:
0206:            //could use java.util.Stack
0207:
0208:            /**
0209:             *  Gets the CurrentEvalPackage attribute of the ConstructorCallsOverridableMethodRule object
0210:             *
0211:             *@return    The CurrentEvalPackage value
0212:             */
0213:            private EvalPackage getCurrentEvalPackage() {
0214:                return (EvalPackage) evalPackages.get(evalPackages.size() - 1);
0215:            }
0216:
0217:            /**
0218:             *  Adds and evaluation package and makes it current
0219:             *
0220:             *@param  ep  Description of Parameter
0221:             */
0222:            private void putEvalPackage(EvalPackage ep) {
0223:                evalPackages.add(ep);
0224:            }
0225:
0226:            /**  Description of the Method */
0227:            private void removeCurrentEvalPackage() {
0228:                evalPackages.remove(evalPackages.size() - 1);
0229:            }
0230:
0231:            /**  Description of the Method */
0232:            private void clearEvalPackages() {
0233:                evalPackages.clear();
0234:            }
0235:
0236:            /**
0237:             *  This check must be evaluated independelty for each class. Inner classses get their own EvalPackage in order to
0238:             *  perform independent evaluation.
0239:             *
0240:             *@param  node  Description of Parameter
0241:             *@param  data  Description of Parameter
0242:             *@return       Description of the Returned Value
0243:             */
0244:            private Object visitClassDec(AccessNode node, Object data) {
0245:                String className = ((ASTUnmodifiedClassDeclaration) node
0246:                        .jjtGetFirstChild()).getImage();
0247:                //	System.out.println("Class is " + className);
0248:                //evaluate each level independently
0249:                if (!node.isFinal() && !node.isStatic()) {
0250:                    putEvalPackage(new EvalPackage(className));
0251:                } else {
0252:                    //System.out.println("NullEvalPackage!");
0253:                    putEvalPackage(nullEvalPackage);
0254:                }
0255:                //store any errors caught from other passes.
0256:                if (node instanceof  ASTClassDeclaration) {
0257:                    super .visit((ASTClassDeclaration) node, data);
0258:                } else {
0259:                    super .visit((ASTNestedClassDeclaration) node, data);
0260:                }
0261:                //skip this class if it has no evaluation package
0262:                if (!(getCurrentEvalPackage() instanceof  NullEvalPackage)) {
0263:                    //evaluate danger of all methods in class
0264:                    while (evaluateDangerOfMethods(getCurrentEvalPackage().allMethodsOfClass) == true) {
0265:                        ;
0266:                    }
0267:                    //evaluate danger of constructors
0268:                    evaluateDangerOfConstructors1(
0269:                            getCurrentEvalPackage().allPrivateConstructorsOfClass,
0270:                            getCurrentEvalPackage().allMethodsOfClass.keySet());
0271:                    while (evaluateDangerOfConstructors2(getCurrentEvalPackage().allPrivateConstructorsOfClass) == true) {
0272:                        ;
0273:                    }
0274:
0275:                    //get each method called on this object from a non-private constructor, if its dangerous flag it
0276:                    for (Iterator it = getCurrentEvalPackage().calledMethods
0277:                            .iterator(); it.hasNext();) {
0278:                        MethodInvocation meth = (MethodInvocation) it.next();
0279:                        //check against each dangerous method in class
0280:                        for (Iterator it2 = getCurrentEvalPackage().allMethodsOfClass
0281:                                .keySet().iterator(); it2.hasNext();) {
0282:                            MethodHolder h = (MethodHolder) it2.next();
0283:                            if (h.isDangerous()) {
0284:                                String methName = h.getASTMethodDeclarator()
0285:                                        .getImage();
0286:                                int count = h.getASTMethodDeclarator()
0287:                                        .getParameterCount();
0288:                                if (meth.getName().equals(methName)
0289:                                        && (meth.getArgumentCount() == count)) {
0290:                                    //bad call
0291:                                    RuleContext ctx = (RuleContext) data;
0292:                                    ctx.getReport().addRuleViolation(
0293:                                            createRuleViolation(ctx, meth
0294:                                                    .getASTPrimaryExpression()
0295:                                                    .getBeginLine()));
0296:                                }
0297:                            }
0298:                        }
0299:                    }
0300:                    //get each unsafe private constructor, and check if its called from any non private constructors
0301:                    for (Iterator privConstIter = getCurrentEvalPackage().allPrivateConstructorsOfClass
0302:                            .keySet().iterator(); privConstIter.hasNext();) {
0303:                        ConstructorHolder ch = (ConstructorHolder) privConstIter
0304:                                .next();
0305:                        if (ch.isDangerous()) {
0306:                            //if its dangerous check if its called from any non-private constructors
0307:                            //System.out.println("visitClassDec Evaluating dangerous constructor with " + ch.getASTConstructorDeclaration().getParameterCount() + " params");
0308:                            int paramCount = ch.getASTConstructorDeclaration()
0309:                                    .getParameterCount();
0310:                            for (Iterator calledConstIter = getCurrentEvalPackage().calledConstructors
0311:                                    .iterator(); calledConstIter.hasNext();) {
0312:                                ConstructorInvocation ci = (ConstructorInvocation) calledConstIter
0313:                                        .next();
0314:                                //System.out.println("called constructor ci.getArgumentCount()="+ci.getArgumentCount());
0315:                                if (ci.getArgumentCount() == paramCount) {
0316:                                    //match name  super / this !?
0317:                                    //System.out.println("adding report");
0318:                                    RuleContext ctx = (RuleContext) data;
0319:                                    ctx
0320:                                            .getReport()
0321:                                            .addRuleViolation(
0322:                                                    createRuleViolation(
0323:                                                            ctx,
0324:                                                            ci
0325:                                                                    .getASTExplicitConstructorInvocation()
0326:                                                                    .getBeginLine()));
0327:                                }
0328:                            }
0329:                        }
0330:                    }
0331:                }
0332:                //finished evaluating this class, move up a level
0333:                removeCurrentEvalPackage();
0334:                return data;
0335:            }
0336:
0337:            /**
0338:             *  Check the methods called on this class by each of the methods on this class. If a method calls an unsafe method,
0339:             *  mark the calling method as unsafe. This changes the list of unsafe methods which necessitates another pass. Keep
0340:             *  passing until you make a clean pass in which no methods are changed to unsafe. For speed it is possible to limit
0341:             *  the number of passes. Impossible to tell type of arguments to method, so forget method matching on types. just
0342:             *  use name and num of arguments. will be some false hits, but oh well.
0343:             *
0344:             *@param  classMethodMap  Description of Parameter
0345:             *@return                 Description of the Returned Value
0346:             *@todo                   investigate limiting the number of passes through config.
0347:             */
0348:            private boolean evaluateDangerOfMethods(Map classMethodMap) {
0349:                //check each method if it calls overridable method
0350:                boolean found = false;
0351:                for (Iterator methodsIter = classMethodMap.keySet().iterator(); methodsIter
0352:                        .hasNext();) {
0353:                    MethodHolder h = (MethodHolder) methodsIter.next();
0354:                    List calledMeths = (List) classMethodMap.get(h);
0355:                    for (Iterator calledMethsIter = calledMeths.iterator(); calledMethsIter
0356:                            .hasNext()
0357:                            && (h.isDangerous() == false);) {
0358:                        //if this method matches one of our dangerous methods, mark it dangerous
0359:                        MethodInvocation meth = (MethodInvocation) calledMethsIter
0360:                                .next();
0361:                        //System.out.println("Called meth is " + meth);
0362:                        for (Iterator innerMethsIter = classMethodMap.keySet()
0363:                                .iterator(); innerMethsIter.hasNext();) {
0364:                            //need to skip self here h == h3
0365:                            MethodHolder h3 = (MethodHolder) innerMethsIter
0366:                                    .next();
0367:                            if (h3.isDangerous()) {
0368:                                String matchMethodName = h3
0369:                                        .getASTMethodDeclarator().getImage();
0370:                                int matchMethodParamCount = h3
0371:                                        .getASTMethodDeclarator()
0372:                                        .getParameterCount();
0373:                                //System.out.println("matchint " + matchMethodName + " to " + meth.getName());
0374:                                if (matchMethodName.equals(meth.getName())
0375:                                        && (matchMethodParamCount == meth
0376:                                                .getArgumentCount())) {
0377:                                    h.setDangerous(true);
0378:                                    found = true;
0379:                                    break;
0380:                                }
0381:                            }
0382:                        }
0383:                    }
0384:                }
0385:                return found;
0386:            }
0387:
0388:            /**
0389:             *  marks constructors dangerous if they call any dangerous methods Requires only a single pass as methods are
0390:             *  already marked
0391:             *
0392:             *@param  classConstructorMap  Description of Parameter
0393:             *@param  evaluatedMethods     Description of Parameter
0394:             *@todo                        optimize by having methods already evaluated somehow!?
0395:             */
0396:            private void evaluateDangerOfConstructors1(Map classConstructorMap,
0397:                    Set evaluatedMethods) {
0398:                //check each constructor in the class
0399:                for (Iterator constIter = classConstructorMap.keySet()
0400:                        .iterator(); constIter.hasNext();) {
0401:                    ConstructorHolder ch = (ConstructorHolder) constIter.next();
0402:                    if (!ch.isDangerous()) {
0403:                        //if its not dangerous then evaluate if it should be
0404:                        //if it calls dangerous method mark it as dangerous
0405:                        List calledMeths = (List) classConstructorMap.get(ch);
0406:                        //check each method it calls
0407:                        for (Iterator calledMethsIter = calledMeths.iterator(); calledMethsIter
0408:                                .hasNext()
0409:                                && !ch.isDangerous();) {
0410:                            //but thee are diff objects which represent same thing but were never evaluated, they need reevaluation
0411:                            MethodInvocation meth = (MethodInvocation) calledMethsIter
0412:                                    .next();
0413:                            //CCE
0414:                            String methName = meth.getName();
0415:                            int methArgCount = meth.getArgumentCount();
0416:                            //check each of the already evaluated methods: need to optimize this out
0417:                            for (Iterator evaldMethsIter = evaluatedMethods
0418:                                    .iterator(); evaldMethsIter.hasNext();) {
0419:                                MethodHolder h = (MethodHolder) evaldMethsIter
0420:                                        .next();
0421:                                if (h.isDangerous()) {
0422:                                    String matchName = h
0423:                                            .getASTMethodDeclarator()
0424:                                            .getImage();
0425:                                    int matchParamCount = h
0426:                                            .getASTMethodDeclarator()
0427:                                            .getParameterCount();
0428:                                    if (methName.equals(matchName)
0429:                                            && (methArgCount == matchParamCount)) {
0430:                                        ch.setDangerous(true);
0431:                                        //System.out.println("evaluateDangerOfConstructors1 setting dangerous constructor with " + ch.getASTConstructorDeclaration().getParameterCount() + " params");
0432:                                        break;
0433:                                    }
0434:                                }
0435:                            }
0436:                        }
0437:                    }
0438:                }
0439:            }
0440:
0441:            /**
0442:             *  Constructor map should contain a key for each private constructor, and maps to a List which contains all called
0443:             *  constructors of that key. marks dangerous if call dangerous private constructor we ignore all non-private
0444:             *  constructors here. That is, the map passed in should not contain any non-private constructors. we return boolean
0445:             *  in order to limit the number of passes through this method but it seems as if we can forgo that and just process
0446:             *  it till its done.
0447:             *
0448:             *@param  classConstructorMap  Description of Parameter
0449:             *@return                      Description of the Returned Value
0450:             */
0451:            private boolean evaluateDangerOfConstructors2(
0452:                    Map classConstructorMap) {
0453:                //System.out.println("evaluateDangerOfConstructors2 map="+classConstructorMap);
0454:                boolean found = false;
0455:                //triggers on danger state change
0456:                //check each constructor in the class
0457:                for (Iterator constIter = classConstructorMap.keySet()
0458:                        .iterator(); constIter.hasNext();) {
0459:                    ConstructorHolder ch = (ConstructorHolder) constIter.next();
0460:                    ConstructorInvocation calledC = ch.getCalledConstructor();
0461:                    if (calledC == null || ch.isDangerous()) {
0462:                        continue;
0463:                    }
0464:                    //if its not dangerous then evaluate if it should be
0465:                    //if it calls dangerous constructor mark it as dangerous
0466:                    int cCount = calledC.getArgumentCount();
0467:                    for (Iterator innerConstIter = classConstructorMap.keySet()
0468:                            .iterator(); innerConstIter.hasNext()
0469:                            && !ch.isDangerous();) {
0470:                        //forget skipping self because that introduces another check for each, but only 1 hit
0471:                        ConstructorHolder h2 = (ConstructorHolder) innerConstIter
0472:                                .next();
0473:                        if (h2.isDangerous()) {
0474:                            int matchConstArgCount = h2
0475:                                    .getASTConstructorDeclaration()
0476:                                    .getParameterCount();
0477:                            if (matchConstArgCount == cCount) {
0478:                                ch.setDangerous(true);
0479:                                found = true;
0480:                                //System.out.println("evaluateDangerOfConstructors2 setting dangerous constructor with " + ch.getASTConstructorDeclaration().getParameterCount() + " params");
0481:                            }
0482:                        }
0483:                    }
0484:                }
0485:                return found;
0486:            }
0487:
0488:            /**
0489:             *  ASTPrimaryPrefix has name in child node of ASTName
0490:             *
0491:             *@param  node  Description of Parameter
0492:             *@return       The NameFromPrefix value
0493:             */
0494:            private static String getNameFromPrefix(ASTPrimaryPrefix node) {
0495:                String name = "";
0496:                //should only be 1 child, if more I need more knowledge
0497:                if (node.jjtGetNumChildren() == 1) {
0498:                    //safety check
0499:                    Node nnode = node.jjtGetFirstChild();
0500:                    if (nnode instanceof  ASTName) {
0501:                        //just as easy as null check and it should be an ASTName anyway
0502:                        name = ((ASTName) nnode).getImage();
0503:                    } else if (nnode instanceof  ASTExpression) {
0504:                        //FIXME? not sure this is correct
0505:                        List expressions = new ArrayList();
0506:                        node.findChildrenOfType(ASTName.class, expressions);
0507:                        if (expressions.size() > 0) {
0508:                            name = ((ASTName) expressions.get(0)).getImage();
0509:                        }
0510:                    }
0511:                }
0512:                return name;
0513:            }
0514:
0515:            /**
0516:             *  ASTPrimarySuffix has name in itself
0517:             *
0518:             *@param  node  Description of Parameter
0519:             *@return       The NameFromSuffix value
0520:             */
0521:            private static String getNameFromSuffix(ASTPrimarySuffix node) {
0522:                return node.getImage();
0523:            }
0524:
0525:            ////////////////////////////////////////////////////////////////////////////////
0526:            ////////////////////////////////////////////////////////////////////////////////
0527:            ////////////////////////////////////////////////////////////////////////////////
0528:            //Helper methods to process visits
0529:
0530:            /**
0531:             *  Adds a feature to the CalledMethodsOfNode attribute of the ConstructorCallsOverridableMethodRule class
0532:             *
0533:             *@param  node           The feature to be added to the CalledMethodsOfNode attribute
0534:             *@param  calledMethods  The feature to be added to the CalledMethodsOfNode attribute
0535:             *@param  className      The feature to be added to the CalledMethodsOfNode attribute
0536:             */
0537:            private static void addCalledMethodsOfNode(AccessNode node,
0538:                    List calledMethods, String className) {
0539:                List expressions = new ArrayList();
0540:                node.findChildrenOfType(ASTPrimaryExpression.class,
0541:                        expressions, false);
0542:                addCalledMethodsOfNodeImpl(expressions, calledMethods,
0543:                        className);
0544:            }
0545:
0546:            /**
0547:             *  Adds all methods called on this instance from within this Node.
0548:             *
0549:             *@param  node           The feature to be added to the CalledMethodsOfNode attribute
0550:             *@param  calledMethods  The feature to be added to the CalledMethodsOfNode attribute
0551:             *@param  className      The feature to be added to the CalledMethodsOfNode attribute
0552:             */
0553:            private static void addCalledMethodsOfNode(SimpleNode node,
0554:                    List calledMethods, String className) {
0555:                List expressions = new ArrayList();
0556:                node
0557:                        .findChildrenOfType(ASTPrimaryExpression.class,
0558:                                expressions);
0559:                addCalledMethodsOfNodeImpl(expressions, calledMethods,
0560:                        className);
0561:            }
0562:
0563:            /**
0564:             *  Adds a feature to the CalledMethodsOfNodeImpl attribute of the ConstructorCallsOverridableMethodRule class
0565:             *
0566:             *@param  expressions    The feature to be added to the CalledMethodsOfNodeImpl attribute
0567:             *@param  calledMethods  The feature to be added to the CalledMethodsOfNodeImpl attribute
0568:             *@param  className      The feature to be added to the CalledMethodsOfNodeImpl attribute
0569:             */
0570:            private static void addCalledMethodsOfNodeImpl(List expressions,
0571:                    List calledMethods, String className) {
0572:                for (Iterator it = expressions.iterator(); it.hasNext();) {
0573:                    ASTPrimaryExpression ape = (ASTPrimaryExpression) it.next();
0574:                    MethodInvocation meth = findMethod(ape, className);
0575:                    if (meth != null) {
0576:                        //System.out.println("Adding call " + methName);
0577:                        calledMethods.add(meth);
0578:                    }
0579:                }
0580:            }
0581:
0582:            /**
0583:             *@param  node       Description of Parameter
0584:             *@param  className  Description of Parameter
0585:             *@return            A method call on the class passed in, or null if no method call is found.
0586:             *@todo              Need a better way to match the class and package name to the actual method being called.
0587:             */
0588:            private static MethodInvocation findMethod(
0589:                    ASTPrimaryExpression node, String className) {
0590:                if (node.jjtGetNumChildren() > 0
0591:                        && node.jjtGetFirstChild().jjtGetNumChildren() > 0
0592:                        && node.jjtGetFirstChild().jjtGetFirstChild() instanceof  ASTLiteral) {
0593:                    return null;
0594:                }
0595:                MethodInvocation meth = MethodInvocation.getMethod(node);
0596:                boolean found = false;
0597:                //		if(meth != null){
0598:                //			meth.show();
0599:                //		}
0600:                if (meth != null) {
0601:                    //if it's a call on a variable, or on its superclass ignore it.
0602:                    if ((meth.getReferenceNames().size() == 0)
0603:                            && !meth.isSuper()) {
0604:                        //if this list does not contain our class name, then its not referencing our class
0605:                        //this is a cheezy test... but it errs on the side of less false hits.
0606:                        List packClass = meth.getQualifierNames();
0607:                        if (packClass.size() > 0) {
0608:                            for (Iterator it = packClass.iterator(); it
0609:                                    .hasNext();) {
0610:                                String name = (String) it.next();
0611:                                if (name.equals(className)) {
0612:                                    found = true;
0613:                                    break;
0614:                                }
0615:                            }
0616:                        } else {
0617:                            found = true;
0618:                        }
0619:                    }
0620:                }
0621:                if (found) {
0622:                    return meth;
0623:                } else {
0624:                    return null;
0625:                }
0626:            }
0627:
0628:            /**
0629:             *  Description of the Class
0630:             *
0631:             *@author    Mike Atkinson
0632:             */
0633:            private final class ConstructorInvocation {
0634:                private ASTExplicitConstructorInvocation m_Eci;
0635:                private String name;
0636:                private int count = 0;
0637:
0638:                /**
0639:                 *  Constructor for the ConstructorInvocation object
0640:                 *
0641:                 *@param  eci  Description of Parameter
0642:                 */
0643:                public ConstructorInvocation(
0644:                        ASTExplicitConstructorInvocation eci) {
0645:                    m_Eci = eci;
0646:                    List l = new ArrayList();
0647:                    eci.findChildrenOfType(ASTArguments.class, l);
0648:                    if (l.size() > 0) {
0649:                        ASTArguments aa = (ASTArguments) l.get(0);
0650:                        count = aa.getArgumentCount();
0651:                    }
0652:                    name = eci.getImage();
0653:                }
0654:
0655:                /**
0656:                 *  Gets the ASTExplicitConstructorInvocation attribute of the ConstructorInvocation object
0657:                 *
0658:                 *@return    The ASTExplicitConstructorInvocation value
0659:                 */
0660:                public ASTExplicitConstructorInvocation getASTExplicitConstructorInvocation() {
0661:                    return m_Eci;
0662:                }
0663:
0664:                /**
0665:                 *  Gets the ArgumentCount attribute of the ConstructorInvocation object
0666:                 *
0667:                 *@return    The ArgumentCount value
0668:                 */
0669:                public int getArgumentCount() {
0670:                    return count;
0671:                }
0672:
0673:                /**
0674:                 *  Gets the Name attribute of the ConstructorInvocation object
0675:                 *
0676:                 *@return    The Name value
0677:                 */
0678:                public String getName() {
0679:                    return name;
0680:                }
0681:            }
0682:
0683:            /**
0684:             *  Description of the Class
0685:             *
0686:             *@author    Mike Atkinson
0687:             */
0688:            private final class MethodHolder {
0689:                private ASTMethodDeclarator m_Amd;
0690:                private boolean m_Dangerous = false;
0691:
0692:                /**
0693:                 *  Constructor for the MethodHolder object
0694:                 *
0695:                 *@param  amd  Description of Parameter
0696:                 */
0697:                public MethodHolder(ASTMethodDeclarator amd) {
0698:                    m_Amd = amd;
0699:                }
0700:
0701:                /**
0702:                 *  Sets the Dangerous attribute of the MethodHolder object
0703:                 *
0704:                 *@param  dangerous  The new Dangerous value
0705:                 */
0706:                public void setDangerous(boolean dangerous) {
0707:                    m_Dangerous = dangerous;
0708:                }
0709:
0710:                /**
0711:                 *  Gets the ASTMethodDeclarator attribute of the MethodHolder object
0712:                 *
0713:                 *@return    The ASTMethodDeclarator value
0714:                 */
0715:                public ASTMethodDeclarator getASTMethodDeclarator() {
0716:                    return m_Amd;
0717:                }
0718:
0719:                /**
0720:                 *  Gets the Dangerous attribute of the MethodHolder object
0721:                 *
0722:                 *@return    The Dangerous value
0723:                 */
0724:                public boolean isDangerous() {
0725:                    return m_Dangerous;
0726:                }
0727:            }
0728:
0729:            /**
0730:             *  Description of the Class
0731:             *
0732:             *@author    Mike Atkinson
0733:             */
0734:            private final class ConstructorHolder {
0735:                private ASTConstructorDeclaration m_Cd;
0736:                private boolean m_Dangerous = false;
0737:                private ConstructorInvocation m_Ci;
0738:                private boolean m_CiInitialized = false;
0739:
0740:                /**
0741:                 *  Constructor for the ConstructorHolder object
0742:                 *
0743:                 *@param  cd  Description of Parameter
0744:                 */
0745:                public ConstructorHolder(ASTConstructorDeclaration cd) {
0746:                    m_Cd = cd;
0747:                }
0748:
0749:                /**
0750:                 *  Sets the Dangerous attribute of the ConstructorHolder object
0751:                 *
0752:                 *@param  dangerous  The new Dangerous value
0753:                 */
0754:                public void setDangerous(boolean dangerous) {
0755:                    m_Dangerous = dangerous;
0756:                }
0757:
0758:                /**
0759:                 *  Gets the ASTConstructorDeclaration attribute of the ConstructorHolder object
0760:                 *
0761:                 *@return    The ASTConstructorDeclaration value
0762:                 */
0763:                public ASTConstructorDeclaration getASTConstructorDeclaration() {
0764:                    return m_Cd;
0765:                }
0766:
0767:                /**
0768:                 *  Gets the CalledConstructor attribute of the ConstructorHolder object
0769:                 *
0770:                 *@return    The CalledConstructor value
0771:                 */
0772:                public ConstructorInvocation getCalledConstructor() {
0773:                    if (m_CiInitialized == false) {
0774:                        initCI();
0775:                    }
0776:                    return m_Ci;
0777:                }
0778:
0779:                /**
0780:                 *  Gets the ASTExplicitConstructorInvocation attribute of the ConstructorHolder object
0781:                 *
0782:                 *@return    The ASTExplicitConstructorInvocation value
0783:                 */
0784:                public ASTExplicitConstructorInvocation getASTExplicitConstructorInvocation() {
0785:                    ASTExplicitConstructorInvocation eci = null;
0786:                    if (m_CiInitialized == false) {
0787:                        initCI();
0788:                    }
0789:                    if (m_Ci != null) {
0790:                        eci = m_Ci.getASTExplicitConstructorInvocation();
0791:                    }
0792:                    return eci;
0793:                }
0794:
0795:                /**
0796:                 *  Gets the Dangerous attribute of the ConstructorHolder object
0797:                 *
0798:                 *@return    The Dangerous value
0799:                 */
0800:                public boolean isDangerous() {
0801:                    return m_Dangerous;
0802:                }
0803:
0804:                /**  Description of the Method */
0805:                private void initCI() {
0806:                    List expressions = new ArrayList();
0807:                    m_Cd
0808:                            .findChildrenOfType(
0809:                                    ASTExplicitConstructorInvocation.class,
0810:                                    expressions);
0811:                    //only 1...
0812:                    if (expressions.size() > 0) {
0813:                        ASTExplicitConstructorInvocation eci = (ASTExplicitConstructorInvocation) expressions
0814:                                .get(0);
0815:                        m_Ci = new ConstructorInvocation(eci);
0816:                        //System.out.println("Const call " + eci.getImage()); //super or this???
0817:                    }
0818:                    m_CiInitialized = true;
0819:                }
0820:            }
0821:
0822:            /**
0823:             *  2: method(); ASTPrimaryPrefix ASTName image = "method" ASTPrimarySuffix *ASTArguments 3: a.method();
0824:             *  ASTPrimaryPrefix -> ASTName image = "a.method" ??? ASTPrimarySuffix -> () ASTArguments 3: this.method();
0825:             *  ASTPrimaryPrefix -> this image=null //MRA image=="this" ASTPrimarySuffix -> method ASTPrimarySuffix -> ()
0826:             *  ASTArguments super.method(); ASTPrimaryPrefix -> image = "method" //MRA ASTPrimaryPrefix -> image =
0827:             *  "super.method" ASTPrimarySuffix -> image = null ASTArguments -> super.a.method(); ASTPrimaryPrefix -> image = "a"
0828:             *  //MRA ASTPrimaryPrefix -> image = "super.a" ASTPrimarySuffix -> image = "method" ASTPrimarySuffix -> image = null
0829:             *  ASTArguments -> 4: this.a.method(); ASTPrimaryPrefix -> image = null ASTPrimarySuffix -> image = "a"
0830:             *  ASTPrimarySuffix -> image = "method" ASTPrimarySuffix -> ASTArguments 4: ClassName.this.method();
0831:             *  ASTPrimaryPrefix ASTName image = "ClassName" ASTPrimarySuffix -> this image=null ASTPrimarySuffix -> image =
0832:             *  "method" ASTPrimarySuffix -> () ASTArguments 5: ClassName.this.a.method(); ASTPrimaryPrefix ASTName image =
0833:             *  "ClassName" ASTPrimarySuffix -> this image=null ASTPrimarySuffix -> image="a" ASTPrimarySuffix -> image="method"
0834:             *  ASTPrimarySuffix -> () ASTArguments 5: Package.ClassName.this.method(); ASTPrimaryPrefix ASTName image
0835:             *  ="Package.ClassName" ASTPrimarySuffix -> this image=null ASTPrimarySuffix -> image="method" ASTPrimarySuffix ->
0836:             *  () ASTArguments 6: Package.ClassName.this.a.method(); ASTPrimaryPrefix ASTName image ="Package.ClassName"
0837:             *  ASTPrimarySuffix -> this image=null ASTPrimarySuffix -> a ASTPrimarySuffix -> method ASTPrimarySuffix -> ()
0838:             *  ASTArguments 5: OuterClass.InnerClass.this.method(); ASTPrimaryPrefix ASTName image = "OuterClass.InnerClass"
0839:             *  ASTPrimarySuffix -> this image=null ASTPrimarySuffix -> method ASTPrimarySuffix -> () ASTArguments 6:
0840:             *  OuterClass.InnerClass.this.a.method(); ASTPrimaryPrefix ASTName image = "OuterClass.InnerClass" ASTPrimarySuffix
0841:             *  -> this image=null ASTPrimarySuffix -> a ASTPrimarySuffix -> method ASTPrimarySuffix -> () ASTArguments
0842:             *  OuterClass.InnerClass.this.a.method().method().method(); ASTPrimaryPrefix ASTName image = "OuterClass.InnerClass"
0843:             *  ASTPrimarySuffix -> this image=null ASTPrimarySuffix -> a image='a' ASTPrimarySuffix -> method image='method'
0844:             *  ASTPrimarySuffix -> () image=null ASTArguments ASTPrimarySuffix -> method image='method' ASTPrimarySuffix -> ()
0845:             *  image=null ASTArguments ASTPrimarySuffix -> method image='method' ASTPrimarySuffix -> () image=null ASTArguments
0846:             *  3..n: Class.InnerClass[0].InnerClass[n].this.method(); ASTPrimaryPrefix ASTName image = "Class[0]..InnerClass[n]"
0847:             *  ASTPrimarySuffix -> image=null ASTPrimarySuffix -> method ASTPrimarySuffix -> () ASTArguments super.aMethod();
0848:             *  ASTPrimaryPrefix -> aMethod ASTPrimarySuffix -> () Evaluate right to left
0849:             *
0850:             *@author    Mike Atkinson
0851:             */
0852:            private static class MethodInvocation {
0853:                private String m_Name;
0854:                private ASTPrimaryExpression m_Ape;
0855:                private List m_ReferenceNames;
0856:                private List m_QualifierNames;
0857:                private int m_ArgumentSize;
0858:                private boolean m_Super;
0859:
0860:                /**
0861:                 *  Constructor for the MethodInvocation object
0862:                 *
0863:                 *@param  ape             Description of Parameter
0864:                 *@param  qualifierNames  Description of Parameter
0865:                 *@param  referenceNames  Description of Parameter
0866:                 *@param  name            Description of Parameter
0867:                 *@param  argumentSize    Description of Parameter
0868:                 *@param  superCall       Description of Parameter
0869:                 */
0870:                private MethodInvocation(ASTPrimaryExpression ape,
0871:                        List qualifierNames, List referenceNames, String name,
0872:                        int argumentSize, boolean super Call) {
0873:                    m_Ape = ape;
0874:                    m_QualifierNames = qualifierNames;
0875:                    m_ReferenceNames = referenceNames;
0876:                    m_Name = name;
0877:                    m_ArgumentSize = argumentSize;
0878:                    m_Super = super Call;
0879:                }
0880:
0881:                /**
0882:                 *  Gets the Super attribute of the MethodInvocation object
0883:                 *
0884:                 *@return    The Super value
0885:                 */
0886:                public boolean isSuper() {
0887:                    return m_Super;
0888:                }
0889:
0890:                /**
0891:                 *  Gets the Name attribute of the MethodInvocation object
0892:                 *
0893:                 *@return    The Name value
0894:                 */
0895:                public String getName() {
0896:                    return m_Name;
0897:                }
0898:
0899:                /**
0900:                 *  Gets the ArgumentCount attribute of the MethodInvocation object
0901:                 *
0902:                 *@return    The ArgumentCount value
0903:                 */
0904:                public int getArgumentCount() {
0905:                    return m_ArgumentSize;
0906:                }
0907:
0908:                /**
0909:                 *  Gets the ReferenceNames attribute of the MethodInvocation object
0910:                 *
0911:                 *@return    The ReferenceNames value
0912:                 */
0913:                public List getReferenceNames() {
0914:                    return m_ReferenceNames;
0915:                    //new ArrayList(variableNames);
0916:                }
0917:
0918:                /**
0919:                 *  Gets the QualifierNames attribute of the MethodInvocation object
0920:                 *
0921:                 *@return    The QualifierNames value
0922:                 */
0923:                public List getQualifierNames() {
0924:                    return m_QualifierNames;
0925:                }
0926:
0927:                /**
0928:                 *  Gets the ASTPrimaryExpression attribute of the MethodInvocation object
0929:                 *
0930:                 *@return    The ASTPrimaryExpression value
0931:                 */
0932:                public ASTPrimaryExpression getASTPrimaryExpression() {
0933:                    return m_Ape;
0934:                }
0935:
0936:                /**  Description of the Method */
0937:                public void show() {
0938:                    System.out.println("<MethodInvocation>");
0939:                    List pkg = getQualifierNames();
0940:                    System.out.println("  <Qualifiers>");
0941:                    for (Iterator it = pkg.iterator(); it.hasNext();) {
0942:                        String name = (String) it.next();
0943:                        System.out.println("    " + name);
0944:                    }
0945:                    System.out.println("  </Qualifiers>");
0946:                    System.out.println("  <Super>" + isSuper() + "</Super>");
0947:                    List vars = getReferenceNames();
0948:                    System.out.println("  <References>");
0949:                    for (Iterator it = vars.iterator(); it.hasNext();) {
0950:                        String name = (String) it.next();
0951:                        System.out.println("    " + name);
0952:                    }
0953:                    System.out.println("  </References>");
0954:                    System.out.println("  <Name>" + getName() + "</Name>");
0955:                    System.out.println("</MethodInvocation>");
0956:                }
0957:
0958:                /**
0959:                 *  Gets the Method attribute of the MethodInvocation class
0960:                 *
0961:                 *@param  node  Description of Parameter
0962:                 *@return       The Method value
0963:                 */
0964:                public static MethodInvocation getMethod(
0965:                        ASTPrimaryExpression node) {
0966:                    MethodInvocation meth = null;
0967:                    int i = node.jjtGetNumChildren();
0968:                    if (i > 1) {
0969:                        //should always be at least 2, probably can eliminate this check
0970:                        //start at end which is guaranteed, work backwards
0971:                        Node lastNode = node.jjtGetChild(i - 1);
0972:                        if ((lastNode.jjtGetNumChildren() == 1)
0973:                                && (lastNode.jjtGetFirstChild() instanceof  ASTArguments)) {
0974:                            //could be ASTExpression for instance 'a[4] = 5';
0975:                            //start putting method together
0976:                            //					System.out.println("Putting method together now");
0977:                            List varNames = new ArrayList();
0978:                            List packagesAndClasses = new ArrayList();
0979:                            //look in JLS for better name here;
0980:                            String methodName = null;
0981:                            ASTArguments args = (ASTArguments) lastNode
0982:                                    .jjtGetFirstChild();
0983:                            int numOfArguments = args.getArgumentCount();
0984:                            boolean super First = false;
0985:                            int this Index = -1;
0986:
0987:                            FIND_SUPER_OR_THIS: {
0988:                                //search all nodes except last for 'this' or 'super'.  will be at: (node 0 | node 1 | nowhere)
0989:                                //this is an ASTPrimarySuffix with a null image and does not have child (which will be of type ASTArguments)
0990:                                //this is an ASTPrimaryPrefix with a null image and an ASTName that has a null image
0991:                                //super is an ASTPrimarySuffix with a null image and does not have child (which will be of type ASTArguments)
0992:                                //super is an ASTPrimaryPrefix with a non-null image
0993:                                for (int x = 0; x < i - 1; x++) {
0994:                                    Node child = node.jjtGetChild(x);
0995:                                    if (child instanceof  ASTPrimarySuffix) {
0996:                                        //check suffix type match
0997:                                        ASTPrimarySuffix child2 = (ASTPrimarySuffix) child;
0998:                                        //								String name = getNameFromSuffix((ASTPrimarySuffix)child);
0999:                                        //								System.out.println("found name suffix of : " + name);
1000:                                        //MRA if (child2.getImage() == null && child2.jjtGetNumChildren() == 0) {
1001:                                        if ("this".equals(child2.getImage())) {
1002:                                            this Index = x;
1003:                                            break;
1004:                                        }
1005:                                        //could be super, could be this.  currently we cant tell difference so we miss super when
1006:                                        //XYZ.ClassName.super.method();
1007:                                        //still works though.
1008:                                    } else if (child instanceof  ASTPrimaryPrefix) {
1009:                                        //check prefix type match
1010:                                        ASTPrimaryPrefix child2 = (ASTPrimaryPrefix) child;
1011:                                        //MRA if (getNameFromPrefix(child2) == null) {
1012:                                        //MRA     if (child2.getImage() == null) {
1013:                                        //MRA         thisIndex = x;
1014:                                        //MRA         break;
1015:                                        //MRA     } else {//happens when super is used [super.method(): image = 'method']
1016:                                        //MRA         superFirst = true;
1017:                                        //MRA         thisIndex = x;
1018:                                        //MRA         //the true super is at an unusable index because super.method() has only 2 nodes [method=0,()=1]
1019:                                        //MRA         //as opposed to the 3 you might expect and which this.method() actually has. [this=0,method=1.()=2]
1020:                                        //MRA         break;
1021:                                        //MRA     }
1022:                                        //MRA }
1023:                                        if ("this".equals(child2)) {
1024:                                            this Index = x;
1025:                                            break;
1026:                                        } else if (child2.getImage() != null
1027:                                                && child2.getImage()
1028:                                                        .startsWith("super.")) {
1029:                                            super First = true;
1030:                                            this Index = x;
1031:                                            break;
1032:                                            //the true super is at an unusable index because super.method() has only 2 nodes [method=0,()=1]
1033:                                            //as opposed to the 3 you might expect and which this.method() actually has. [this=0,method=1.()=2]
1034:                                        }
1035:                                    }
1036:                                    //							else{
1037:                                    //								System.err.println("Bad Format error"); //throw exception, quit evaluating this compilation node
1038:                                    //							}
1039:                                }
1040:                            }
1041:
1042:                            if (this Index != -1) {
1043:                                //						System.out.println("Found this or super: " + thisIndex);
1044:                                //Hack that must be removed if and when the patters of super.method() begins to logically match the rest of the patterns !!!
1045:                                if (super First) {
1046:                                    //this is when super is the first node of statement.  no qualifiers, all variables or method
1047:                                    //							System.out.println("super first");
1048:                                    FIRSTNODE: {
1049:                                        ASTPrimaryPrefix child = (ASTPrimaryPrefix) node
1050:                                                .jjtGetFirstChild();
1051:                                        String name = child.getImage();
1052:                                        //special case
1053:                                        if (i == 2) {
1054:                                            //last named node = method name
1055:                                            methodName = name;
1056:                                        } else {
1057:                                            //not the last named node so its only var name
1058:                                            varNames.add(name);
1059:                                        }
1060:                                    }
1061:                                    OTHERNODES: {
1062:                                        //variables
1063:                                        for (int x = 1; x < i - 1; x++) {
1064:                                            Node child = node.jjtGetChild(x);
1065:                                            ASTPrimarySuffix ps = (ASTPrimarySuffix) child;
1066:                                            if (ps.isArguments() == false) {
1067:                                                String name = ((ASTPrimarySuffix) child)
1068:                                                        .getImage();
1069:                                                if (x == i - 2) {
1070:                                                    //last node
1071:                                                    methodName = name;
1072:                                                } else {
1073:                                                    //not the last named node so its only var name
1074:                                                    varNames.add(name);
1075:                                                }
1076:                                            }
1077:                                        }
1078:                                    }
1079:                                } else {
1080:                                    //not super call
1081:                                    FIRSTNODE: {
1082:                                        if (this Index == 1) {
1083:                                            //qualifiers in node 0
1084:                                            ASTPrimaryPrefix child = (ASTPrimaryPrefix) node
1085:                                                    .jjtGetFirstChild();
1086:                                            String toParse = getNameFromPrefix(child);
1087:                                            //									System.out.println("parsing for class/package names in : " + toParse);
1088:                                            java.util.StringTokenizer st = new java.util.StringTokenizer(
1089:                                                    toParse, ".");
1090:                                            while (st.hasMoreTokens()) {
1091:                                                packagesAndClasses.add(st
1092:                                                        .nextToken());
1093:                                            }
1094:                                        }
1095:                                    }
1096:                                    OTHERNODES: {
1097:                                        //other methods called in this statement are grabbed here
1098:                                        //this is at 0, then no Qualifiers
1099:                                        //this is at 1, the node 0 contains qualifiers
1100:                                        for (int x = this Index + 1; x < i - 1; x++) {
1101:                                            //everything after this is var name or method name
1102:                                            ASTPrimarySuffix child = (ASTPrimarySuffix) node
1103:                                                    .jjtGetChild(x);
1104:                                            if (child.isArguments() == false) {
1105:                                                //skip the () of method calls
1106:                                                String name = getNameFromSuffix(child);
1107:                                                //										System.out.println("Found suffix: " + name);
1108:                                                if (x == i - 2) {
1109:                                                    methodName = name;
1110:                                                } else {
1111:                                                    varNames.add(name);
1112:                                                }
1113:                                            }
1114:                                        }
1115:                                    }
1116:                                }
1117:                            } else {
1118:                                //if no this or super found, everything is method name or variable
1119:                                //System.out.println("no this found:");
1120:                                FIRSTNODE: {
1121:                                    //variable names are in the prefix + the first method call [a.b.c.x()]
1122:                                    ASTPrimaryPrefix child = (ASTPrimaryPrefix) node
1123:                                            .jjtGetFirstChild();
1124:                                    String toParse = getNameFromPrefix(child);
1125:                                    //							System.out.println("parsing for var names in : " + toParse);
1126:                                    java.util.StringTokenizer st = new java.util.StringTokenizer(
1127:                                            toParse, ".");
1128:                                    while (st.hasMoreTokens()) {
1129:                                        String value = st.nextToken();
1130:                                        if (!st.hasMoreTokens()) {
1131:                                            if (i == 2) {
1132:                                                //if this expression is 2 nodes long, then the last part of prefix is method name
1133:                                                methodName = value;
1134:                                            } else {
1135:                                                varNames.add(value);
1136:                                            }
1137:                                        } else {
1138:                                            //variable name
1139:                                            varNames.add(value);
1140:                                        }
1141:                                    }
1142:                                }
1143:                                OTHERNODES: {
1144:                                    //other methods called in this statement are grabbed here
1145:                                    for (int x = 1; x < i - 1; x++) {
1146:                                        ASTPrimarySuffix child = (ASTPrimarySuffix) node
1147:                                                .jjtGetChild(x);
1148:                                        if (child.isArguments() == false) {
1149:                                            String name = getNameFromSuffix(child);
1150:                                            if (x == i - 2) {
1151:                                                methodName = name;
1152:                                            } else {
1153:                                                varNames.add(name);
1154:                                            }
1155:                                        }
1156:                                    }
1157:                                }
1158:                            }
1159:                            meth = new MethodInvocation(node,
1160:                                    packagesAndClasses, varNames, methodName,
1161:                                    numOfArguments, super First);
1162:                        }
1163:                    }
1164:                    return meth;
1165:                }
1166:            }
1167:
1168:            /**
1169:             *  1 package per class. holds info for evaluating a single class.
1170:             *
1171:             *@author    Mike Atkinson
1172:             */
1173:            private static class EvalPackage {
1174:
1175:                /**  Description of the Field */
1176:                public String m_ClassName;
1177:                /**  Description of the Field */
1178:                public List calledMethods;
1179:                /**  Description of the Field */
1180:                public Map allMethodsOfClass;
1181:
1182:                /**  Description of the Field */
1183:                public List calledConstructors;
1184:                /**  Description of the Field */
1185:                public Map allPrivateConstructorsOfClass;
1186:
1187:                /**  Constructor for the EvalPackage object */
1188:                public EvalPackage() {
1189:                }
1190:
1191:                /**
1192:                 *  Constructor for the EvalPackage object
1193:                 *
1194:                 *@param  className  Description of Parameter
1195:                 */
1196:                public EvalPackage(String className) {
1197:                    m_ClassName = className;
1198:                    calledMethods = new ArrayList();
1199:                    //meths called from constructor
1200:                    allMethodsOfClass = new HashMap();
1201:                    calledConstructors = new ArrayList();
1202:                    //all constructors called from constructor
1203:                    allPrivateConstructorsOfClass = new HashMap();
1204:                }
1205:            }
1206:
1207:            /**
1208:             *  Description of the Class
1209:             *
1210:             *@author    Mike Atkinson
1211:             */
1212:            private final static class NullEvalPackage extends EvalPackage {
1213:                /**  Constructor for the NullEvalPackage object */
1214:                public NullEvalPackage() {
1215:                    m_ClassName = "";
1216:                    calledMethods = Collections.EMPTY_LIST;
1217:                    allMethodsOfClass = Collections.EMPTY_MAP;
1218:                    calledConstructors = Collections.EMPTY_LIST;
1219:                    allPrivateConstructorsOfClass = Collections.EMPTY_MAP;
1220:                }
1221:            }
1222:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.