Source Code Cross Referenced for HotSwapClassRegister.java in  » Byte-Code » PROSE » ch » ethz » inf » iks » jvmai » jvmdi » 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 » Byte Code » PROSE » ch.ethz.inf.iks.jvmai.jvmdi 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        //
0002:        //  This file is part of the prose package.
0003:        //
0004:        //  The contents of this file are subject to the Mozilla Public License
0005:        //  Version 1.1 (the "License"); you may not use this file except in
0006:        //  compliance with the License. You may obtain a copy of the License at
0007:        //  http://www.mozilla.org/MPL/
0008:        //
0009:        //  Software distributed under the License is distributed on an "AS IS" basis,
0010:        //  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
0011:        //  for the specific language governing rights and limitations under the
0012:        //  License.
0013:        //
0014:        //  The Original Code is prose.
0015:        //
0016:        //  Contributor(s):
0017:        //  $Id$
0018:        //  =====================================================================
0019:        //
0020:        // (history at end)
0021:        //
0022:        package ch.ethz.inf.iks.jvmai.jvmdi;
0023:
0024:        import java.lang.reflect.Field;
0025:        import java.lang.ref.WeakReference;
0026:        import java.util.Collection;
0027:        import java.util.Map;
0028:        import java.util.List;
0029:        import java.util.Set;
0030:        import java.util.HashMap;
0031:        import java.util.LinkedList;
0032:        import java.util.HashSet;
0033:        import java.util.Iterator;
0034:        import java.util.ListIterator;
0035:        import java.util.Arrays;
0036:        import java.util.WeakHashMap;
0037:
0038:        import org.apache.bcel.classfile.JavaClass;
0039:        import org.apache.bcel.classfile.Constant;
0040:        import org.apache.bcel.classfile.ConstantFieldref;
0041:        import org.apache.bcel.classfile.ConstantCP;
0042:        import org.apache.bcel.classfile.ConstantPool;
0043:        import org.apache.bcel.classfile.ConstantNameAndType;
0044:        import org.apache.bcel.generic.*;
0045:
0046:        import ch.ethz.jvmai.JVMAIRuntimeException;
0047:        import ch.ethz.jvmai.MethodWeaver;
0048:
0049:        /**
0050:         * Analyses classes and holds a register all found field 
0051:         * accesses, field modifications, method calls, exception 
0052:         * throws and exception catches.
0053:         * 
0054:         * @author	Angela Nicoara
0055:         * @author  Gerald Linhofer
0056:         * @version $Revision: 1.1.2.2 $
0057:         *
0058:         */
0059:        public class HotSwapClassRegister {
0060:
0061:            /**
0062:             * The one and only instance of this class.
0063:             * (Singelton Pattern)
0064:             */
0065:            private static HotSwapClassRegister instance;
0066:            /**
0067:             * The JVMAspectInterface of this system or
0068:             * <CODE>null</CODE> if not initialized.
0069:             */
0070:            private static HotSwapAspectInterfaceImpl aspectInterface;
0071:            /**
0072:             * Prefixes defining the scope of the prose system.
0073:             * (Defines which packages should be affected by
0074:             * Aspects, and which not.)
0075:             */
0076:            private static Set worldPrefixes;
0077:            /**
0078:             * <CODE>false</CODE> if only classes matching
0079:             * the prefixes in {@link #worldPrefixes worldPrefixes} 
0080:             * should be scanned. Otherwise classes matching
0081:             * the prefixes will be ignored.
0082:             */
0083:            private static boolean openWorldAssumption;
0084:            /**
0085:             * Holds the names of internal (Prose and Java) packages to
0086:             * prevent them, and there sub packages, from beeing scanned.
0087:             */
0088:            private static Set internalPackages;
0089:
0090:            static {
0091:                internalPackages = new HashSet(6);
0092:                // fill internalPackages with all packages which may cause 
0093:                // trouble during scanning or weaving.
0094:                internalPackages.add("org.apache.bcel"); // some classes causes problems
0095:                // add also all classes in the package 'java' 
0096:                // just to make shure there will be no problems.
0097:                internalPackages.add("java"); // recommended by BCEL
0098:                internalPackages.add("javax"); // recommended by BCEL
0099:                internalPackages.add("sun"); // recommemded by BCEL
0100:            }
0101:
0102:            /**
0103:             * Maps field names to collection of classes, which holds references to them.
0104:             * This Map stores results from <CODE>scanConstantPool</CODE>.
0105:             * The field name is in the form <CODE>Classname#FieldName#JNISignature</CODE>.
0106:             */
0107:            public static Map knownFieldReferences = new HashMap(1024);
0108:
0109:            //	/**
0110:            //	 * Maps method names to collection of classes, which holds references to them.
0111:            //	 * This Map stores results from <CODE>scanConstantPool</CODE>.
0112:            //	 * The method name is in the form <CODE>Classname#MethodName#JNISignature</CODE>.
0113:            //	 */
0114:            //	public static Map knownMethodReferences	= new HashMap( 1024 );
0115:
0116:            /**
0117:             * Maps fields to all methods known to access them.
0118:             * Identifier for the fields are the keys, the value
0119:             * is a Collection, holding identifiers for the method.
0120:             * <P>
0121:             * The field identifier has the form <CODE>Classname#FieldName#JNISignature</CODE>
0122:             * and the method identifier <CODE>Classname#MethodName#JNISignature#isStatic</CODE>.
0123:             */
0124:            public static Map knownFieldAccesses = new HashMap(1024);
0125:            /**
0126:             * Maps fields to all methods known to modifie them.
0127:             * Identifier for the fields are the keys, the value
0128:             * is a Collection, holding identifiers for the method.
0129:             * <P>
0130:             * The field identifier has the form <CODE>Classname#FieldName#JNISignature</CODE>
0131:             * and the method identifier <CODE>Classname#MethodName#JNISignature#isStatic</CODE>.
0132:             */
0133:            public static Map knownFieldModifiers = new HashMap(1024);
0134:            //	/**
0135:            //	 * Maps methods to all methods known to access them.
0136:            //	 * Identifier for the called methods are the keys, the value
0137:            //	 * is a Collection, holding identifiers for the caller.
0138:            //	 */
0139:            //	public static Map knownMethodCalls				= new HashMap( 1024 );
0140:            //	/**
0141:            //	 * Maps exceptions to all methods known to throw them.
0142:            //	 * Identifier for the exceptions are the keys, the value
0143:            //	 * is a Collection, holding identifiers for the method.
0144:            //	 * 
0145:            //	 * Note: This are the 'declared' exceptions.
0146:            //	 */
0147:            //	public static Map knownExceptionThrows		= new HashMap( 1024 );
0148:            //	/**
0149:            //	 * Maps exceptions to all methods that may throw them.
0150:            //	 * Identifier for the exceptions are the keys, the value
0151:            //	 * is a Collection, holding identifiers for the method.
0152:            //	 * 
0153:            //	 * This are potential exceptions, so they may be called
0154:            //	 * or not. to set an watch for such an exception, an
0155:            //	 * exception handler must be woven around the instruction,
0156:            //	 * which may throw the exception. (ignore method calls, to
0157:            //	 * avoid repeated advice calling for the same exception).
0158:            //	 */
0159:            //	public static Map knownPotentialExceptionThrows	= new HashMap( 1024 );
0160:            //	/**
0161:            //	 * Maps exceptions to all methods known to catch them.
0162:            //	 * Identifier for the exceptions are the keys, the value
0163:            //	 * is a Collection, holding identifiers for the method.
0164:            //	 */
0165:            //	public static Map knownExceptionCatches			= new HashMap( 1024 );
0166:
0167:            /**
0168:             * <CODE>true</CODE> if all loaded classes should be scanned.
0169:             * The value of this variable triggers if all new loaded classes
0170:             * should be scanned or not.
0171:             */
0172:            private boolean registerAll = false;
0173:            /**
0174:             * Number of active weavers requested registerAll.
0175:             */
0176:            private int registerAllCount = 0;
0177:            /**
0178:             * Holds packages, which contains classes that should be
0179:             * scanned.
0180:             */
0181:            private Map registeredPackages = new HashMap();
0182:            /**
0183:             * Holds classes for which all direct or indirect sub classes 
0184:             * should be scanned.
0185:             */
0186:            private Map registeredSuperClasses = new HashMap();
0187:            /**
0188:             * Remembers the scanned classes and maps them to
0189:             * a collection with all <CODE>known...</CODE> map 
0190:             * entries, pointing to methods of this class.
0191:             * 
0192:             * This is also used as monitor object to synchronize
0193:             * modification of this map or any of the static known...
0194:             * maps defined above.
0195:             */
0196:            private Map scannedClasses = new WeakHashMap(1024);
0197:
0198:            /// Dummy value for using WeakHashMap as HashSet
0199:            private static Object dummyValue = new Object();
0200:
0201:            /**
0202:             * Remembers the classes, which constant pools where scanned for
0203:             * field and method references.
0204:             */
0205:            private Map scannedConstantPools = new WeakHashMap(1024);
0206:
0207:            //--------------------------------------------------------------------------------------------------------------
0208:            // Internal method to determine if a class should be scanned
0209:            //--------------------------------------------------------------------------------------------------------------
0210:
0211:            /**
0212:             * Determines if a class may be scanned. This depends
0213:             * on static constraints, which are hard coded or where
0214:             * set at startup of prose ({@link #worldPrefixes worldPrefixes}
0215:             * and {@link #internalPackages internalPackages}).
0216:             * 
0217:             * @param className name of the class.
0218:             * @return <CODE>true</CODE> if scanning of the class is
0219:             * 				allowed.
0220:             */
0221:            private boolean isScanningAllowed(Class cls) {
0222:                // Note: check for array class is only required for JVMDI not for JVMTI
0223:                if (null == aspectInterface || cls.isInterface()
0224:                        || cls.isArray() /*|| cls.isPrimitive()*//*|| ch.ethz.prose.DefaultAspect.class.isAssignableFrom(cls)*/
0225:                        || null == cls)
0226:                    return false;
0227:
0228:                String className = cls.getName();
0229:                int pos = className.indexOf('.');
0230:
0231:                if (!openWorldAssumption) {
0232:                    // check if any super package or the package it self
0233:                    // is in 'worldPrefixes'.
0234:                    while (-1 < pos) {
0235:                        String packageName = className.substring(0, pos);
0236:                        // Check if it's an internal class
0237:                        if (internalPackages.contains(packageName))
0238:                            return false;
0239:
0240:                        // Check if it 'part of our world'
0241:                        if (worldPrefixes.contains(packageName))
0242:                            return true;
0243:
0244:                        pos = className.indexOf('.', pos + 1);
0245:                    }
0246:                    return false;
0247:                } else {
0248:                    // check if any super package or the package it self
0249:                    // is in 'internalPackage' or 'worldPrefixes'.
0250:                    while (-1 < pos) {
0251:                        String packageName = className.substring(0, pos);
0252:                        if (internalPackages.contains(packageName)
0253:                                || worldPrefixes.contains(packageName))
0254:                            return false;
0255:
0256:                        pos = className.indexOf('.', pos + 1);
0257:                    }
0258:                    return true;
0259:                }
0260:            }
0261:
0262:            /**
0263:             * Determines if a class should be scanned or not.
0264:             * checks also if scanning is allowed. This checks
0265:             * for 'dynamic' constraints, which may change at
0266:             * each invocation of a <CODE>register...()<CODE> 
0267:             * or <CODE>unregister..()<CODE> method.
0268:             * 
0269:             * @param cls Class that may be scanned.
0270:             * @return <CODE>true</CODE> if <CODE>cls</CODE>
0271:             * 				should be scanned.
0272:             */
0273:            private boolean isScanningRequired(Class cls) {
0274:                return (!scannedConstantPools.containsKey(cls))
0275:                        && isScanningAllowed(cls)
0276:                        && (registerAll
0277:                                || registeredPackages.containsKey(cls
0278:                                        .getPackage()) || hasRegisteredSuperClass(cls));
0279:            }
0280:
0281:            /**
0282:             * Returns true if {@link #registeredSuperClasses registeredSuperClasses}
0283:             * contains a super class of <CODE>cls</CODE>.
0284:             * 
0285:             * @param cls
0286:             * @return boolean
0287:             */
0288:            private boolean hasRegisteredSuperClass(Class cls) {
0289:                // check for all super classes of cls, 
0290:                // if it's in registeredSuperClasses. 
0291:
0292:                // the problem with checking the super classes is, that
0293:                // it ignores interfaces. so either an additional check
0294:                // for interfaces, or a painfull slow checking of all 
0295:                // registered super classes is required.
0296:
0297:                for (Class subClass = cls; null != subClass; subClass = subClass
0298:                        .getSuperclass())
0299:                    if (registeredSuperClasses.containsKey(subClass))
0300:                        return true;
0301:
0302:                Class[] interfaces = cls.getInterfaces();
0303:                for (int i = 0; i < interfaces.length; i++)
0304:                    if (hasRegisteredSuperClass(interfaces[i]))
0305:                        return true;
0306:
0307:                return false;
0308:            }
0309:
0310:            //-------------------------------------------------------------------------------------------------------
0311:            //
0312:            //-------------------------------------------------------------------------------------------------------
0313:
0314:            /**
0315:             * Creates an uninitialized instance of this class.
0316:             * private to force use of {@link #getInstance
0317:             * getInstance()} (Singelton Pattern).
0318:             */
0319:            private HotSwapClassRegister() {
0320:                rmv = new RegisterMethodVisitorImpl();
0321:            }
0322:
0323:            /**
0324:             * Returns the instance of this class (this is a
0325:             * 'singelton', so there's only one instance).
0326:             * 
0327:             * @return HotSwapClassRegister instance.
0328:             */
0329:            public static HotSwapClassRegister getInstance() {
0330:                if (null == instance)
0331:                    instance = new HotSwapClassRegister();
0332:                return instance;
0333:            }
0334:
0335:            /**
0336:             * Registers the JVMAspectInterface (must be called before the first
0337:             * call to {@link #scan scan(java.lang.Class)}.
0338:             * 
0339:             * @param aspectInterface
0340:             * @param packagePrefixes
0341:             * @param openWorldAssumption
0342:             */
0343:            protected static void setAspectInterface(
0344:                    HotSwapAspectInterfaceImpl aspectInterface,
0345:                    String[] packagePrefixes, boolean openWorldAssumption) {
0346:                HotSwapClassRegister.aspectInterface = aspectInterface;
0347:                HotSwapClassRegister.openWorldAssumption = openWorldAssumption;
0348:                worldPrefixes = new HashSet(Arrays.asList(packagePrefixes));
0349:            }
0350:
0351:            //--------------------------------------------------------------------------------------------------
0352:            // Public Methods to trigger scanning of classes (register them for scanning)
0353:            //--------------------------------------------------------------------------------------------------
0354:            /**
0355:             * Notification that the class <code>cls</code> will be loaded.
0356:             * Scanns the cls if required, and triggers weaving of the class
0357:             * if it contains any join point.
0358:             * 
0359:             * @param cls	the class that has been prepared
0360:             */
0361:            public void classLoaded(Class cls) {
0362:                synchronized (scannedClasses) {
0363:                    if (isScanningRequired(cls)) {
0364:                        try {
0365:                            //System.out.println("on class load: Scanning: " + cls.getName() );
0366:                            instance.scanConstantPool(cls);
0367:                            // redefine methods if required
0368:                            // this must be done after the class was
0369:                            // loaded!
0370:                            if (instance.weave) {
0371:                                aspectInterface.resumeNotification(Thread
0372:                                        .currentThread());
0373:                                //System.out.println("on class load: Weaving: " + cls.getName() );
0374:                            }
0375:                        } catch (ClassNotFoundException e) {
0376:                            System.err.println("can not load classfile for "
0377:                                    + cls.getName());
0378:                            System.err.println(e.getMessage());
0379:                        }
0380:                    }
0381:                }
0382:            }
0383:
0384:            /**
0385:             * Registers a class, which may hold a field, method call or
0386:             * exception join point. This class will be scanned immediatly
0387:             * and all potential join points will be registered.
0388:             * 
0389:             * @param cls class that may contain join points.
0390:             * @throws java.io.IOException can not read the class file.
0391:             */
0392:            public void registrationRequest(Class cls)
0393:                    throws ClassNotFoundException {
0394:                synchronized (scannedClasses) {
0395:                    if ((!scannedConstantPools.containsKey(cls))
0396:                            && isScanningAllowed(cls)) {
0397:                        scanConstantPool(cls);
0398:                    }
0399:                }
0400:            }
0401:
0402:            /**
0403:             * Registers a package, which may contain classes that may
0404:             * hold a field, method call or exception join point. This classes 
0405:             * will be scanned and all potential join points will be registrated.
0406:             * <p>
0407:             * New loaded classes will alse be scaned until {@link #removeRequestAll 
0408:             * removeRequestAll()} is called.
0409:             * 
0410:             * @param pkg
0411:             */
0412:            public void registrationRequest(Package pkg) {
0413:                if (null == aspectInterface)
0414:                    throw new JVMAIRuntimeException(this .getClass().getName()
0415:                            + ".setAspectInterface() must be called first");
0416:
0417:                Integer regCount = (Integer) registeredPackages.get(pkg);
0418:                if (null == regCount) {
0419:                    if (!registerAll) {
0420:                        String packageName = pkg.getName();
0421:
0422:                        // get all loaded classes
0423:                        List loadedClasses = aspectInterface.getLoadedClasses();
0424:                        Iterator iter = loadedClasses.iterator();
0425:                        while (iter.hasNext()) {
0426:                            Class loadedClass = (Class) iter.next();
0427:                            // look if the class belongs to pkg
0428:                            if (loadedClass.getName().startsWith(packageName)) {
0429:                                try {
0430:                                    registrationRequest(loadedClass);
0431:                                } catch (ClassNotFoundException e) {
0432:                                    // just report the error
0433:                                    System.err
0434:                                            .println(this .getClass().getName()
0435:                                                    + ".registrationRequest(Package): Could not read class file "
0436:                                                    + loadedClass.getName());
0437:                                    System.err.println("->	" + e.getMessage());
0438:                                }
0439:                            }
0440:                        }
0441:                    }
0442:                    registeredPackages.put(pkg, new Integer(1));
0443:                } else
0444:                    registeredPackages.put(pkg, new Integer(
0445:                            regCount.intValue() + 1));
0446:            }
0447:
0448:            /**
0449:             * Scans all loaded subclasses of <CODE>cls</CODE> for
0450:             * potential join points.
0451:             * <P>
0452:             * New loaded classes will also be scanned.
0453:             * 
0454:             * @param cls
0455:             */
0456:            public void registrationRequestSubClasses(Class cls) {
0457:                if (null == aspectInterface)
0458:                    throw new JVMAIRuntimeException(this .getClass().getName()
0459:                            + ".setAspectInterface() must be called first");
0460:
0461:                Integer regCount = (Integer) registeredSuperClasses.get(cls);
0462:                if (null == regCount) {
0463:                    if (!registerAll) {
0464:                        List loadedClasses = aspectInterface.getLoadedClasses();
0465:                        Iterator iter = loadedClasses.iterator();
0466:                        while (iter.hasNext()) {
0467:                            Class loadedClass = (Class) iter.next();
0468:                            if (cls.isAssignableFrom(loadedClass))
0469:                                try {
0470:                                    registrationRequest(loadedClass);
0471:                                } catch (ClassNotFoundException e) {
0472:                                    // just report the error
0473:                                    System.err
0474:                                            .println(this .getClass().getName()
0475:                                                    + ".registrationRequestSubClasses(Class): Could not read class file "
0476:                                                    + loadedClass.getName());
0477:                                    System.err.println("->	" + e.getMessage());
0478:                                }
0479:                        }
0480:                    }
0481:                    registeredSuperClasses.put(cls, new Integer(1));
0482:                } else {
0483:                    registeredSuperClasses.put(cls, new Integer(regCount
0484:                            .intValue() + 1));
0485:                }
0486:            }
0487:
0488:            /**
0489:             * Scans all loaded classes for potential field, method call and exception
0490:             * join points.
0491:             * <P>
0492:             * New loaded classes will alse be scaned until {@link #removeRequestAll 
0493:             * removeRequestAll()} is called.
0494:             */
0495:            public void registrationRequestAll() {
0496:                if (null == aspectInterface)
0497:                    throw new JVMAIRuntimeException(this .getClass().getName()
0498:                            + ".setAspectInterface() must be called first");
0499:
0500:                registerAllCount++;
0501:
0502:                if (!registerAll) {
0503:                    registerAll = true;
0504:
0505:                    // registrationRequest all loaded classes
0506:                    List loadedClasses = aspectInterface.getLoadedClasses();
0507:                    Iterator iter = loadedClasses.iterator();
0508:                    while (iter.hasNext()) {
0509:                        Class loadedClass = (Class) iter.next();
0510:                        try {
0511:                            registrationRequest(loadedClass);
0512:                        } catch (ClassNotFoundException e) {
0513:                            // just report the error
0514:                            //System.err.println(this.getClass().getName() + ".registrationRequestAll(): Could not read class file " + loadedClass.getName() );
0515:                            //System.err.println( "->	" + e.getMessage() );
0516:                        }
0517:                    }
0518:                }
0519:            }
0520:
0521:            /**
0522:             * Just for convinience, this method does nothing.
0523:             * @param cls
0524:             */
0525:            public void removeRequest(Class cls) {
0526:                // Nothing to do
0527:            }
0528:
0529:            /**
0530:             * Stops scanning and registration of new loaded classes
0531:             * belonging to Package <CODE>pkg</CODE>. If {@link #registrationRequestAll
0532:             * registrationRequestAll()} is set, the classes will still be scanned until
0533:             * {@link #removeRequestAll removeRequestAll()} is called.
0534:             * 
0535:             * @param pkg
0536:             */
0537:            public void removeRequest(Package pkg) {
0538:                Integer regCount = (Integer) registeredPackages.get(pkg);
0539:                if (null != regCount && (1 < regCount.intValue()))
0540:                    registeredPackages.put(pkg, new Integer(
0541:                            regCount.intValue() - 1));
0542:                else
0543:                    registeredPackages.remove(pkg);
0544:            }
0545:
0546:            /**
0547:             * Stops scanning and registration of new loaded sub classes
0548:             * of <CODE>cls</CODE>. If {@link #registrationRequestAll registrationRequestAll()} 
0549:             * is set, the classes will still be scanned until {@link 
0550:             * #removeRequestAll removeRequestAll()} is called.
0551:             * 
0552:             * @param cls
0553:             */
0554:            public void removeRequestSubClass(Class cls) {
0555:                Integer regCount = (Integer) registeredSuperClasses.get(cls);
0556:                if (null != regCount && (1 < regCount.intValue()))
0557:                    registeredSuperClasses.put(cls, new Integer(regCount
0558:                            .intValue() - 1));
0559:                else
0560:                    registeredSuperClasses.remove(cls);
0561:            }
0562:
0563:            /**
0564:             * Stops scanning and registration of all new loaded classes.
0565:             */
0566:            public void removeRequestAll() {
0567:                if (1 < registerAllCount) {
0568:                    registerAllCount = 0;
0569:                    registerAll = false;
0570:                } else
0571:                    registerAllCount--;
0572:            }
0573:
0574:            /**
0575:             * Clears all registrations and registration requests
0576:             */
0577:            public void reset() {
0578:                // 1. Stop scanning of new loaded classes
0579:                registerAll = false;
0580:                registerAllCount = 0;
0581:                registeredPackages.clear();
0582:                registeredSuperClasses.clear();
0583:                // 2. Clear informations
0584:                synchronized (scannedClasses) {
0585:                    knownFieldReferences.clear();
0586:                    //knownMethodReferences.clear();
0587:                    //knownExceptionCatches.clear();
0588:                    //knownExceptionThrows.clear();
0589:                    knownFieldAccesses.clear();
0590:                    knownFieldModifiers.clear();
0591:                    //knownMethodCalls.clear();
0592:                    scannedClasses.clear();
0593:                    scannedConstantPools.clear();
0594:                }
0595:            }
0596:
0597:            //---------------------------------------------------------------------------------------------------------------------------
0598:            // Fields and Methods for scanning class files
0599:            //---------------------------------------------------------------------------------------------------------------------------
0600:
0601:            private boolean weave;
0602:
0603:            /**
0604:             * This object does the work: Scanning the methods and reporting
0605:             * the mappings.
0606:             */
0607:            private RegisterMethodVisitorImpl rmv;
0608:
0609:            /**
0610:             * BCEL constant pool object for the class. 
0611:             */
0612:            private ConstantPoolGen cpGen;
0613:
0614:            /**
0615:             * Scans the constant pool of class <CODE>cls</CODE> for method and field
0616:             * references.
0617:             * 
0618:             * @param cls the class that's constant pool should get scanned.
0619:             * @throws ClassNotFoundException can not find the file defining the class.
0620:             */
0621:            protected void scanConstantPool(Class cls)
0622:                    throws ClassNotFoundException {
0623:                if (scannedClasses.containsKey(cls))
0624:                    return;
0625:
0626:                String className = cls.getName();
0627:                // 0. Get the BCEL constant pool object
0628:                JavaClass bcelClass = HotSwapAspectInterfaceImpl
0629:                        .getBCELClassDefinition(cls);
0630:                ConstantPool constantPool = bcelClass.getConstantPool();
0631:                Constant[] constants = constantPool.getConstantPool();
0632:
0633:                // Remember the class, so it doesn't get scanned again.
0634:                scannedConstantPools.put(cls, dummyValue);
0635:
0636:                // 1. Iterate through all constant pool entries
0637:                for (int i = 0; i < constants.length; i++) {
0638:                    Constant con = constants[i];
0639:
0640:                    // 2. Get field and method references 
0641:                    if (con instanceof  ConstantCP) {
0642:                        ConstantCP cp = (ConstantCP) con;
0643:                        ConstantNameAndType nt = (ConstantNameAndType) constants[cp
0644:                                .getNameAndTypeIndex()];
0645:                        // 3. Create a unique key (string) for the field or method
0646:                        String key = cp.getClass(constantPool) + '#'
0647:                                + nt.getName(constantPool) + '#'
0648:                                + nt.getSignature(constantPool);
0649:
0650:                        if (con instanceof  ConstantFieldref) {
0651:                            // Constant is a field reference
0652:
0653:                            // 4. Look if the field must be woven
0654:                            if (HotSwapFieldWeaver.weaverNames.containsKey(key)) {
0655:                                // Scan all methods and return
0656:                                //System.out.println("ClassRegister.scanConstantPool: found key: " + key);
0657:                                scan(cls);
0658:                                return;
0659:                            }
0660:                            // 5. Get the entry for the field
0661:                            Collection col = (Collection) knownFieldReferences
0662:                                    .get(key);
0663:                            if (null == col) {
0664:                                // 5a. Create a new entry for the field
0665:                                col = new LinkedList();
0666:                                knownFieldReferences.put(key, col);
0667:                            }
0668:                            // 6. Add a reference to cls to the entry
0669:                            col.add(new WeakReference(cls));
0670:                        }
0671:
0672:                        // The lines below will be used for the implementation of
0673:                        // Method call join points
0674:                        //
0675:                        //				else {
0676:                        //					// Constant is a method reference (ConstantMethodref or ConstantInterfaceMethodref)
0677:                        //					// 4. Get the entry for the method
0678:                        //					Collection col = (Collection) knownMethodReferences.get( key );
0679:                        //					if( null == col ) {
0680:                        //						// 4a. Create a new entry for the method
0681:                        //						col = new LinkedList();
0682:                        //						knownMethodReferences.put( key, col );
0683:                        //					}
0684:                        //					// 5. Add cls to the entry
0685:                        //					col.add( new WeakReference( cls ) );
0686:                        //				}
0687:                    }
0688:
0689:                }
0690:            }
0691:
0692:            /**
0693:             * Scans the method byte codes of a Collection of classes. Already scanned classes
0694:             * will be ignored.
0695:             * 
0696:             * @param cls Collection holding {@link java.lang.Class Class} objects, for the classes
0697:             * 					that will be scanned.
0698:             */
0699:            public void scanClasses(List cls) {
0700:                if (null == cls)
0701:                    return;
0702:
0703:                ListIterator iter = cls.listIterator();
0704:                while (iter.hasNext()) {
0705:                    Class klass = (Class) ((WeakReference) iter.next()).get();
0706:                    if (null == klass)
0707:                        iter.remove();
0708:                    else if (!scannedClasses.containsKey(klass))
0709:                        try {
0710:                            scan(klass);
0711:                        } catch (ClassNotFoundException e) {
0712:                            System.err
0713:                                    .println("HotSwapClassRegister.scanClasses: "
0714:                                            + e.getMessage());
0715:                        }
0716:                }
0717:            }
0718:
0719:            /**
0720:             * Scans the target method for field accesses, field modifications,
0721:             * catched exceptions, method calls and method returns, and registers
0722:             * all found actions to the according map.
0723:             * 
0724:             * @param cls
0725:             * @throws java.io.IOException can not read the class file
0726:             */
0727:            protected void scan(Class cls) throws ClassNotFoundException {
0728:                weave = false;
0729:
0730:                String className = cls.getName();
0731:
0732:                // 1. Get the BCEL JavaClass object for cls
0733:                JavaClass bcelClass;
0734:                bcelClass = HotSwapAspectInterfaceImpl
0735:                        .getBCELClassDefinition(cls);
0736:                // The constant pool is common for all methods belonging to a class, so we store it
0737:                // here to make it accessible to all RegisterMethodVisitors
0738:                cpGen = new ConstantPoolGen(bcelClass.getConstantPool());
0739:
0740:                // 2. Scan each method defined in the class file
0741:                org.apache.bcel.classfile.Method[] methods = bcelClass
0742:                        .getMethods();
0743:
0744:                for (int j = 0; j < methods.length; j++) {
0745:                    org.apache.bcel.classfile.Method method = methods[j];
0746:                    if ((!method.isAbstract()) && (!method.isNative())) {
0747:                        MethodGen methodGen = new MethodGen(methods[j],
0748:                                className, cpGen);
0749:                        rmv.init(methodGen/*, entries, declMembers[j]*/);
0750:                        rmv.go();
0751:                    }
0752:                }
0753:                cpGen = null;
0754:                scannedClasses.put(cls, dummyValue);
0755:            }
0756:
0757:            //------------------------------------------------------------------------------------------------------------
0758:            // Inner class for scaning the method bodies.
0759:            //------------------------------------------------------------------------------------------------------------
0760:
0761:            /**
0762:             * BCEL InstructionList visitor implementation, which registers all
0763:             * field accesses, field modifications, potetial exception throws
0764:             * (except for JVMExceptions, which may be thrown anywhere)
0765:             * and method calls found in the InstructionList.
0766:             */
0767:            class RegisterMethodVisitorImpl extends EmptyVisitor {
0768:                /**
0769:                 * List of instructions (method body)
0770:                 */
0771:                private InstructionList instList;
0772:                /**
0773:                 * String holding the class name and the method name of the
0774:                 * analyzed method separated by an # and the signature.
0775:                 * Used as key for registering actions.
0776:                 */
0777:                private String key;
0778:                /**
0779:                 * Temporary instruction handle. References the actual
0780:                 * instruction while iterating through instList.
0781:                 */
0782:                private InstructionHandle handle;
0783:
0784:                /**
0785:                 * Initialzes this object. The same object may be initialzed 
0786:                 * multiple times.
0787:                 * 
0788:                 * @param mg MethodGen for the target method that should be
0789:                 * 			scaned. 
0790:                 */
0791:                void init(MethodGen mg) {
0792:                    instList = mg.getInstructionList();
0793:
0794:                    key = mg.getClassName() + "#" + mg.getName() + '#'
0795:                            + mg.getSignature() + (mg.isStatic() ? "#" : "");
0796:                }
0797:
0798:                /**
0799:                 * Scan the target method, and registers any occourences of
0800:                 * field manipulations, method calls and exception throws
0801:                 */
0802:                public synchronized void go() {
0803:                    if (null == instList)
0804:                        return;
0805:
0806:                    handle = instList.getStart();
0807:                    while (null != handle) {
0808:                        handle.getInstruction().accept(this );
0809:                        handle = handle.getNext();
0810:                    }
0811:
0812:                    instList.dispose();
0813:                }
0814:
0815:                // Exceptions and method calls are not yet implemented
0816:
0817:                //		public void visitATHROW(ATHROW obj) {
0818:                //			Class[] exceptions = obj.getExceptions();
0819:                //			for( int i = 0; i < exceptions.length; i++ ) {
0820:                //				Class exc = exceptions[i];
0821:                //				// String key = exc.getName();
0822:                //				List mws = (List) knownExceptionThrows.get( exc );
0823:                //				if( null == mws ) {
0824:                //					mws = new LinkedList();
0825:                //					knownExceptionThrows.put( exc, mws );
0826:                //				}
0827:                //				mws.add( key );
0828:                //				entries.add( mws );
0829:                //			}
0830:                //		}
0831:
0832:                //		/**
0833:                //		 * Instruction may throw an exception.
0834:                //		 * 
0835:                //		 * Note: this registers all potential exception throws, not
0836:                //		 * 			only the declared throw instructions.
0837:                //		 */
0838:                //		public void	visitExceptionThrower(ExceptionThrower obj) {
0839:                //			// Excepetions thrown by InvokeInstruction mostly are thrown at
0840:                //			// an other method.
0841:                //			if( obj instanceof InvokeInstruction ) {
0842:                //				// TODO: implemention that avoid repeated calls
0843:                //			}
0844:                //		
0845:                //			Class[] exceptions = obj.getExceptions();
0846:                //			if( obj instanceof ATHROW)
0847:                //				// Explicite exception throws
0848:                //				for( int i = 0; i < exceptions.length; i++ ) {
0849:                //					Class exc = exceptions[i];
0850:                //					// String key = exc.getName();
0851:                //					List mws = (List) knownExceptionThrows.get( exc );
0852:                //					if( null == mws ) {
0853:                //						mws = new LinkedList();
0854:                //						knownExceptionThrows.put( exc, mws );
0855:                //					}
0856:                //					mws.add( key );
0857:                //					entries.add( mws );
0858:                //				}
0859:                //			else
0860:                //				// Instructions that may throw an exception
0861:                //				for( int i = 0; i < exceptions.length; i++ ) {
0862:                //					Class exc = exceptions[i];
0863:                //					List mws = (List) knownPotentialExceptionThrows.get( exc );
0864:                //					if( null == mws ) {
0865:                //						mws = new LinkedList();
0866:                //						knownPotentialExceptionThrows.put( exc, mws );
0867:                //					}
0868:                //					mws.add( key );
0869:                //					entries.add( mws );
0870:                //				}
0871:                //		}
0872:                /**
0873:                 * Instruction accesses a member field.
0874:                 */
0875:                public void visitGETFIELD(GETFIELD obj) {
0876:                    doVisitFieldAccess(obj, false);
0877:                }
0878:
0879:                /**
0880:                 * Instruction accesses a static field.
0881:                 */
0882:                public void visitGETSTATIC(GETSTATIC obj) {
0883:                    doVisitFieldAccess(obj, true);
0884:                }
0885:
0886:                /**
0887:                 * Instruction modifies a member field.
0888:                 */
0889:                public void visitPUTFIELD(PUTFIELD obj) {
0890:                    doVisitFieldModification(obj, false);
0891:                }
0892:
0893:                /**
0894:                 * Instruction modifies a static field.
0895:                 */
0896:                public void visitPUTSTATIC(PUTSTATIC obj) {
0897:                    doVisitFieldModification(obj, true);
0898:                }
0899:
0900:                //		/**
0901:                //		 * Instruction calls a method.
0902:                //		 */
0903:                //		public void visitInvokeInstruction(InvokeInstruction obj) {
0904:                //			Member method;
0905:                //			try{ method = aspectInterface.getMethodFromString( obj.getReferenceType(cpGen).toString(), obj.getName(cpGen), obj.getSignature(cpGen), obj instanceof INVOKESTATIC ); }
0906:                //			catch( Exception e ) { throw new JVMAIRuntimeException("can not resolve method: " + obj.getReferenceType(cpGen).toString() + "." + obj.getName(cpGen)); }
0907:                //			List mws = (List) knownMethodCalls.get( method );
0908:                //			if( null == mws ) {
0909:                //				mws = new LinkedList();
0910:                //				knownMethodCalls.put( method, mws );
0911:                //			}
0912:                //			mws.add( key );
0913:                //			entries.add( mws );
0914:                //			
0915:                //			// TODO: register also the method call weaver
0916:                //		}
0917:
0918:                //		/**
0919:                //		 * Instruction may call a constructor.
0920:                //		 */
0921:                //		public void	visitNEW(NEW obj) {
0922:                //		}
0923:
0924:                private void doVisitFieldAccess(FieldInstruction obj,
0925:                        boolean isStatic) {
0926:                    String fkey = obj.getReferenceType(cpGen).toString() + '#'
0927:                            + obj.getFieldName(cpGen) + '#'
0928:                            + obj.getSignature(cpGen);
0929:                    // 1. Register the field to knownFieldAccesses
0930:
0931:                    List mws = (List) knownFieldAccesses.get(fkey);
0932:                    if (null == mws) {
0933:                        mws = new LinkedList();
0934:                        knownFieldAccesses.put(fkey, mws);
0935:                    }
0936:                    mws.add(key);
0937:
0938:                    // 2. Register the field to the MethodWeaver for this method,
0939:                    //    if there's a watch for it.
0940:                    HotSwapFieldWeaver fw = (HotSwapFieldWeaver) HotSwapFieldWeaver.weaverNames
0941:                            .get(fkey);
0942:                    if (null != fw
0943:                            && (HotSwapFieldWeaver.FW_ACCESS_ENABLED & fw.status) > 0) {
0944:                        // Weave method
0945:                        MethodWeaver mw;
0946:                        try {
0947:                            mw = HotSwapClassWeaver
0948:                                    .getWeaver(HotSwapAspectInterfaceImpl
0949:                                            .getMethodFromString(key));
0950:                        } catch (ClassNotFoundException e) {
0951:                            throw new JVMAIRuntimeException(
0952:                                    "scanning a class file, but can not find the class: "
0953:                                            + e.getMessage());
0954:                        }
0955:                        mw.addFieldAccessor(fw);
0956:                        weave = true;
0957:                    }
0958:                }
0959:
0960:                private void doVisitFieldModification(FieldInstruction obj,
0961:                        boolean isStatic) {
0962:                    // 1. Register the field to knownFieldModifications
0963:                    String fkey = obj.getReferenceType(cpGen).toString() + '#'
0964:                            + obj.getFieldName(cpGen) + '#'
0965:                            + obj.getSignature(cpGen);
0966:
0967:                    List mws = (List) knownFieldModifiers.get(fkey);
0968:                    if (null == mws) {
0969:                        mws = new LinkedList();
0970:                        knownFieldModifiers.put(fkey, mws);
0971:                    }
0972:                    mws.add(key);
0973:
0974:                    // 2. Register the field to the MethodWeaver for this method,
0975:                    //    if there's a watch for it.
0976:                    HotSwapFieldWeaver fw = (HotSwapFieldWeaver) HotSwapFieldWeaver.weaverNames
0977:                            .get(fkey);
0978:                    if (null != fw
0979:                            && (HotSwapFieldWeaver.FW_MODIFICATION_ENABLED & fw.status) > 0) {
0980:                        // Weave method
0981:                        MethodWeaver mw;
0982:                        try {
0983:                            mw = HotSwapClassWeaver
0984:                                    .getWeaver(HotSwapAspectInterfaceImpl
0985:                                            .getMethodFromString(key));
0986:                        } catch (ClassNotFoundException e) {
0987:                            throw new JVMAIRuntimeException(
0988:                                    "scanning a class file, but can not find the class: "
0989:                                            + e.getMessage());
0990:                        }
0991:                        mw.addFieldModifier(fw);
0992:                        weave = true;
0993:                    }
0994:                }
0995:
0996:                private Field resolveFieldName(FieldInstruction obj,
0997:                        boolean isStatic) {
0998:                    try {
0999:                        return HotSwapAspectInterfaceImpl.getFieldFromString(
1000:                                obj.getReferenceType(cpGen).toString(), obj
1001:                                        .getName(cpGen), obj
1002:                                        .getSignature(cpGen), isStatic);
1003:                    } catch (Exception e) {
1004:                        throw new JVMAIRuntimeException(
1005:                                "can not resolve field "
1006:                                        + obj.getReferenceType(cpGen)
1007:                                                .toString() + "."
1008:                                        + obj.getName(cpGen) + ": "
1009:                                        + e.getClass().getName() + ": "
1010:                                        + e.getMessage());
1011:                    }
1012:                }
1013:            }
1014:
1015:        }
1016:
1017:        //======================================================================
1018:        //
1019:        // $Log$
1020:        //
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.