Source Code Cross Referenced for Hierarchy.java in  » Code-Analyzer » findbugs » edu » umd » cs » findbugs » ba » 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 » Code Analyzer » findbugs » edu.umd.cs.findbugs.ba 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Bytecode Analysis Framework
0003:         * Copyright (C) 2003,2004 University of Maryland
0004:         * 
0005:         * This library is free software; you can redistribute it and/or
0006:         * modify it under the terms of the GNU Lesser General Public
0007:         * License as published by the Free Software Foundation; either
0008:         * version 2.1 of the License, or (at your option) any later version.
0009:         * 
0010:         * This library is distributed in the hope that it will be useful,
0011:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013:         * Lesser General Public License for more details.
0014:         * 
0015:         * You should have received a copy of the GNU Lesser General Public
0016:         * License along with this library; if not, write to the Free Software
0017:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0018:         */
0019:
0020:        package edu.umd.cs.findbugs.ba;
0021:
0022:        import java.util.HashMap;
0023:        import java.util.HashSet;
0024:        import java.util.Map;
0025:        import java.util.Set;
0026:
0027:        import org.apache.bcel.Constants;
0028:        import org.apache.bcel.Repository;
0029:        import org.apache.bcel.classfile.Field;
0030:        import org.apache.bcel.classfile.JavaClass;
0031:        import org.apache.bcel.classfile.Method;
0032:        import org.apache.bcel.generic.ArrayType;
0033:        import org.apache.bcel.generic.ConstantPoolGen;
0034:        import org.apache.bcel.generic.FieldInstruction;
0035:        import org.apache.bcel.generic.INVOKESTATIC;
0036:        import org.apache.bcel.generic.Instruction;
0037:        import org.apache.bcel.generic.InvokeInstruction;
0038:        import org.apache.bcel.generic.ObjectType;
0039:        import org.apache.bcel.generic.ReferenceType;
0040:        import org.apache.bcel.generic.Type;
0041:
0042:        import edu.umd.cs.findbugs.SystemProperties;
0043:        import edu.umd.cs.findbugs.annotations.CheckForNull;
0044:        import edu.umd.cs.findbugs.annotations.NonNull;
0045:        import edu.umd.cs.findbugs.ba.ch.Subtypes2;
0046:        import edu.umd.cs.findbugs.ba.type.TypeFrame;
0047:        import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
0048:        import edu.umd.cs.findbugs.classfile.ClassDescriptor;
0049:        import edu.umd.cs.findbugs.classfile.DescriptorFactory;
0050:        import edu.umd.cs.findbugs.classfile.Global;
0051:
0052:        /**
0053:         * Facade for class hierarchy queries.
0054:         * These typically access the class hierarchy using
0055:         * the {@link org.apache.bcel.Repository} class.  Callers should generally
0056:         * expect to handle ClassNotFoundException for when referenced
0057:         * classes can't be found.
0058:         *
0059:         * @author David Hovemeyer
0060:         */
0061:        public class Hierarchy {
0062:            protected static final boolean DEBUG_METHOD_LOOKUP = SystemProperties
0063:                    .getBoolean("hier.lookup.debug");
0064:
0065:            /**
0066:             * Type of java.lang.Exception.
0067:             */
0068:            public static final ObjectType EXCEPTION_TYPE = ObjectTypeFactory
0069:                    .getInstance("java.lang.Exception");
0070:            /**
0071:             * Type of java.lang.Error.
0072:             */
0073:            public static final ObjectType ERROR_TYPE = ObjectTypeFactory
0074:                    .getInstance("java.lang.Error");
0075:            /**
0076:             * Type of java.lang.RuntimeException.
0077:             */
0078:            public static final ObjectType RUNTIME_EXCEPTION_TYPE = ObjectTypeFactory
0079:                    .getInstance("java.lang.RuntimeException");
0080:
0081:            /**
0082:             * Determine whether one class (or reference type) is a subtype
0083:             * of another.
0084:             *
0085:             * @param clsName                    the name of the class or reference type
0086:             * @param possibleSupertypeClassName the name of the possible superclass
0087:             * @return true if clsName is a subtype of possibleSupertypeClassName,
0088:             *         false if not
0089:             */
0090:            public static boolean isSubtype(String clsName,
0091:                    String possibleSupertypeClassName)
0092:                    throws ClassNotFoundException {
0093:                ObjectType cls = ObjectTypeFactory.getInstance(clsName);
0094:                ObjectType super Cls = ObjectTypeFactory
0095:                        .getInstance(possibleSupertypeClassName);
0096:                return isSubtype(cls, super Cls);
0097:            }
0098:
0099:            /**
0100:             * Determine if one reference type is a subtype of another.
0101:             *
0102:             * @param t                 a reference type
0103:             * @param possibleSupertype the possible supertype
0104:             * @return true if t is a subtype of possibleSupertype,
0105:             *         false if not
0106:             */
0107:            public static boolean isSubtype(ReferenceType t,
0108:                    ReferenceType possibleSupertype)
0109:                    throws ClassNotFoundException {
0110:                if (Subtypes2.ENABLE_SUBTYPES2) {
0111:                    try {
0112:                        Subtypes2 subtypes2 = Global.getAnalysisCache()
0113:                                .getDatabase(Subtypes2.class);
0114:                        return subtypes2.isSubtype(t, possibleSupertype);
0115:                    } catch (CheckedAnalysisException e) {
0116:                        // Should not happen
0117:                        IllegalStateException ise = new IllegalStateException(
0118:                                "Should not happen");
0119:                        ise.initCause(e);
0120:                        throw ise;
0121:                    }
0122:                } else {
0123:                    Map<ReferenceType, Boolean> subtypes = subtypeCache
0124:                            .get(possibleSupertype);
0125:                    if (subtypes == null) {
0126:                        subtypes = new HashMap<ReferenceType, Boolean>();
0127:                        subtypeCache.put(possibleSupertype, subtypes);
0128:                    }
0129:                    Boolean result = subtypes.get(t);
0130:                    if (result == null) {
0131:                        result = Boolean.valueOf(t
0132:                                .isAssignmentCompatibleWith(possibleSupertype));
0133:                        subtypes.put(t, result);
0134:                    }
0135:                    return result;
0136:                }
0137:            }
0138:
0139:            static Map<ReferenceType, Map<ReferenceType, Boolean>> subtypeCache = new HashMap<ReferenceType, Map<ReferenceType, Boolean>>();
0140:
0141:            /**
0142:             * Determine if the given ObjectType reference represents
0143:             * a <em>universal</em> exception handler.  That is,
0144:             * one that will catch any kind of exception.
0145:             *
0146:             * @param catchType the ObjectType of the exception handler
0147:             * @return true if catchType is null, or if catchType is
0148:             *         java.lang.Throwable
0149:             */
0150:            public static boolean isUniversalExceptionHandler(
0151:                    ObjectType catchType) {
0152:                return catchType == null || catchType.equals(Type.THROWABLE);
0153:            }
0154:
0155:            /**
0156:             * Determine if the given ObjectType refers to an unchecked
0157:             * exception (RuntimeException or Error).
0158:             */
0159:            public static boolean isUncheckedException(ObjectType type)
0160:                    throws ClassNotFoundException {
0161:                return isSubtype(type, RUNTIME_EXCEPTION_TYPE)
0162:                        || isSubtype(type, ERROR_TYPE);
0163:            }
0164:
0165:            /**
0166:             * Determine if method whose name and signature is specified
0167:             * is a monitor wait operation.
0168:             *
0169:             * @param methodName name of the method
0170:             * @param methodSig  signature of the method
0171:             * @return true if the method is a monitor wait, false if not
0172:             */
0173:            public static boolean isMonitorWait(String methodName,
0174:                    String methodSig) {
0175:                return methodName.equals("wait")
0176:                        && (methodSig.equals("()V") || methodSig.equals("(J)V") || methodSig
0177:                                .equals("(JI)V"));
0178:            }
0179:
0180:            /**
0181:             * Determine if given Instruction is a monitor wait.
0182:             * 
0183:             * @param ins the Instruction
0184:             * @param cpg the ConstantPoolGen for the Instruction
0185:             *
0186:             * @return true if the instruction is a monitor wait, false if not
0187:             */
0188:            public static boolean isMonitorWait(Instruction ins,
0189:                    ConstantPoolGen cpg) {
0190:                if (!(ins instanceof  InvokeInstruction))
0191:                    return false;
0192:                if (ins.getOpcode() == Constants.INVOKESTATIC)
0193:                    return false;
0194:
0195:                InvokeInstruction inv = (InvokeInstruction) ins;
0196:                String methodName = inv.getMethodName(cpg);
0197:                String methodSig = inv.getSignature(cpg);
0198:
0199:                return isMonitorWait(methodName, methodSig);
0200:            }
0201:
0202:            /**
0203:             * Determine if method whose name and signature is specified
0204:             * is a monitor notify operation.
0205:             *
0206:             * @param methodName name of the method
0207:             * @param methodSig  signature of the method
0208:             * @return true if the method is a monitor notify, false if not
0209:             */
0210:            public static boolean isMonitorNotify(String methodName,
0211:                    String methodSig) {
0212:                return (methodName.equals("notify") || methodName
0213:                        .equals("notifyAll"))
0214:                        && methodSig.equals("()V");
0215:            }
0216:
0217:            /**
0218:             * Determine if given Instruction is a monitor wait.
0219:             * 
0220:             * @param ins the Instruction
0221:             * @param cpg the ConstantPoolGen for the Instruction
0222:             *
0223:             * @return true if the instruction is a monitor wait, false if not
0224:             */
0225:            public static boolean isMonitorNotify(Instruction ins,
0226:                    ConstantPoolGen cpg) {
0227:                if (!(ins instanceof  InvokeInstruction))
0228:                    return false;
0229:                if (ins.getOpcode() == Constants.INVOKESTATIC)
0230:                    return false;
0231:
0232:                InvokeInstruction inv = (InvokeInstruction) ins;
0233:                String methodName = inv.getMethodName(cpg);
0234:                String methodSig = inv.getSignature(cpg);
0235:
0236:                return isMonitorNotify(methodName, methodSig);
0237:            }
0238:
0239:            /**
0240:             * Look up the method referenced by given InvokeInstruction.
0241:             * This method does <em>not</em> look for implementations in
0242:             * super or subclasses according to the virtual dispatch rules.
0243:             *
0244:             * @param inv the InvokeInstruction
0245:             * @param cpg the ConstantPoolGen used by the class the InvokeInstruction belongs to
0246:             * @return the JavaClassAndMethod, or null if no such method is defined in the class
0247:             */
0248:            public static JavaClassAndMethod findExactMethod(
0249:                    InvokeInstruction inv, ConstantPoolGen cpg)
0250:                    throws ClassNotFoundException {
0251:                return findExactMethod(inv, cpg, ANY_METHOD);
0252:            }
0253:
0254:            /**
0255:             * Look up the method referenced by given InvokeInstruction.
0256:             * This method does <em>not</em> look for implementations in
0257:             * super or subclasses according to the virtual dispatch rules.
0258:             *
0259:             * @param inv     the InvokeInstruction
0260:             * @param cpg     the ConstantPoolGen used by the class the InvokeInstruction belongs to
0261:             * @param chooser JavaClassAndMethodChooser to use to pick the method from among the candidates
0262:             * @return the JavaClassAndMethod, or null if no such method is defined in the class
0263:             */
0264:            public static JavaClassAndMethod findExactMethod(
0265:                    InvokeInstruction inv, ConstantPoolGen cpg,
0266:                    JavaClassAndMethodChooser chooser)
0267:                    throws ClassNotFoundException {
0268:                String className = inv.getClassName(cpg);
0269:                String methodName = inv.getName(cpg);
0270:                String methodSig = inv.getSignature(cpg);
0271:
0272:                JavaClass jclass = Repository.lookupClass(className);
0273:                return findMethod(jclass, methodName, methodSig, chooser);
0274:            }
0275:
0276:            /**
0277:             * Visit all superclass methods which the given method overrides. 
0278:             * 
0279:             * @param method  the method
0280:             * @param chooser chooser which visits each superclass method
0281:             * @return the chosen method, or null if no method is chosen
0282:             * @throws ClassNotFoundException
0283:             */
0284:            public static JavaClassAndMethod visitSuperClassMethods(
0285:                    JavaClassAndMethod method, JavaClassAndMethodChooser chooser)
0286:                    throws ClassNotFoundException {
0287:                return findMethod(method.getJavaClass().getSuperClasses(),
0288:                        method.getMethod().getName(), method.getMethod()
0289:                                .getSignature(), chooser);
0290:            }
0291:
0292:            /**
0293:             * Visit all superinterface methods which the given method implements. 
0294:             * 
0295:             * @param method  the method
0296:             * @param chooser chooser which visits each superinterface method
0297:             * @return the chosen method, or null if no method is chosen
0298:             * @throws ClassNotFoundException
0299:             */
0300:            public static JavaClassAndMethod visitSuperInterfaceMethods(
0301:                    JavaClassAndMethod method, JavaClassAndMethodChooser chooser)
0302:                    throws ClassNotFoundException {
0303:                return findMethod(method.getJavaClass().getAllInterfaces(),
0304:                        method.getMethod().getName(), method.getMethod()
0305:                                .getSignature(), chooser);
0306:            }
0307:
0308:            /**
0309:             * Find the least upper bound method in the class hierarchy
0310:             * which could be called by the given InvokeInstruction.
0311:             * One reason this method is useful is that it indicates 
0312:             * which declared exceptions are thrown by the called methods.
0313:             * 
0314:             * <p/>
0315:             * <ul>
0316:             * <li> For  invokespecial, this is simply an
0317:             * exact lookup.
0318:             * <li> For invokestatic and invokevirtual, the named class is searched,
0319:             * followed by superclasses  up to the root of the object
0320:             * hierarchy (java.lang.Object).  Yes, invokestatic really is declared
0321:             * to check superclasses.  See VMSpec, 2nd ed, sec. 5.4.3.3.
0322:             * <li> For invokeinterface, the named class is searched,
0323:             * followed by all interfaces transitively declared by the class.
0324:             * (Question: is the order important here? Maybe the VM spec
0325:             * requires that the actual interface desired is given,
0326:             * so the extended lookup will not be required. Should check.)
0327:             * </ul>
0328:             *
0329:             * @param inv           the InvokeInstruction
0330:             * @param cpg           the ConstantPoolGen used by the class the InvokeInstruction belongs to
0331:             * @return the JavaClassAndMethod, or null if no matching method can be found
0332:             */
0333:            public static @CheckForNull
0334:            JavaClassAndMethod findInvocationLeastUpperBound(
0335:                    InvokeInstruction inv, ConstantPoolGen cpg)
0336:                    throws ClassNotFoundException {
0337:                return findInvocationLeastUpperBound(inv, cpg, ANY_METHOD);
0338:            }
0339:
0340:            public static @CheckForNull
0341:            JavaClassAndMethod findInvocationLeastUpperBound(
0342:                    InvokeInstruction inv, ConstantPoolGen cpg,
0343:                    JavaClassAndMethodChooser methodChooser)
0344:                    throws ClassNotFoundException {
0345:
0346:                if (DEBUG_METHOD_LOOKUP) {
0347:                    System.out.println("Find prototype method for "
0348:                            + SignatureConverter.convertMethodSignature(inv,
0349:                                    cpg));
0350:                }
0351:
0352:                short opcode = inv.getOpcode();
0353:
0354:                if (opcode == Constants.INVOKESTATIC) {
0355:                    if (methodChooser == INSTANCE_METHOD)
0356:                        return null;
0357:                } else {
0358:                    if (methodChooser == STATIC_METHOD)
0359:                        return null;
0360:                }
0361:
0362:                // Find the method
0363:                if (opcode == Constants.INVOKESPECIAL) {
0364:                    // Non-virtual dispatch
0365:                    return findExactMethod(inv, cpg, methodChooser);
0366:                } else {
0367:                    String className = inv.getClassName(cpg);
0368:                    String methodName = inv.getName(cpg);
0369:                    String methodSig = inv.getSignature(cpg);
0370:                    if (DEBUG_METHOD_LOOKUP) {
0371:                        System.out.println("[Class name is " + className + "]");
0372:                        System.out.println("[Method name is " + methodName
0373:                                + "]");
0374:                        System.out.println("[Method signature is " + methodSig
0375:                                + "]");
0376:                    }
0377:
0378:                    if (className.startsWith("[")) {
0379:                        // Java 1.5 allows array classes to appear as the class name
0380:                        className = "java.lang.Object";
0381:                    }
0382:
0383:                    JavaClass jClass = Repository.lookupClass(className);
0384:                    return findInvocationLeastUpperBound(jClass, methodName,
0385:                            methodSig, methodChooser,
0386:                            opcode == Constants.INVOKEINTERFACE);
0387:
0388:                }
0389:            }
0390:
0391:            public static @CheckForNull
0392:            JavaClassAndMethod findInvocationLeastUpperBound(JavaClass jClass,
0393:                    String methodName, String methodSig,
0394:                    JavaClassAndMethodChooser methodChooser,
0395:                    boolean invokeInterface) throws ClassNotFoundException {
0396:                JavaClassAndMethod result = findMethod(jClass, methodName,
0397:                        methodSig, methodChooser);
0398:                if (result != null)
0399:                    return result;
0400:                if (invokeInterface)
0401:                    for (JavaClass i : jClass.getInterfaces()) {
0402:                        result = findInvocationLeastUpperBound(i, methodName,
0403:                                methodSig, methodChooser, invokeInterface);
0404:                        if (result != null)
0405:                            return null;
0406:                    }
0407:                else {
0408:                    JavaClass sClass = jClass.getSuperClass();
0409:                    if (sClass != null)
0410:                        return findInvocationLeastUpperBound(sClass,
0411:                                methodName, methodSig, methodChooser,
0412:                                invokeInterface);
0413:                }
0414:                return null;
0415:
0416:            }
0417:
0418:            /**
0419:             * Find the declared exceptions for the method called
0420:             * by given instruction.
0421:             *
0422:             * @param inv the InvokeInstruction
0423:             * @param cpg the ConstantPoolGen used by the class the InvokeInstruction belongs to
0424:             * @return array of ObjectTypes of thrown exceptions, or null
0425:             *         if we can't find the list of declared exceptions
0426:             * @deprecated Use {@link Hierarchy2#findDeclaredExceptions(InvokeInstruction,ConstantPoolGen)} instead
0427:             */
0428:            public static ObjectType[] findDeclaredExceptions(
0429:                    InvokeInstruction inv, ConstantPoolGen cpg)
0430:                    throws ClassNotFoundException {
0431:                return Hierarchy2.findDeclaredExceptions(inv, cpg);
0432:            }
0433:
0434:            /**
0435:             * Find a method in given class.
0436:             *
0437:             * @param javaClass  the class
0438:             * @param methodName the name of the method
0439:             * @param methodSig  the signature of the method
0440:             * @return the JavaClassAndMethod, or null if no such method exists in the class
0441:             */
0442:            public static @CheckForNull
0443:            JavaClassAndMethod findMethod(JavaClass javaClass,
0444:                    String methodName, String methodSig) {
0445:                return findMethod(javaClass, methodName, methodSig, ANY_METHOD);
0446:            }
0447:
0448:            public static @CheckForNull
0449:            JavaClassAndMethod findMethod(JavaClass javaClass,
0450:                    String methodName, String methodSig,
0451:                    JavaClassAndMethodChooser chooser) {
0452:                if (DEBUG_METHOD_LOOKUP) {
0453:                    System.out.println("Check " + javaClass.getClassName());
0454:                }
0455:                Method[] methodList = javaClass.getMethods();
0456:                for (Method method : methodList)
0457:                    if (method.getName().equals(methodName)
0458:                            && method.getSignature().equals(methodSig)) {
0459:                        JavaClassAndMethod m = new JavaClassAndMethod(
0460:                                javaClass, method);
0461:                        if (chooser.choose(m)) {
0462:                            if (DEBUG_METHOD_LOOKUP) {
0463:                                System.out.println("\t==> FOUND: " + method);
0464:                            }
0465:                            return m;
0466:                        }
0467:                    }
0468:                if (DEBUG_METHOD_LOOKUP) {
0469:                    System.out.println("\t==> NOT FOUND");
0470:                }
0471:                return null;
0472:            }
0473:
0474:            /**
0475:             * Find a method in given class.
0476:             *
0477:             * @param classDesc  the class descriptor
0478:             * @param methodName the name of the method
0479:             * @param methodSig  the signature of the method
0480:             * @param isStatic    are we looking for a static method?
0481:             * @return the JavaClassAndMethod, or null if no such method exists in the class
0482:             */
0483:            public static @CheckForNull
0484:            XMethod findMethod(ClassDescriptor classDesc, String methodName,
0485:                    String methodSig, boolean isStatic) {
0486:                if (DEBUG_METHOD_LOOKUP) {
0487:                    System.out.println("Check " + classDesc.getClassName());
0488:                }
0489:
0490:                try {
0491:                    XClass xClass = Global.getAnalysisCache().getClassAnalysis(
0492:                            XClass.class, classDesc);
0493:                    return xClass.findMethod(methodName, methodSig, isStatic);
0494:                } catch (CheckedAnalysisException e) {
0495:                    AnalysisContext.logError("Error looking for " + classDesc
0496:                            + "." + methodName + methodSig, e);
0497:                    return null;
0498:                }
0499:
0500:            }
0501:
0502:            /**
0503:             * Find a method in given class.
0504:             *
0505:             * @param javaClass  the class
0506:             * @param methodName the name of the method
0507:             * @param methodSig  the signature of the method
0508:             * @return the JavaClassAndMethod, or null if no such method exists in the class
0509:             */
0510:            @Deprecated
0511:            public static @CheckForNull
0512:            JavaClassAndMethod findConcreteMethod(JavaClass javaClass,
0513:                    String methodName, String methodSig) {
0514:
0515:                if (DEBUG_METHOD_LOOKUP) {
0516:                    System.out.println("Check " + javaClass.getClassName());
0517:                }
0518:                Method[] methodList = javaClass.getMethods();
0519:                for (Method method : methodList)
0520:                    if (method.getName().equals(methodName)
0521:                            && method.getSignature().equals(methodSig)
0522:                            && accessFlagsAreConcrete(method.getAccessFlags())) {
0523:                        JavaClassAndMethod m = new JavaClassAndMethod(
0524:                                javaClass, method);
0525:
0526:                        return m;
0527:
0528:                    }
0529:                if (DEBUG_METHOD_LOOKUP) {
0530:                    System.out.println("\t==> NOT FOUND");
0531:                }
0532:                return null;
0533:            }
0534:
0535:            /**
0536:             * Find a method in given class.
0537:             *
0538:             * @param javaClass  the class
0539:             * @param methodName the name of the method
0540:             * @param methodSig  the signature of the method
0541:             * @param chooser    the JavaClassAndMethodChooser to use to screen possible candidates
0542:             * @return the XMethod, or null if no such method exists in the class
0543:             */
0544:            @Deprecated
0545:            public static @CheckForNull
0546:            XMethod findXMethod(JavaClass javaClass, String methodName,
0547:                    String methodSig, JavaClassAndMethodChooser chooser) {
0548:                JavaClassAndMethod result = findMethod(javaClass, methodName,
0549:                        methodSig, chooser);
0550:                return result == null ? null : XFactory.createXMethod(result
0551:                        .getJavaClass(), result.getMethod());
0552:            }
0553:
0554:            /**
0555:             * JavaClassAndMethodChooser which accepts any method.
0556:             */
0557:            public static final JavaClassAndMethodChooser ANY_METHOD = new JavaClassAndMethodChooser() {
0558:                public boolean choose(JavaClassAndMethod javaClassAndMethod) {
0559:                    return true;
0560:                }
0561:
0562:                public boolean choose(XMethod method) {
0563:                    return true;
0564:                }
0565:
0566:            };
0567:
0568:            // FIXME: perhaps native methods should be concrete.
0569:            public static boolean accessFlagsAreConcrete(int accessFlags) {
0570:                return (accessFlags & Constants.ACC_ABSTRACT) == 0
0571:                        && (accessFlags & Constants.ACC_NATIVE) == 0;
0572:            }
0573:
0574:            /**
0575:             * JavaClassAndMethodChooser which accepts only concrete (not abstract or native) methods.
0576:             */
0577:            public static final JavaClassAndMethodChooser CONCRETE_METHOD = new JavaClassAndMethodChooser() {
0578:                public boolean choose(JavaClassAndMethod javaClassAndMethod) {
0579:                    Method method = javaClassAndMethod.getMethod();
0580:                    int accessFlags = method.getAccessFlags();
0581:                    return accessFlagsAreConcrete(accessFlags);
0582:                }
0583:
0584:                public boolean choose(XMethod method) {
0585:                    return accessFlagsAreConcrete(method.getAccessFlags());
0586:                }
0587:            };
0588:
0589:            /**
0590:             * JavaClassAndMethodChooser which accepts only static methods.
0591:             */
0592:            public static final JavaClassAndMethodChooser STATIC_METHOD = new JavaClassAndMethodChooser() {
0593:                public boolean choose(JavaClassAndMethod javaClassAndMethod) {
0594:                    return javaClassAndMethod.getMethod().isStatic();
0595:                }
0596:
0597:                public boolean choose(XMethod method) {
0598:                    return method.isStatic();
0599:                }
0600:            };
0601:
0602:            /**
0603:             * JavaClassAndMethodChooser which accepts only instance methods.
0604:             */
0605:            public static final JavaClassAndMethodChooser INSTANCE_METHOD = new JavaClassAndMethodChooser() {
0606:                public boolean choose(JavaClassAndMethod javaClassAndMethod) {
0607:                    return !javaClassAndMethod.getMethod().isStatic();
0608:                }
0609:
0610:                public boolean choose(XMethod method) {
0611:                    return !method.isStatic();
0612:                }
0613:            };
0614:
0615:            /**
0616:             * Find a method in given list of classes,
0617:             * searching the classes in order.
0618:             *
0619:             * @param classList  list of classes in which to search
0620:             * @param methodName the name of the method
0621:             * @param methodSig  the signature of the method
0622:             * @return the JavaClassAndMethod, or null if no such method exists in the class
0623:             */
0624:            @Deprecated
0625:            public static JavaClassAndMethod findMethod(JavaClass[] classList,
0626:                    String methodName, String methodSig) {
0627:                return findMethod(classList, methodName, methodSig, ANY_METHOD);
0628:            }
0629:
0630:            /**
0631:             * Find a method in given list of classes,
0632:             * searching the classes in order.
0633:             *
0634:             * @param classList  list of classes in which to search
0635:             * @param methodName the name of the method
0636:             * @param methodSig  the signature of the method
0637:             * @param chooser    JavaClassAndMethodChooser to select which methods are considered;
0638:             *                   it must return true for a method to be returned
0639:             * @return the JavaClassAndMethod, or null if no such method exists in the class
0640:             */
0641:            public static JavaClassAndMethod findMethod(JavaClass[] classList,
0642:                    String methodName, String methodSig,
0643:                    JavaClassAndMethodChooser chooser) {
0644:                JavaClassAndMethod m = null;
0645:
0646:                for (JavaClass cls : classList) {
0647:                    if ((m = findMethod(cls, methodName, methodSig, chooser)) != null)
0648:                        break;
0649:                }
0650:
0651:                return m;
0652:            }
0653:
0654:            /**
0655:             * Find XMethod for method in given list of classes,
0656:             * searching the classes in order.
0657:             *
0658:             * @param classList  list of classes in which to search
0659:             * @param methodName the name of the method
0660:             * @param methodSig  the signature of the method
0661:             * @return the XMethod, or null if no such method exists in the class
0662:             */
0663:            @Deprecated
0664:            public static XMethod findXMethod(JavaClass[] classList,
0665:                    String methodName, String methodSig) {
0666:                return findXMethod(classList, methodName, methodSig, ANY_METHOD);
0667:            }
0668:
0669:            /**
0670:             * Find XMethod for method in given list of classes,
0671:             * searching the classes in order.
0672:             *
0673:             * @param classList  list of classes in which to search
0674:             * @param methodName the name of the method
0675:             * @param methodSig  the signature of the method
0676:             * @param chooser    JavaClassAndMethodChooser to select which methods are considered;
0677:             *                   it must return true for a method to be returned
0678:             * @return the XMethod, or null if no such method exists in the class
0679:             */
0680:            @Deprecated
0681:            public static XMethod findXMethod(JavaClass[] classList,
0682:                    String methodName, String methodSig,
0683:                    JavaClassAndMethodChooser chooser) {
0684:                for (JavaClass cls : classList) {
0685:                    JavaClassAndMethod m;
0686:                    if ((m = findMethod(cls, methodName, methodSig)) != null
0687:                            && chooser.choose(m)) {
0688:                        return XFactory.createXMethod(cls, m.getMethod());
0689:                    }
0690:                }
0691:                return null;
0692:            }
0693:
0694:            /**
0695:             * Resolve possible method call targets.
0696:             * This works for both static and instance method calls.
0697:             * 
0698:             * @param invokeInstruction the InvokeInstruction
0699:             * @param typeFrame         the TypeFrame containing the types of stack values
0700:             * @param cpg               the ConstantPoolGen
0701:             * @return Set of methods which might be called
0702:             * @throws DataflowAnalysisException 
0703:             * @throws ClassNotFoundException 
0704:             */
0705:            public static Set<JavaClassAndMethod> resolveMethodCallTargets(
0706:                    InvokeInstruction invokeInstruction, TypeFrame typeFrame,
0707:                    ConstantPoolGen cpg) throws DataflowAnalysisException,
0708:                    ClassNotFoundException {
0709:
0710:                short opcode = invokeInstruction.getOpcode();
0711:
0712:                if (opcode == Constants.INVOKESTATIC) {
0713:                    HashSet<JavaClassAndMethod> result = new HashSet<JavaClassAndMethod>();
0714:                    JavaClassAndMethod targetMethod = findInvocationLeastUpperBound(
0715:                            invokeInstruction, cpg, CONCRETE_METHOD);
0716:                    if (targetMethod != null) {
0717:                        result.add(targetMethod);
0718:                    }
0719:                    return result;
0720:                }
0721:
0722:                if (!typeFrame.isValid()) {
0723:                    return new HashSet<JavaClassAndMethod>();
0724:                }
0725:
0726:                Type receiverType;
0727:                boolean receiverTypeIsExact;
0728:
0729:                if (opcode == Constants.INVOKESPECIAL) {
0730:                    // invokespecial instructions are dispatched to EXACTLY
0731:                    // the class specified by the instruction
0732:                    receiverType = ObjectTypeFactory
0733:                            .getInstance(invokeInstruction.getClassName(cpg));
0734:                    receiverTypeIsExact = false; // Doesn't actually matter
0735:                } else {
0736:                    // For invokevirtual and invokeinterface instructions, we have
0737:                    // virtual dispatch.  By taking the receiver type (which may be a
0738:                    // subtype of the class specified by the instruction),
0739:                    // we may get a more precise set of call targets.
0740:                    int instanceStackLocation = typeFrame
0741:                            .getInstanceStackLocation(invokeInstruction, cpg);
0742:                    receiverType = typeFrame
0743:                            .getStackValue(instanceStackLocation);
0744:                    if (!(receiverType instanceof  ReferenceType)) {
0745:                        return new HashSet<JavaClassAndMethod>();
0746:                    }
0747:                    receiverTypeIsExact = typeFrame
0748:                            .isExact(instanceStackLocation);
0749:                }
0750:                if (DEBUG_METHOD_LOOKUP) {
0751:                    System.out.println("[receiver type is " + receiverType
0752:                            + ", "
0753:                            + (receiverTypeIsExact ? "exact]" : " not exact]"));
0754:                }
0755:
0756:                return resolveMethodCallTargets((ReferenceType) receiverType,
0757:                        invokeInstruction, cpg, receiverTypeIsExact);
0758:            }
0759:
0760:            /**
0761:             * Resolve possible instance method call targets.
0762:             * Assumes that invokevirtual and invokeinterface methods may
0763:             * call any subtype of the receiver class.
0764:             * 
0765:             * @param receiverType      type of the receiver object
0766:             * @param invokeInstruction the InvokeInstruction
0767:             * @param cpg               the ConstantPoolGen
0768:             * @return Set of methods which might be called
0769:             * @throws ClassNotFoundException
0770:             */
0771:            public static Set<JavaClassAndMethod> resolveMethodCallTargets(
0772:                    ReferenceType receiverType,
0773:                    InvokeInstruction invokeInstruction, ConstantPoolGen cpg)
0774:                    throws ClassNotFoundException {
0775:                return resolveMethodCallTargets(receiverType,
0776:                        invokeInstruction, cpg, false);
0777:            }
0778:
0779:            /**
0780:             * Resolve possible instance method call targets.
0781:             * 
0782:             * @param receiverType        type of the receiver object
0783:             * @param invokeInstruction   the InvokeInstruction
0784:             * @param cpg                 the ConstantPoolGen
0785:             * @param receiverTypeIsExact if true, the receiver type is known exactly,
0786:             *                            which should allow a precise result
0787:             * @return Set of methods which might be called
0788:             * @throws ClassNotFoundException
0789:             */
0790:            public static Set<JavaClassAndMethod> resolveMethodCallTargets(
0791:                    ReferenceType receiverType,
0792:                    InvokeInstruction invokeInstruction, ConstantPoolGen cpg,
0793:                    boolean receiverTypeIsExact) throws ClassNotFoundException {
0794:                HashSet<JavaClassAndMethod> result = new HashSet<JavaClassAndMethod>();
0795:
0796:                if (invokeInstruction.getOpcode() == Constants.INVOKESTATIC)
0797:                    throw new IllegalArgumentException();
0798:
0799:                String methodName = invokeInstruction.getName(cpg);
0800:                String methodSig = invokeInstruction.getSignature(cpg);
0801:
0802:                // Array method calls aren't virtual.
0803:                // They should just resolve to Object methods.
0804:                if (receiverType instanceof  ArrayType) {
0805:                    JavaClass javaLangObject = AnalysisContext
0806:                            .currentAnalysisContext().lookupClass(
0807:                                    "java.lang.Object");
0808:                    JavaClassAndMethod classAndMethod = findMethod(
0809:                            javaLangObject, methodName, methodSig,
0810:                            INSTANCE_METHOD);
0811:                    if (classAndMethod != null)
0812:                        result.add(classAndMethod);
0813:                    return result;
0814:                }
0815:
0816:                AnalysisContext analysisContext = AnalysisContext
0817:                        .currentAnalysisContext();
0818:
0819:                // Get the receiver class.
0820:                String receiverClassName = ((ObjectType) receiverType)
0821:                        .getClassName();
0822:                JavaClass receiverClass = analysisContext
0823:                        .lookupClass(receiverClassName);
0824:                ClassDescriptor receiverDesc = DescriptorFactory
0825:                        .createClassDescriptorFromDottedClassName(receiverClassName);
0826:
0827:                // Figure out the upper bound for the method.
0828:                // This is what will be called if this is not a virtual call site.
0829:                JavaClassAndMethod upperBound = findMethod(receiverClass,
0830:                        methodName, methodSig, CONCRETE_METHOD);
0831:                if (upperBound == null) {
0832:                    upperBound = findInvocationLeastUpperBound(receiverClass,
0833:                            methodName, methodSig, CONCRETE_METHOD, false);
0834:                }
0835:                if (upperBound != null) {
0836:                    if (DEBUG_METHOD_LOOKUP) {
0837:                        System.out.println("Adding upper bound: "
0838:                                + SignatureConverter.convertMethodSignature(
0839:                                        upperBound.getJavaClass(), upperBound
0840:                                                .getMethod()));
0841:                    }
0842:                    result.add(upperBound);
0843:                }
0844:
0845:                // Is this a virtual call site?
0846:                boolean virtualCall = (invokeInstruction.getOpcode() == Constants.INVOKEVIRTUAL || invokeInstruction
0847:                        .getOpcode() == Constants.INVOKEINTERFACE)
0848:                        && (upperBound == null || !upperBound.getJavaClass()
0849:                                .isFinal()
0850:                                && !upperBound.getMethod().isFinal())
0851:                        && !receiverTypeIsExact;
0852:
0853:                if (virtualCall) {
0854:                    if (!receiverClassName.equals("java.lang.Object")) {
0855:
0856:                        // This is a true virtual call: assume that any concrete
0857:                        // subtype method may be called.
0858:                        Set<ClassDescriptor> subTypeSet = analysisContext
0859:                                .getSubtypes2().getSubtypes(receiverDesc);
0860:                        for (ClassDescriptor subtype : subTypeSet) {
0861:                            XMethod concreteSubtypeMethod = findMethod(subtype,
0862:                                    methodName, methodSig, false);
0863:                            if (concreteSubtypeMethod != null
0864:                                    && (concreteSubtypeMethod.getAccessFlags() & Constants.ACC_ABSTRACT) == 0) {
0865:                                result.add(new JavaClassAndMethod(
0866:                                        concreteSubtypeMethod));
0867:                            }
0868:                        }
0869:                        if (false && subTypeSet.size() > 500)
0870:                            new RuntimeException(receiverClassName + " has "
0871:                                    + subTypeSet.size() + " subclasses, "
0872:                                    + result.size() + " of which implement "
0873:                                    + methodName + methodSig + " "
0874:                                    + invokeInstruction)
0875:                                    .printStackTrace(System.out);
0876:
0877:                    }
0878:                }
0879:                return result;
0880:            }
0881:
0882:            /**
0883:             * Return whether or not the given method is concrete.
0884:             * 
0885:             * @param xmethod the method
0886:             * @return true if the method is concrete, false otherwise
0887:             */
0888:            @Deprecated
0889:            public static boolean isConcrete(XMethod xmethod) {
0890:                int accessFlags = xmethod.getAccessFlags();
0891:                return (accessFlags & Constants.ACC_ABSTRACT) == 0
0892:                        && (accessFlags & Constants.ACC_NATIVE) == 0;
0893:            }
0894:
0895:            /**
0896:             * Find a field with given name defined in given class.
0897:             *
0898:             * @param className the name of the class
0899:             * @param fieldName the name of the field
0900:             * @return the Field, or null if no such field could be found
0901:             */
0902:            public static Field findField(String className, String fieldName)
0903:                    throws ClassNotFoundException {
0904:                JavaClass jclass = Repository.lookupClass(className);
0905:
0906:                while (jclass != null) {
0907:                    Field[] fieldList = jclass.getFields();
0908:                    for (Field field : fieldList) {
0909:                        if (field.getName().equals(fieldName)) {
0910:                            return field;
0911:                        }
0912:                    }
0913:
0914:                    jclass = jclass.getSuperClass();
0915:                }
0916:
0917:                return null;
0918:            }
0919:
0920:            /**
0921:             * Look up a field with given name and signature in given class,
0922:             * returning it as an {@link XField XField} object.
0923:             * If a field can't be found in the immediate class,
0924:             * its superclass is search, and so forth.
0925:             *
0926:             * @param className name of the class through which the field
0927:             *                  is referenced
0928:             * @param fieldName name of the field
0929:             * @param fieldSig  signature of the field
0930:             * @param isStatic  true if field is static, false otherwise
0931:             * @return an XField object representing the field, or null if no such field could be found
0932:             */
0933:            public static XField findXField(String className, String fieldName,
0934:                    String fieldSig, boolean isStatic)
0935:                    throws ClassNotFoundException {
0936:
0937:                return XFactory.createXField(className, fieldName, fieldSig,
0938:                        isStatic);
0939:            }
0940:
0941:            /**
0942:             * Look up the field referenced by given FieldInstruction,
0943:             * returning it as an {@link XField XField} object.
0944:             *
0945:             * @param fins the FieldInstruction
0946:             * @param cpg  the ConstantPoolGen used by the class containing the instruction
0947:             * @return an XField object representing the field, or null
0948:             *         if no such field could be found
0949:             */
0950:            public static XField findXField(FieldInstruction fins, @NonNull
0951:            ConstantPoolGen cpg) throws ClassNotFoundException {
0952:
0953:                String className = fins.getClassName(cpg);
0954:                String fieldName = fins.getFieldName(cpg);
0955:                String fieldSig = fins.getSignature(cpg);
0956:
0957:                boolean isStatic = (fins.getOpcode() == Constants.GETSTATIC || fins
0958:                        .getOpcode() == Constants.PUTSTATIC);
0959:
0960:                XField xfield = findXField(className, fieldName, fieldSig,
0961:                        isStatic);
0962:                short opcode = fins.getOpcode();
0963:                if (xfield != null
0964:                        && xfield.isStatic() == (opcode == Constants.GETSTATIC || opcode == Constants.PUTSTATIC))
0965:                    return xfield;
0966:                else
0967:                    return null;
0968:            }
0969:
0970:            /**
0971:             * Determine whether the given INVOKESTATIC instruction
0972:             * is an inner-class field accessor method.
0973:             * @param inv the INVOKESTATIC instruction
0974:             * @param cpg the ConstantPoolGen for the method
0975:             * @return true if the instruction is an inner-class field accessor, false if not
0976:             */
0977:            public static boolean isInnerClassAccess(INVOKESTATIC inv,
0978:                    ConstantPoolGen cpg) {
0979:                String methodName = inv.getName(cpg);
0980:                return methodName.startsWith("access$");
0981:            }
0982:
0983:            /**
0984:             * Get the InnerClassAccess for access method called
0985:             * by given INVOKESTATIC.
0986:             * @param inv the INVOKESTATIC instruction
0987:             * @param cpg the ConstantPoolGen for the method
0988:             * @return the InnerClassAccess, or null if the instruction is not
0989:             *    an inner-class access
0990:             */
0991:            public static InnerClassAccess getInnerClassAccess(
0992:                    INVOKESTATIC inv, ConstantPoolGen cpg)
0993:                    throws ClassNotFoundException {
0994:
0995:                String className = inv.getClassName(cpg);
0996:                String methodName = inv.getName(cpg);
0997:                String methodSig = inv.getSignature(cpg);
0998:
0999:                InnerClassAccess access = AnalysisContext
1000:                        .currentAnalysisContext().getInnerClassAccessMap()
1001:                        .getInnerClassAccess(className, methodName);
1002:                return (access != null && access.getMethodSignature().equals(
1003:                        methodSig)) ? access : null;
1004:            }
1005:
1006:        }
1007:
1008:        // vim:ts=4
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.