Source Code Cross Referenced for Cglib2AopProxy.java in  » J2EE » spring-framework-2.0.6 » org » springframework » aop » framework » 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 » J2EE » spring framework 2.0.6 » org.springframework.aop.framework 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2002-2007 the original author or authors.
0003:         *
0004:         * Licensed under the Apache License, Version 2.0 (the "License");
0005:         * you may not use this file except in compliance with the License.
0006:         * You may obtain a copy of the License at
0007:         *
0008:         *      http://www.apache.org/licenses/LICENSE-2.0
0009:         *
0010:         * Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS,
0012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         * See the License for the specific language governing permissions and
0014:         * limitations under the License.
0015:         */
0016:
0017:        package org.springframework.aop.framework;
0018:
0019:        import java.io.Serializable;
0020:        import java.lang.reflect.Method;
0021:        import java.lang.reflect.Modifier;
0022:        import java.lang.reflect.UndeclaredThrowableException;
0023:        import java.util.HashMap;
0024:        import java.util.HashSet;
0025:        import java.util.List;
0026:        import java.util.Map;
0027:        import java.util.Set;
0028:
0029:        import net.sf.cglib.core.CodeGenerationException;
0030:        import net.sf.cglib.proxy.Callback;
0031:        import net.sf.cglib.proxy.CallbackFilter;
0032:        import net.sf.cglib.proxy.Dispatcher;
0033:        import net.sf.cglib.proxy.Enhancer;
0034:        import net.sf.cglib.proxy.Factory;
0035:        import net.sf.cglib.proxy.MethodInterceptor;
0036:        import net.sf.cglib.proxy.MethodProxy;
0037:        import net.sf.cglib.proxy.NoOp;
0038:        import net.sf.cglib.transform.impl.UndeclaredThrowableStrategy;
0039:        import org.aopalliance.aop.Advice;
0040:        import org.aopalliance.intercept.MethodInvocation;
0041:        import org.apache.commons.logging.Log;
0042:        import org.apache.commons.logging.LogFactory;
0043:
0044:        import org.springframework.aop.Advisor;
0045:        import org.springframework.aop.PointcutAdvisor;
0046:        import org.springframework.aop.RawTargetAccess;
0047:        import org.springframework.aop.support.AopUtils;
0048:        import org.springframework.util.Assert;
0049:        import org.springframework.util.ObjectUtils;
0050:
0051:        /**
0052:         * CGLIB2-based {@link AopProxy} implementation for the Spring AOP framework.
0053:         *
0054:         * <p><i>Requires CGLIB 2.1+ on the classpath.</i>.
0055:         * As of Spring 2.0, earlier CGLIB versions are not supported anymore.
0056:         *
0057:         * <p>Objects of this type should be obtained through proxy factories,
0058:         * configured by an {@link AdvisedSupport} object. This class is internal
0059:         * to Spring's AOP framework and need not be used directly by client code.
0060:         *
0061:         * <p>{@link DefaultAopProxyFactory} will automatically create CGLIB2-based
0062:         * proxies if necessary, for example in case of proxying a target class
0063:         * (see the {@link DefaultAopProxyFactory attendant javadoc} for details).
0064:         *
0065:         * <p>Proxies created using this class are thread-safe if the underlying
0066:         * (target) class is thread-safe.
0067:         *
0068:         * @author Rod Johnson
0069:         * @author Rob Harrop
0070:         * @author Juergen Hoeller
0071:         * @see net.sf.cglib.proxy.Enhancer
0072:         * @see AdvisedSupport#setProxyTargetClass
0073:         * @see DefaultAopProxyFactory
0074:         */
0075:        final class Cglib2AopProxy implements  AopProxy, Serializable {
0076:
0077:            // Constants for CGLIB callback array indices
0078:            private static final int AOP_PROXY = 0;
0079:            private static final int INVOKE_TARGET = 1;
0080:            private static final int NO_OVERRIDE = 2;
0081:            private static final int DISPATCH_TARGET = 3;
0082:            private static final int DISPATCH_ADVISED = 4;
0083:            private static final int INVOKE_EQUALS = 5;
0084:            private static final int INVOKE_HASHCODE = 6;
0085:
0086:            /** Logger available to subclasses; static to optimize serialization */
0087:            protected final static Log logger = LogFactory
0088:                    .getLog(Cglib2AopProxy.class);
0089:
0090:            /** Keeps track of the Classes that we have validated for final methods */
0091:            private static final Set validatedClasses = new HashSet();
0092:
0093:            /** The configuration used to configure this proxy */
0094:            protected final AdvisedSupport advised;
0095:
0096:            private Object[] constructorArgs;
0097:
0098:            private Class[] constructorArgTypes;
0099:
0100:            /** Dispatcher used for methods on Advised */
0101:            private final transient AdvisedDispatcher advisedDispatcher;
0102:
0103:            private transient Map fixedInterceptorMap;
0104:
0105:            private transient int fixedInterceptorOffset;
0106:
0107:            /**
0108:             * Create a new Cglib2AopProxy for the given AOP configuration.
0109:             * @param config the AOP configuration as AdvisedSupport object
0110:             * @throws AopConfigException if the config is invalid. We try to throw an informative
0111:             * exception in this case, rather than let a mysterious failure happen later.
0112:             */
0113:            public Cglib2AopProxy(AdvisedSupport config)
0114:                    throws AopConfigException {
0115:                Assert.notNull(config, "AdvisedSupport must not be null");
0116:                if (config.getAdvisors().length == 0
0117:                        && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
0118:                    throw new AopConfigException(
0119:                            "No advisors and no TargetSource specified");
0120:                }
0121:                this .advised = config;
0122:                this .advisedDispatcher = new AdvisedDispatcher(this .advised);
0123:            }
0124:
0125:            /**
0126:             * Set constructor arguments to use for creating the proxy.
0127:             * @param constructorArgs the constructor argument values
0128:             * @param constructorArgTypes the constructor argument types
0129:             */
0130:            public void setConstructorArguments(Object[] constructorArgs,
0131:                    Class[] constructorArgTypes) {
0132:                if (constructorArgs == null || constructorArgTypes == null) {
0133:                    throw new IllegalArgumentException(
0134:                            "Both 'constructorArgs' and 'constructorArgTypes' need to be specified");
0135:                }
0136:                if (constructorArgs.length != constructorArgTypes.length) {
0137:                    throw new IllegalArgumentException(
0138:                            "Number of 'constructorArgs' ("
0139:                                    + constructorArgs.length
0140:                                    + ") must match number of 'constructorArgTypes' ("
0141:                                    + constructorArgTypes.length + ")");
0142:                }
0143:                this .constructorArgs = constructorArgs;
0144:                this .constructorArgTypes = constructorArgTypes;
0145:            }
0146:
0147:            public Object getProxy() {
0148:                return getProxy(null);
0149:            }
0150:
0151:            public Object getProxy(ClassLoader classLoader) {
0152:                if (logger.isDebugEnabled()) {
0153:                    logger.debug("Creating CGLIB2 proxy: target source is "
0154:                            + this .advised.getTargetSource());
0155:                }
0156:
0157:                Enhancer enhancer = createEnhancer();
0158:                try {
0159:                    // Create proxy in specific ClassLoader, if given.
0160:                    if (classLoader != null) {
0161:                        enhancer.setClassLoader(classLoader);
0162:                    }
0163:
0164:                    Class rootClass = this .advised.getTargetClass();
0165:                    Assert
0166:                            .state(rootClass != null,
0167:                                    "Target class must be available for creating a CGLIB proxy");
0168:                    Class proxySuperClass = rootClass;
0169:
0170:                    if (AopUtils.isCglibProxyClass(rootClass)) {
0171:                        proxySuperClass = rootClass.getSuperclass();
0172:                        Class[] additionalInterfaces = rootClass
0173:                                .getInterfaces();
0174:                        for (int i = 0; i < additionalInterfaces.length; i++) {
0175:                            Class additionalInterface = additionalInterfaces[i];
0176:                            this .advised.addInterface(additionalInterface);
0177:                        }
0178:                    }
0179:
0180:                    // Validate the class, writing log messages as necessary.
0181:                    validateClassIfNecessary(proxySuperClass);
0182:
0183:                    enhancer.setSuperclass(proxySuperClass);
0184:                    enhancer.setStrategy(new UndeclaredThrowableStrategy(
0185:                            UndeclaredThrowableException.class));
0186:                    enhancer.setInterfaces(AopProxyUtils
0187:                            .completeProxiedInterfaces(this .advised));
0188:                    enhancer.setInterceptDuringConstruction(false);
0189:
0190:                    Callback[] callbacks = getCallbacks(rootClass);
0191:                    enhancer.setCallbacks(callbacks);
0192:                    enhancer.setCallbackFilter(new ProxyCallbackFilter(
0193:                            this .advised, this .fixedInterceptorMap,
0194:                            this .fixedInterceptorOffset));
0195:
0196:                    Class[] types = new Class[callbacks.length];
0197:                    for (int x = 0; x < types.length; x++) {
0198:                        types[x] = callbacks[x].getClass();
0199:                    }
0200:                    enhancer.setCallbackTypes(types);
0201:
0202:                    // Generate the proxy class and create a proxy instance.
0203:                    Object proxy;
0204:                    if (this .constructorArgs != null) {
0205:                        proxy = enhancer.create(this .constructorArgTypes,
0206:                                this .constructorArgs);
0207:                    } else {
0208:                        proxy = enhancer.create();
0209:                    }
0210:
0211:                    return proxy;
0212:                } catch (CodeGenerationException ex) {
0213:                    throw new AopConfigException(
0214:                            "Couldn't generate CGLIB subclass of class ["
0215:                                    + this .advised.getTargetClass()
0216:                                    + "]: "
0217:                                    + "Common causes of this problem include using a final class or a non-visible class",
0218:                            ex);
0219:                } catch (IllegalArgumentException ex) {
0220:                    throw new AopConfigException(
0221:                            "Couldn't generate CGLIB subclass of class ["
0222:                                    + this .advised.getTargetClass()
0223:                                    + "]: "
0224:                                    + "Common causes of this problem include using a final class or a non-visible class",
0225:                            ex);
0226:                } catch (Exception ex) {
0227:                    // TargetSource.getTarget() failed
0228:                    throw new AopConfigException("Unexpected AOP exception", ex);
0229:                }
0230:            }
0231:
0232:            /**
0233:             * Creates the CGLIB {@link Enhancer}. Subclasses may wish to override this to return a custom
0234:             * {@link Enhancer} implementation.
0235:             */
0236:            protected Enhancer createEnhancer() {
0237:                return new Enhancer();
0238:            }
0239:
0240:            /**
0241:             * Checks to see whether the supplied <code>Class</code> has already been validated and
0242:             * validates it if not.
0243:             */
0244:            private void validateClassIfNecessary(Class proxySuperClass) {
0245:                if (logger.isWarnEnabled()) {
0246:                    synchronized (validatedClasses) {
0247:                        if (!validatedClasses.contains(proxySuperClass)) {
0248:                            doValidateClass(proxySuperClass);
0249:                            validatedClasses.add(proxySuperClass);
0250:                        }
0251:                    }
0252:                }
0253:            }
0254:
0255:            /**
0256:             * Checks for final methods on the <code>Class</code> and writes warnings to the log
0257:             * for each one found.
0258:             */
0259:            private void doValidateClass(Class proxySuperClass) {
0260:                Method[] methods = proxySuperClass.getMethods();
0261:                for (int i = 0; i < methods.length; i++) {
0262:                    Method method = methods[i];
0263:                    if (!Object.class.equals(method.getDeclaringClass())
0264:                            && Modifier.isFinal(method.getModifiers())) {
0265:                        logger
0266:                                .warn("Unable to proxy method ["
0267:                                        + method
0268:                                        + "] because it is final: "
0269:                                        + "All calls to this method via a proxy will be routed directly to the proxy.");
0270:                    }
0271:                }
0272:            }
0273:
0274:            private Callback[] getCallbacks(Class rootClass) throws Exception {
0275:                // Parameters used for optimisation choices...
0276:                boolean exposeProxy = this .advised.isExposeProxy();
0277:                boolean isFrozen = this .advised.isFrozen();
0278:                boolean isStatic = this .advised.getTargetSource().isStatic();
0279:
0280:                // Choose an "aop" interceptor (used for AOP calls).
0281:                Callback aopInterceptor = new DynamicAdvisedInterceptor(
0282:                        this .advised);
0283:
0284:                // Choose a "straight to target" interceptor. (used for calls that are
0285:                // unadvised but can return this). May be required to expose the proxy.
0286:                Callback targetInterceptor = null;
0287:
0288:                if (exposeProxy) {
0289:                    targetInterceptor = isStatic ? (Callback) new StaticUnadvisedExposedInterceptor(
0290:                            this .advised.getTargetSource().getTarget())
0291:                            : (Callback) new DynamicUnadvisedExposedInterceptor(
0292:                                    this .advised);
0293:                } else {
0294:                    targetInterceptor = isStatic ? (Callback) new StaticUnadvisedInterceptor(
0295:                            this .advised.getTargetSource().getTarget())
0296:                            : (Callback) new DynamicUnadvisedInterceptor(
0297:                                    this .advised);
0298:                }
0299:
0300:                // Choose a "direct to target" dispatcher (used for
0301:                // unadvised calls to static targets that cannot return this).
0302:                Callback targetDispatcher = isStatic ? (Callback) new StaticDispatcher(
0303:                        this .advised.getTargetSource().getTarget())
0304:                        : new SerializableNoOp();
0305:
0306:                Callback[] mainCallbacks = new Callback[] {
0307:                        aopInterceptor, // for normal advice
0308:                        targetInterceptor, // invoke target without considering advice, if optimized
0309:                        new SerializableNoOp(), // no override for methods mapped to this
0310:                        targetDispatcher, this .advisedDispatcher,
0311:                        new EqualsInterceptor(this .advised),
0312:                        new HashCodeInterceptor(this .advised) };
0313:
0314:                Callback[] callbacks;
0315:
0316:                // If the target is a static one and the advice chain is frozen,
0317:                // then we can make some optimisations by sending the AOP calls
0318:                // direct to the target using the fixed chain for that method.
0319:                if (isStatic && isFrozen) {
0320:                    Method[] methods = rootClass.getMethods();
0321:                    Callback[] fixedCallbacks = new Callback[methods.length];
0322:                    this .fixedInterceptorMap = new HashMap(methods.length);
0323:
0324:                    // TODO: small memory optimisation here (can skip creation for
0325:                    // methods with no advice)
0326:                    for (int x = 0; x < methods.length; x++) {
0327:                        List chain = this .advised
0328:                                .getInterceptorsAndDynamicInterceptionAdvice(
0329:                                        methods[x], rootClass);
0330:                        fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
0331:                                chain, this .advised.getTargetSource()
0332:                                        .getTarget(), this .advised
0333:                                        .getTargetClass());
0334:                        this .fixedInterceptorMap.put(methods[x].toString(),
0335:                                new Integer(x));
0336:                    }
0337:
0338:                    // Now copy both the callbacks from mainCallbacks
0339:                    // and fixedCallbacks into the callbacks array.
0340:                    callbacks = new Callback[mainCallbacks.length
0341:                            + fixedCallbacks.length];
0342:
0343:                    for (int x = 0; x < mainCallbacks.length; x++) {
0344:                        callbacks[x] = mainCallbacks[x];
0345:                    }
0346:
0347:                    for (int x = 0; x < fixedCallbacks.length; x++) {
0348:                        callbacks[x + mainCallbacks.length] = fixedCallbacks[x];
0349:                    }
0350:
0351:                    this .fixedInterceptorOffset = mainCallbacks.length;
0352:                } else {
0353:                    callbacks = mainCallbacks;
0354:                }
0355:                return callbacks;
0356:            }
0357:
0358:            /**
0359:             * Wrap a return of this if necessary to be the proxy
0360:             */
0361:            private static Object massageReturnTypeIfNecessary(Object proxy,
0362:                    Object target, Method method, Object retVal) {
0363:                // Massage return value if necessary
0364:                if (retVal != null
0365:                        && retVal == target
0366:                        && !RawTargetAccess.class.isAssignableFrom(method
0367:                                .getDeclaringClass())) {
0368:                    // Special case: it returned "this".
0369:                    // Note that we can't help if the target sets a reference
0370:                    // to itself in another returned object.
0371:                    retVal = proxy;
0372:                }
0373:                return retVal;
0374:            }
0375:
0376:            public boolean equals(Object other) {
0377:                return (this  == other || (other instanceof  Cglib2AopProxy && AopProxyUtils
0378:                        .equalsInProxy(this .advised,
0379:                                ((Cglib2AopProxy) other).advised)));
0380:            }
0381:
0382:            public int hashCode() {
0383:                return Cglib2AopProxy.class.hashCode() * 13
0384:                        + this .advised.getTargetSource().hashCode();
0385:            }
0386:
0387:            /**
0388:             * Serializable replacement for CGLIB's NoOp interface.
0389:             * Public to allow use elsewhere in the framework.
0390:             */
0391:            public static class SerializableNoOp implements  NoOp, Serializable {
0392:            }
0393:
0394:            /**
0395:             * Method interceptor used for static targets with no advice chain. The call
0396:             * is passed directly back to the target. Used when the proxy needs to be
0397:             * exposed and it can't be determined that the method won't return
0398:             * <code>this</code>.
0399:             */
0400:            private static class StaticUnadvisedInterceptor implements 
0401:                    MethodInterceptor, Serializable {
0402:
0403:                private final Object target;
0404:
0405:                public StaticUnadvisedInterceptor(Object target) {
0406:                    this .target = target;
0407:                }
0408:
0409:                public Object intercept(Object proxy, Method method,
0410:                        Object[] args, MethodProxy methodProxy)
0411:                        throws Throwable {
0412:                    Object retVal = methodProxy.invoke(this .target, args);
0413:                    return massageReturnTypeIfNecessary(proxy, this .target,
0414:                            method, retVal);
0415:                }
0416:            }
0417:
0418:            /**
0419:             * Method interceptor used for static targets with no advice chain, when the
0420:             * proxy is to be exposed.
0421:             */
0422:            private static class StaticUnadvisedExposedInterceptor implements 
0423:                    MethodInterceptor, Serializable {
0424:
0425:                private final Object target;
0426:
0427:                public StaticUnadvisedExposedInterceptor(Object target) {
0428:                    this .target = target;
0429:                }
0430:
0431:                public Object intercept(Object proxy, Method method,
0432:                        Object[] args, MethodProxy methodProxy)
0433:                        throws Throwable {
0434:                    Object oldProxy = null;
0435:                    try {
0436:                        oldProxy = AopContext.setCurrentProxy(proxy);
0437:                        Object retVal = methodProxy.invoke(this .target, args);
0438:                        return massageReturnTypeIfNecessary(proxy, this .target,
0439:                                method, retVal);
0440:                    } finally {
0441:                        AopContext.setCurrentProxy(oldProxy);
0442:                    }
0443:                }
0444:            }
0445:
0446:            /**
0447:             * Interceptor used to invoke a dynamic target without creating a method
0448:             * invocation or evaluating an advice chain. (We know there was no advice
0449:             * for this method.)
0450:             */
0451:            private static class DynamicUnadvisedInterceptor implements 
0452:                    MethodInterceptor, Serializable {
0453:
0454:                private final AdvisedSupport advised;
0455:
0456:                public DynamicUnadvisedInterceptor(AdvisedSupport advised) {
0457:                    this .advised = advised;
0458:                }
0459:
0460:                public Object intercept(Object proxy, Method method,
0461:                        Object[] args, MethodProxy methodProxy)
0462:                        throws Throwable {
0463:                    Object target = this .advised.getTargetSource().getTarget();
0464:                    try {
0465:                        Object retVal = methodProxy.invoke(target, args);
0466:                        return massageReturnTypeIfNecessary(proxy, target,
0467:                                method, retVal);
0468:                    } finally {
0469:                        this .advised.getTargetSource().releaseTarget(target);
0470:                    }
0471:                }
0472:            }
0473:
0474:            /**
0475:             * Interceptor for unadvised dynamic targets when the proxy needs exposing.
0476:             */
0477:            private static class DynamicUnadvisedExposedInterceptor implements 
0478:                    MethodInterceptor, Serializable {
0479:
0480:                private final AdvisedSupport advised;
0481:
0482:                public DynamicUnadvisedExposedInterceptor(AdvisedSupport advised) {
0483:                    this .advised = advised;
0484:                }
0485:
0486:                public Object intercept(Object proxy, Method method,
0487:                        Object[] args, MethodProxy methodProxy)
0488:                        throws Throwable {
0489:                    Object oldProxy = null;
0490:                    Object target = this .advised.getTargetSource().getTarget();
0491:                    try {
0492:                        oldProxy = AopContext.setCurrentProxy(proxy);
0493:                        Object retVal = methodProxy.invoke(target, args);
0494:                        return massageReturnTypeIfNecessary(proxy, target,
0495:                                method, retVal);
0496:                    } finally {
0497:                        AopContext.setCurrentProxy(oldProxy);
0498:                        this .advised.getTargetSource().releaseTarget(target);
0499:                    }
0500:                }
0501:            }
0502:
0503:            /**
0504:             * Dispatcher for a static target. Dispatcher is much faster than
0505:             * interceptor. This will be used whenever it can be determined that a
0506:             * method definitely does not return "this"
0507:             */
0508:            private static class StaticDispatcher implements  Dispatcher,
0509:                    Serializable {
0510:
0511:                private Object target;
0512:
0513:                public StaticDispatcher(Object target) {
0514:                    this .target = target;
0515:                }
0516:
0517:                public Object loadObject() {
0518:                    return this .target;
0519:                }
0520:            }
0521:
0522:            /**
0523:             * Dispatcher for any methods declared on the Advised class.
0524:             */
0525:            private static class AdvisedDispatcher implements  Dispatcher,
0526:                    Serializable {
0527:
0528:                private final AdvisedSupport advised;
0529:
0530:                public AdvisedDispatcher(AdvisedSupport advised) {
0531:                    this .advised = advised;
0532:                }
0533:
0534:                public Object loadObject() throws Exception {
0535:                    return this .advised;
0536:                }
0537:            }
0538:
0539:            /**
0540:             * Dispatcher for the <code>equals</code> method.
0541:             * Ensures that the method call is always handled by this class.
0542:             */
0543:            private static class EqualsInterceptor implements 
0544:                    MethodInterceptor, Serializable {
0545:
0546:                private final AdvisedSupport advised;
0547:
0548:                public EqualsInterceptor(AdvisedSupport advised) {
0549:                    this .advised = advised;
0550:                }
0551:
0552:                public Object intercept(Object proxy, Method method,
0553:                        Object[] args, MethodProxy methodProxy) {
0554:                    Object other = args[0];
0555:                    if (proxy == other) {
0556:                        return Boolean.TRUE;
0557:                    }
0558:                    AdvisedSupport otherAdvised = null;
0559:                    if (other instanceof  Factory) {
0560:                        Callback callback = ((Factory) other)
0561:                                .getCallback(INVOKE_EQUALS);
0562:                        if (!(callback instanceof  EqualsInterceptor)) {
0563:                            return Boolean.FALSE;
0564:                        }
0565:                        otherAdvised = ((EqualsInterceptor) callback).advised;
0566:                    } else {
0567:                        return Boolean.FALSE;
0568:                    }
0569:                    return (AopProxyUtils.equalsInProxy(this .advised,
0570:                            otherAdvised) ? Boolean.TRUE : Boolean.FALSE);
0571:                }
0572:            }
0573:
0574:            /**
0575:             * Dispatcher for the <code>hashCode</code> method.
0576:             * Ensures that the method call is always handled by this class.
0577:             */
0578:            private static class HashCodeInterceptor implements 
0579:                    MethodInterceptor, Serializable {
0580:
0581:                private final AdvisedSupport advised;
0582:
0583:                public HashCodeInterceptor(AdvisedSupport advised) {
0584:                    this .advised = advised;
0585:                }
0586:
0587:                public Object intercept(Object proxy, Method method,
0588:                        Object[] args, MethodProxy methodProxy) {
0589:                    return new Integer(Cglib2AopProxy.class.hashCode() * 13
0590:                            + this .advised.getTargetSource().hashCode());
0591:                }
0592:            }
0593:
0594:            /**
0595:             * Interceptor used specifically for advised methods on a frozen, static proxy.
0596:             */
0597:            private static class FixedChainStaticTargetInterceptor implements 
0598:                    MethodInterceptor, Serializable {
0599:
0600:                private final List adviceChain;
0601:
0602:                private final Object target;
0603:
0604:                private final Class targetClass;
0605:
0606:                public FixedChainStaticTargetInterceptor(List adviceChain,
0607:                        Object target, Class targetClass) {
0608:                    this .adviceChain = adviceChain;
0609:                    this .target = target;
0610:                    this .targetClass = targetClass;
0611:                }
0612:
0613:                public Object intercept(Object proxy, Method method,
0614:                        Object[] args, MethodProxy methodProxy)
0615:                        throws Throwable {
0616:                    Object retVal = null;
0617:                    MethodInvocation invocation = new CglibMethodInvocation(
0618:                            proxy, this .target, method, args, this .targetClass,
0619:                            this .adviceChain, methodProxy);
0620:                    // If we get here, we need to create a MethodInvocation.
0621:                    retVal = invocation.proceed();
0622:                    retVal = massageReturnTypeIfNecessary(proxy, this .target,
0623:                            method, retVal);
0624:                    return retVal;
0625:                }
0626:            }
0627:
0628:            /**
0629:             * General purpose AOP callback. Used when the target is dynamic or when the
0630:             * proxy is not frozen.
0631:             */
0632:            private static class DynamicAdvisedInterceptor implements 
0633:                    MethodInterceptor, Serializable {
0634:
0635:                private AdvisedSupport advised;
0636:
0637:                public DynamicAdvisedInterceptor(AdvisedSupport advised) {
0638:                    this .advised = advised;
0639:                }
0640:
0641:                public Object intercept(Object proxy, Method method,
0642:                        Object[] args, MethodProxy methodProxy)
0643:                        throws Throwable {
0644:                    MethodInvocation invocation = null;
0645:                    Object oldProxy = null;
0646:                    boolean setProxyContext = false;
0647:                    Class targetClass = null;
0648:                    Object target = null;
0649:                    try {
0650:                        Object retVal = null;
0651:                        if (this .advised.exposeProxy) {
0652:                            // Make invocation available if necessary.
0653:                            oldProxy = AopContext.setCurrentProxy(proxy);
0654:                            setProxyContext = true;
0655:                        }
0656:                        // May be <code>null</code>. Get as late as possible to minimize the time we
0657:                        // "own" the target, in case it comes from a pool.
0658:                        target = getTarget();
0659:                        if (target != null) {
0660:                            targetClass = target.getClass();
0661:                        }
0662:                        List chain = this .advised
0663:                                .getInterceptorsAndDynamicInterceptionAdvice(
0664:                                        method, targetClass);
0665:                        // Check whether we only have one InvokerInterceptor: that is,
0666:                        // no real advice, but just reflective invocation of the target.
0667:                        if (chain.isEmpty()
0668:                                && Modifier.isPublic(method.getModifiers())) {
0669:                            // We can skip creating a MethodInvocation: just invoke the target directly.
0670:                            // Note that the final invoker must be an InvokerInterceptor, so we know
0671:                            // it does nothing but a reflective operation on the target, and no hot
0672:                            // swapping or fancy proxying.
0673:                            retVal = methodProxy.invoke(target, args);
0674:                        } else {
0675:                            // We need to create a method invocation...
0676:                            invocation = new CglibMethodInvocation(proxy,
0677:                                    target, method, args, targetClass, chain,
0678:                                    methodProxy);
0679:                            // If we get here, we need to create a MethodInvocation.
0680:                            retVal = invocation.proceed();
0681:                        }
0682:
0683:                        retVal = massageReturnTypeIfNecessary(proxy, target,
0684:                                method, retVal);
0685:                        return retVal;
0686:                    } finally {
0687:                        if (target != null) {
0688:                            releaseTarget(target);
0689:                        }
0690:                        if (setProxyContext) {
0691:                            // Restore old proxy.
0692:                            AopContext.setCurrentProxy(oldProxy);
0693:                        }
0694:                    }
0695:                }
0696:
0697:                public boolean equals(Object other) {
0698:                    return (this  == other || (other instanceof  DynamicAdvisedInterceptor && this .advised
0699:                            .equals(((DynamicAdvisedInterceptor) other).advised)));
0700:                }
0701:
0702:                /**
0703:                 * CGLIB uses this to drive proxy creation.
0704:                 */
0705:                public int hashCode() {
0706:                    return this .advised.hashCode();
0707:                }
0708:
0709:                protected Object getTarget() throws Exception {
0710:                    return this .advised.getTargetSource().getTarget();
0711:                }
0712:
0713:                protected void releaseTarget(Object target) throws Exception {
0714:                    this .advised.getTargetSource().releaseTarget(target);
0715:                }
0716:            }
0717:
0718:            /**
0719:             * Implementation of AOP Alliance MethodInvocation used by this AOP proxy.
0720:             */
0721:            private static class CglibMethodInvocation extends
0722:                    ReflectiveMethodInvocation {
0723:
0724:                private final MethodProxy methodProxy;
0725:
0726:                private boolean protectedMethod;
0727:
0728:                public CglibMethodInvocation(Object proxy, Object target,
0729:                        Method method, Object[] arguments, Class targetClass,
0730:                        List interceptorsAndDynamicMethodMatchers,
0731:                        MethodProxy methodProxy) {
0732:                    super (proxy, target, method, arguments, targetClass,
0733:                            interceptorsAndDynamicMethodMatchers);
0734:                    this .methodProxy = methodProxy;
0735:                    this .protectedMethod = Modifier.isProtected(method
0736:                            .getModifiers());
0737:                }
0738:
0739:                /**
0740:                 * Gives a marginal performance improvement versus using reflection to
0741:                 * invoke the target when invoking public methods.
0742:                 */
0743:                protected Object invokeJoinpoint() throws Throwable {
0744:                    if (this .protectedMethod) {
0745:                        return super .invokeJoinpoint();
0746:                    } else {
0747:                        return this .methodProxy.invoke(this .target,
0748:                                this .arguments);
0749:                    }
0750:                }
0751:            }
0752:
0753:            /**
0754:             * CallbackFilter to assign Callbacks to methods.
0755:             */
0756:            private static class ProxyCallbackFilter implements  CallbackFilter {
0757:
0758:                private final AdvisedSupport advised;
0759:
0760:                private final Map fixedInterceptorMap;
0761:
0762:                private final int fixedInterceptorOffset;
0763:
0764:                public ProxyCallbackFilter(AdvisedSupport advised,
0765:                        Map fixedInterceptorMap, int fixedInterceptorOffset) {
0766:                    this .advised = advised;
0767:                    this .fixedInterceptorMap = fixedInterceptorMap;
0768:                    this .fixedInterceptorOffset = fixedInterceptorOffset;
0769:                }
0770:
0771:                /**
0772:                 * Implementation of CallbackFilter.accept() to return the index of the
0773:                 * callback we need.
0774:                 * <p>The callbacks for each proxy are built up of a set of fixed callbacks
0775:                 * for general use and then a set of callbacks that are specific to a method
0776:                 * for use on static targets with a fixed advice chain.
0777:                 * <p>The callback used is determined thus:
0778:                 * <dl>
0779:                 * <dt>For exposed proxies</dt>
0780:                 * <dd>Exposing the proxy requires code to execute before and after the
0781:                 * method/chain invocation. This means we must use
0782:                 * DynamicAdvisedInterceptor, since all other interceptors can avoid the
0783:                 * need for a try/catch block</dd>
0784:                 * <dt>For Object.finalize():</dt>
0785:                 * <dd>No override for this method is used</dd>
0786:                 * <dt>For equals():</dt>
0787:                 * <dd>The EqualsInterceptor is used to redirect equals() calls to a
0788:                 * special handler to this proxy.</dd>
0789:                 * <dt>For methods on the Advised class:</dt>
0790:                 * <dd>the AdvisedDispatcher is used to dispatch the call directly to
0791:                 * the target</dd>
0792:                 * <dt>For advised methods:</dt>
0793:                 * <dd>If the target is static and the advice chain is frozen then a
0794:                 * FixedChainStaticTargetInterceptor specific to the method is used to
0795:                 * invoke the advice chain. Otherwise a DyanmicAdvisedInterceptor is
0796:                 * used.</dd>
0797:                 * <dt>For non-advised methods:</dt>
0798:                 * <dd>Where it can be determined that the method will not return <code>this</code>
0799:                 * or when <code>ProxyFactory.getExposeProxy()</code> returns <code>false</code>,
0800:                 * then a Dispatcher is used. For static targets, the StaticDispatcher is used;
0801:                 * and for dynamic targets, a DynamicUnadvisedInterceptor is used.
0802:                 * If it possible for the method to return <code>this</code> then a
0803:                 * StaticUnadvisedInterceptor is used for static targets - the
0804:                 * DynamicUnadvisedInterceptor already considers this.</dd>
0805:                 * </dl>
0806:                 */
0807:                public int accept(Method method) {
0808:                    if (method.getDeclaringClass() == Object.class
0809:                            && method.getName().equals("finalize")) {
0810:                        logger
0811:                                .debug("Found finalize() method - using NO_OVERRIDE");
0812:                        return NO_OVERRIDE;
0813:                    }
0814:                    if (!this .advised.opaque
0815:                            && method.getDeclaringClass().isInterface()
0816:                            && method.getDeclaringClass().isAssignableFrom(
0817:                                    Advised.class)) {
0818:                        if (logger.isDebugEnabled()) {
0819:                            logger
0820:                                    .debug("Method is declared on Advised interface: "
0821:                                            + method);
0822:                        }
0823:                        return DISPATCH_ADVISED;
0824:                    }
0825:                    // We must always proxy equals, to direct calls to this.
0826:                    if (AopUtils.isEqualsMethod(method)) {
0827:                        logger.debug("Found 'equals' method: " + method);
0828:                        return INVOKE_EQUALS;
0829:                    }
0830:                    // We must always calculate hashCode based on the proxy.
0831:                    if (AopUtils.isHashCodeMethod(method)) {
0832:                        logger.debug("Found 'hashCode' method: " + method);
0833:                        return INVOKE_HASHCODE;
0834:                    }
0835:                    Class targetClass = this .advised.getTargetClass();
0836:                    // Proxy is not yet available, but that shouldn't matter.
0837:                    List chain = this .advised
0838:                            .getInterceptorsAndDynamicInterceptionAdvice(
0839:                                    method, targetClass);
0840:                    boolean haveAdvice = !chain.isEmpty();
0841:                    boolean exposeProxy = this .advised.isExposeProxy();
0842:                    boolean isStatic = this .advised.getTargetSource()
0843:                            .isStatic();
0844:                    boolean isFrozen = this .advised.isFrozen();
0845:                    if (haveAdvice || !isFrozen) {
0846:                        // If exposing the proxy, then AOP_PROXY must be used.
0847:                        if (exposeProxy) {
0848:                            if (logger.isDebugEnabled()) {
0849:                                logger
0850:                                        .debug("Must expose proxy on advised method: "
0851:                                                + method);
0852:                            }
0853:                            return AOP_PROXY;
0854:                        }
0855:                        String key = method.toString();
0856:                        // Check to see if we have fixed interceptor to serve this method.
0857:                        // Else use the AOP_PROXY.
0858:                        if (isStatic && isFrozen
0859:                                && this .fixedInterceptorMap.containsKey(key)) {
0860:                            if (logger.isDebugEnabled()) {
0861:                                logger
0862:                                        .debug("Method has advice and optimisations are enabled: "
0863:                                                + method);
0864:                            }
0865:                            // We know that we are optimising so we can use the
0866:                            // FixedStaticChainInterceptors.
0867:                            int index = ((Integer) this .fixedInterceptorMap
0868:                                    .get(key)).intValue();
0869:                            return (index + fixedInterceptorOffset);
0870:                        } else {
0871:                            if (logger.isDebugEnabled()) {
0872:                                logger
0873:                                        .debug("Unable to apply any optimisations to advised method: "
0874:                                                + method);
0875:                            }
0876:                            return AOP_PROXY;
0877:                        }
0878:                    } else {
0879:                        // See if the return type of the method is outside the class hierarchy
0880:                        // of the target type. If so we know it never needs to have return type
0881:                        // massage and can use a dispatcher.
0882:                        // If the proxy is being exposed, then must use the interceptor the
0883:                        // correct one is already configured. If the target is not static cannot
0884:                        // use a Dispatcher because the target can not then be released.
0885:                        if (exposeProxy || !isStatic) {
0886:                            return INVOKE_TARGET;
0887:                        }
0888:                        Class returnType = method.getReturnType();
0889:                        if (targetClass == returnType) {
0890:                            if (logger.isDebugEnabled()) {
0891:                                logger
0892:                                        .debug("Method "
0893:                                                + method
0894:                                                + "has return type same as target type (may return this) - using INVOKE_TARGET");
0895:                            }
0896:                            return INVOKE_TARGET;
0897:                        } else if (returnType.isPrimitive()
0898:                                || !returnType.isAssignableFrom(targetClass)) {
0899:                            if (logger.isDebugEnabled()) {
0900:                                logger
0901:                                        .debug("Method "
0902:                                                + method
0903:                                                + " has return type that ensures this cannot be returned- using DISPATCH_TARGET");
0904:                            }
0905:                            return DISPATCH_TARGET;
0906:                        } else {
0907:                            if (logger.isDebugEnabled()) {
0908:                                logger
0909:                                        .debug("Method "
0910:                                                + method
0911:                                                + "has return type that is assignable from the target type (may return this) - "
0912:                                                + "using INVOKE_TARGET");
0913:                            }
0914:                            return INVOKE_TARGET;
0915:                        }
0916:                    }
0917:                }
0918:
0919:                public boolean equals(Object other) {
0920:                    if (other == this ) {
0921:                        return true;
0922:                    }
0923:                    if (!(other instanceof  ProxyCallbackFilter)) {
0924:                        return false;
0925:                    }
0926:                    ProxyCallbackFilter otherCallbackFilter = (ProxyCallbackFilter) other;
0927:                    if (this .advised.isFrozen() != otherCallbackFilter.advised
0928:                            .isFrozen()) {
0929:                        return false;
0930:                    }
0931:                    if (this .advised.isExposeProxy() != otherCallbackFilter.advised
0932:                            .isExposeProxy()) {
0933:                        return false;
0934:                    }
0935:                    if (this .advised.getTargetSource().isStatic() != otherCallbackFilter.advised
0936:                            .getTargetSource().isStatic()) {
0937:                        return false;
0938:                    }
0939:                    if (!AopProxyUtils.equalsProxiedInterfaces(this .advised,
0940:                            otherCallbackFilter.advised)) {
0941:                        return false;
0942:                    }
0943:                    // Advice instance identity is unimportant to the proxy class:
0944:                    // All that matters is type and ordering.
0945:                    Advisor[] this Advisors = this .advised.getAdvisors();
0946:                    Advisor[] thatAdvisors = otherCallbackFilter.advised
0947:                            .getAdvisors();
0948:                    if (this Advisors.length != thatAdvisors.length) {
0949:                        return false;
0950:                    }
0951:                    for (int i = 0; i < this Advisors.length; i++) {
0952:                        Advisor this Advisor = this Advisors[i];
0953:                        Advisor thatAdvisor = thatAdvisors[i];
0954:                        if (!equalsAdviceClasses(this Advisor, thatAdvisor)) {
0955:                            return false;
0956:                        }
0957:                        if (!equalsPointcuts(this Advisor, thatAdvisor)) {
0958:                            return false;
0959:                        }
0960:                    }
0961:                    return true;
0962:                }
0963:
0964:                private boolean equalsAdviceClasses(Advisor a, Advisor b) {
0965:                    Advice aa = a.getAdvice();
0966:                    Advice ba = b.getAdvice();
0967:                    if (aa == null || ba == null) {
0968:                        return (aa == ba);
0969:                    }
0970:                    return aa.getClass().equals(ba.getClass());
0971:                }
0972:
0973:                private boolean equalsPointcuts(Advisor a, Advisor b) {
0974:                    return (a instanceof  PointcutAdvisor
0975:                            && b instanceof  PointcutAdvisor && ObjectUtils
0976:                            .nullSafeEquals(
0977:                                    ((PointcutAdvisor) a).getPointcut(),
0978:                                    ((PointcutAdvisor) b).getPointcut()));
0979:                }
0980:
0981:                public int hashCode() {
0982:                    int hashCode = 0;
0983:                    Advisor[] advisors = this .advised.getAdvisors();
0984:                    for (int i = 0; i < advisors.length; i++) {
0985:                        Advice advice = advisors[i].getAdvice();
0986:                        if (advice != null) {
0987:                            hashCode = 13 * hashCode
0988:                                    + advice.getClass().hashCode();
0989:                        }
0990:                    }
0991:                    hashCode = 13 * hashCode
0992:                            + (this .advised.isFrozen() ? 1 : 0);
0993:                    hashCode = 13 * hashCode
0994:                            + (this .advised.isExposeProxy() ? 1 : 0);
0995:                    hashCode = 13 * hashCode
0996:                            + (this .advised.isOptimize() ? 1 : 0);
0997:                    hashCode = 13 * hashCode
0998:                            + (this .advised.isOpaque() ? 1 : 0);
0999:                    return hashCode;
1000:                }
1001:            }
1002:
1003:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.