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