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


001:        /*
002:         * Copyright 2002-2007 the original author or authors.
003:         *
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         *
008:         *      http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:
017:        package org.springframework.aop.aspectj;
018:
019:        import java.lang.reflect.InvocationTargetException;
020:        import java.lang.reflect.Method;
021:        import java.util.HashMap;
022:        import java.util.Map;
023:
024:        import org.aopalliance.aop.Advice;
025:        import org.aopalliance.intercept.MethodInvocation;
026:        import org.aspectj.lang.JoinPoint;
027:        import org.aspectj.lang.ProceedingJoinPoint;
028:        import org.aspectj.weaver.tools.JoinPointMatch;
029:        import org.aspectj.weaver.tools.PointcutParameter;
030:
031:        import org.springframework.aop.AopInvocationException;
032:        import org.springframework.aop.MethodMatcher;
033:        import org.springframework.aop.Pointcut;
034:        import org.springframework.aop.ProxyMethodInvocation;
035:        import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
036:        import org.springframework.aop.support.ComposablePointcut;
037:        import org.springframework.aop.support.MethodMatchers;
038:        import org.springframework.aop.support.StaticMethodMatcher;
039:        import org.springframework.core.JdkVersion;
040:        import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
041:        import org.springframework.core.ParameterNameDiscoverer;
042:        import org.springframework.core.PrioritizedParameterNameDiscoverer;
043:        import org.springframework.util.Assert;
044:        import org.springframework.util.ClassUtils;
045:        import org.springframework.util.CollectionUtils;
046:        import org.springframework.util.ReflectionUtils;
047:        import org.springframework.util.StringUtils;
048:
049:        /**
050:         * Base class for AOP Alliance {@link org.aopalliance.aop.Advice} classes
051:         * wrapping an AspectJ aspect or an AspectJ-annotated advice method.
052:         *
053:         * @author Rod Johnson
054:         * @author Adrian Colyer
055:         * @author Juergen Hoeller
056:         * @author Ramnivas Laddad
057:         * @since 2.0
058:         */
059:        public abstract class AbstractAspectJAdvice implements  Advice,
060:                AspectJPrecedenceInformation {
061:
062:            /**
063:             * Key used in ReflectiveMethodInvocation userAtributes map for the current joinpoint.
064:             */
065:            protected static final String JOIN_POINT_KEY = JoinPoint.class
066:                    .getName();
067:
068:            /**
069:             * Lazily instantiate joinpoint for the current invocation.
070:             * Requires MethodInvocation to be bound with ExposeInvocationInterceptor.
071:             * <p>Do not use if access is available to the current ReflectiveMethodInvocation
072:             * (in an around advice).
073:             * @return current AspectJ joinpoint, or through an exception if we're not in a
074:             * Spring AOP invocation.
075:             */
076:            public static JoinPoint currentJoinPoint() {
077:                MethodInvocation mi = ExposeInvocationInterceptor
078:                        .currentInvocation();
079:                if (!(mi instanceof  ProxyMethodInvocation)) {
080:                    throw new IllegalStateException(
081:                            "MethodInvocation is not a Spring ProxyMethodInvocation: "
082:                                    + mi);
083:                }
084:                ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
085:                JoinPoint jp = (JoinPoint) pmi.getUserAttribute(JOIN_POINT_KEY);
086:                if (jp == null) {
087:                    jp = new MethodInvocationProceedingJoinPoint(pmi);
088:                    pmi.setUserAttribute(JOIN_POINT_KEY, jp);
089:                }
090:                return jp;
091:            }
092:
093:            protected final Method aspectJAdviceMethod;
094:
095:            /** The total number of arguments we have to populate on advice dispatch */
096:            private final int adviceInvocationArgumentCount;
097:
098:            private final AspectJExpressionPointcut pointcut;
099:
100:            private final AspectInstanceFactory aspectInstanceFactory;
101:
102:            /**
103:             * The name of the aspect (ref bean) in which this advice was defined (used
104:             * when determining advice precedence so that we can determine
105:             * whether two pieces of advice come from the same aspect).
106:             */
107:            private String aspectName;
108:
109:            /**
110:             * The order of declaration of this advice within the aspect.
111:             */
112:            private int declarationOrder;
113:
114:            /**
115:             * This will be non-null if the creator of this advice object knows the argument names
116:             * and sets them explicitly
117:             */
118:            private String[] argumentNames = null;
119:
120:            /** Non-null if after throwing advice binds the thrown value */
121:            private String throwingName = null;
122:
123:            /** Non-null if after returning advice binds the return value */
124:            private String returningName = null;
125:
126:            private Class discoveredReturningType = Object.class;
127:
128:            private Class discoveredThrowingType = Object.class;
129:
130:            /**
131:             * Index for thisJoinPoint argument (currently only
132:             * supported at index 0 if present at all)
133:             */
134:            private int joinPointArgumentIndex = -1;
135:
136:            /**
137:             * Index for thisJoinPointStaticPart argument (currently only
138:             * supported at index 0 if present at all)
139:             */
140:            private int joinPointStaticPartArgumentIndex = -1;
141:
142:            private Map argumentBindings = null;
143:
144:            private boolean argumentsIntrospected = false;
145:
146:            // The actual type is java.lang.reflect.Type,
147:            // but for JDK 1.4 compatibility we use Object as the static type.
148:            private Object discoveredReturningGenericType;
149:
150:            // Note: Unlike return type, no such generic information is needed for the throwing type,
151:            // since Java doesn't allow exception types to be parameterized.
152:
153:            /**
154:             * Create a new AbstractAspectJAdvice for the given advice method.
155:             * @param aspectJAdviceMethod the AspectJ-style advice method
156:             * @param pointcut the AspectJ expression pointcut
157:             * @param aspectInstanceFactory the factory for aspect instances
158:             */
159:            public AbstractAspectJAdvice(Method aspectJAdviceMethod,
160:                    AspectJExpressionPointcut pointcut,
161:                    AspectInstanceFactory aspectInstanceFactory) {
162:
163:                Assert.notNull(aspectJAdviceMethod,
164:                        "Advice method must not be null");
165:                this .aspectJAdviceMethod = aspectJAdviceMethod;
166:                this .adviceInvocationArgumentCount = this .aspectJAdviceMethod
167:                        .getParameterTypes().length;
168:                this .pointcut = pointcut;
169:                this .aspectInstanceFactory = aspectInstanceFactory;
170:            }
171:
172:            /**
173:             * Return the AspectJ-style advice method.
174:             */
175:            public final Method getAspectJAdviceMethod() {
176:                return this .aspectJAdviceMethod;
177:            }
178:
179:            /**
180:             * Return the AspectJ expression pointcut.
181:             */
182:            public final AspectJExpressionPointcut getPointcut() {
183:                calculateArgumentBindings();
184:                return this .pointcut;
185:            }
186:
187:            /**
188:             * Build a 'safe' pointcut that excludes the AspectJ advice method itself.
189:             * @return a composable pointcut that builds on the original AspectJ expression pointcut
190:             * @see #getPointcut()
191:             */
192:            public final Pointcut buildSafePointcut() {
193:                Pointcut pc = getPointcut();
194:                MethodMatcher safeMethodMatcher = MethodMatchers.intersection(
195:                        new AdviceExcludingMethodMatcher(
196:                                this .aspectJAdviceMethod), pc
197:                                .getMethodMatcher());
198:                return new ComposablePointcut(pc.getClassFilter(),
199:                        safeMethodMatcher);
200:            }
201:
202:            /**
203:             * Return the factory for aspect instances.
204:             */
205:            public final AspectInstanceFactory getAspectInstanceFactory() {
206:                return this .aspectInstanceFactory;
207:            }
208:
209:            /**
210:             * Return the ClassLoader for aspect instances.
211:             */
212:            public final ClassLoader getAspectClassLoader() {
213:                return this .aspectInstanceFactory.getAspectClassLoader();
214:            }
215:
216:            public int getOrder() {
217:                return this .aspectInstanceFactory.getOrder();
218:            }
219:
220:            public void setAspectName(String name) {
221:                this .aspectName = name;
222:            }
223:
224:            public String getAspectName() {
225:                return this .aspectName;
226:            }
227:
228:            /**
229:             * Sets the <b>declaration order</b> of this advice within the aspect
230:             */
231:            public void setDeclarationOrder(int order) {
232:                this .declarationOrder = order;
233:            }
234:
235:            public int getDeclarationOrder() {
236:                return this .declarationOrder;
237:            }
238:
239:            /**
240:             * Set by creator of this advice object if the argument names are known.
241:             * <p>This could be for example because they have been explicitly specified in XML,
242:             * or in an advice annotation.
243:             * @param argNames comma delimited list of arg names
244:             */
245:            public void setArgumentNames(String argNames) {
246:                String[] tokens = StringUtils
247:                        .commaDelimitedListToStringArray(argNames);
248:                setArgumentNamesFromStringArray(tokens);
249:            }
250:
251:            public void setArgumentNamesFromStringArray(String[] args) {
252:                this .argumentNames = new String[args.length];
253:                for (int i = 0; i < args.length; i++) {
254:                    this .argumentNames[i] = StringUtils.trimWhitespace(args[i]);
255:                    if (!isVariableName(this .argumentNames[i])) {
256:                        throw new IllegalArgumentException(
257:                                "'argumentNames' property of AbstractAspectJAdvice contains an argument name '"
258:                                        + this .argumentNames[i]
259:                                        + "' that is not a valid Java identifier");
260:                    }
261:                }
262:                if (argumentNames != null) {
263:                    if (aspectJAdviceMethod.getParameterTypes().length == argumentNames.length + 1) {
264:                        // May need to add implicit join point arg name...
265:                        Class firstArgType = aspectJAdviceMethod
266:                                .getParameterTypes()[0];
267:                        if (firstArgType == JoinPoint.class
268:                                || firstArgType == ProceedingJoinPoint.class
269:                                || firstArgType == JoinPoint.StaticPart.class) {
270:                            String[] oldNames = argumentNames;
271:                            argumentNames = new String[oldNames.length + 1];
272:                            argumentNames[0] = "THIS_JOIN_POINT";
273:                            System.arraycopy(oldNames, 0, argumentNames, 1,
274:                                    oldNames.length);
275:                        }
276:                    }
277:                }
278:            }
279:
280:            public void setReturningName(String name) {
281:                throw new UnsupportedOperationException(
282:                        "Only afterReturning advice can be used to bind a return value");
283:            }
284:
285:            /** 
286:             * We need to hold the returning name at this level for argument binding calculations,
287:             * this method allows the afterReturning advice subclass to set the name.
288:             */
289:            protected void setReturningNameNoCheck(String name) {
290:                // name could be a variable or a type...
291:                if (isVariableName(name)) {
292:                    this .returningName = name;
293:                } else {
294:                    // assume a type
295:                    try {
296:                        this .discoveredReturningType = ClassUtils.forName(name,
297:                                getAspectClassLoader());
298:                    } catch (Throwable ex) {
299:                        throw new IllegalArgumentException(
300:                                "Returning name '"
301:                                        + name
302:                                        + "' is neither a valid argument name nor the fully-qualified name of a Java type on the classpath. "
303:                                        + "Root cause: " + ex);
304:                    }
305:                }
306:            }
307:
308:            protected Class getDiscoveredReturningType() {
309:                return this .discoveredReturningType;
310:            }
311:
312:            protected Object getDiscoveredReturningGenericType() {
313:                return this .discoveredReturningGenericType;
314:            }
315:
316:            public void setThrowingName(String name) {
317:                throw new UnsupportedOperationException(
318:                        "Only afterThrowing advice can be used to bind a thrown exception");
319:            }
320:
321:            /** 
322:             * We need to hold the throwing name at this level for argument binding calculations,
323:             * this method allows the afterThrowing advice subclass to set the name.
324:             */
325:            protected void setThrowingNameNoCheck(String name) {
326:                // name could be a variable or a type...
327:                if (isVariableName(name)) {
328:                    this .throwingName = name;
329:                } else {
330:                    // assume a type
331:                    try {
332:                        this .discoveredThrowingType = ClassUtils.forName(name,
333:                                getAspectClassLoader());
334:                    } catch (Throwable ex) {
335:                        throw new IllegalArgumentException(
336:                                "Throwing name '"
337:                                        + name
338:                                        + "' is neither a valid argument name nor the fully-qualified name of a Java type on the classpath. "
339:                                        + "Root cause: " + ex);
340:                    }
341:                }
342:            }
343:
344:            protected Class getDiscoveredThrowingType() {
345:                return this .discoveredThrowingType;
346:            }
347:
348:            private boolean isVariableName(String name) {
349:                char[] chars = name.toCharArray();
350:                if (!Character.isJavaIdentifierStart(chars[0])) {
351:                    return false;
352:                }
353:                for (int i = 1; i < chars.length; i++) {
354:                    if (!Character.isJavaIdentifierPart(chars[i])) {
355:                        return false;
356:                    }
357:                }
358:                return true;
359:            }
360:
361:            /**
362:             * Do as much work as we can as part of the set-up so that argument binding
363:             * on subsequent advice invocations can be as fast as possible.
364:             * <p>If the first argument is of type JoinPoint or ProceedingJoinPoint then we
365:             * pass a JoinPoint in that position (ProceedingJoinPoint for around advice).
366:             * <p>If the first argument is of type <code>JoinPoint.StaticPart</code>
367:             * then we pass a <code>JoinPoint.StaticPart</code> in that position.
368:             * <p>Remaining arguments have to be bound by pointcut evaluation at
369:             * a given join point. We will get back a map from argument name to
370:             * value. We need to calculate which advice parameter needs to be bound
371:             * to which argument name. There are multiple strategies for determining
372:             * this binding, which are arranged in a ChainOfResponsibility.
373:             */
374:            public synchronized final void calculateArgumentBindings() {
375:                // The simple case... nothing to bind.
376:                if (this .argumentsIntrospected
377:                        || this .adviceInvocationArgumentCount == 0) {
378:                    return;
379:                }
380:
381:                int numUnboundArgs = this .adviceInvocationArgumentCount;
382:                Class[] parameterTypes = this .aspectJAdviceMethod
383:                        .getParameterTypes();
384:                if (maybeBindJoinPoint(parameterTypes[0])
385:                        || maybeBindProceedingJoinPoint(parameterTypes[0])) {
386:                    numUnboundArgs--;
387:                } else if (maybeBindJoinPointStaticPart(parameterTypes[0])) {
388:                    numUnboundArgs--;
389:                }
390:
391:                if (numUnboundArgs > 0) {
392:                    // need to bind arguments by name as returned from the pointcut match
393:                    bindArgumentsByName(numUnboundArgs);
394:                }
395:
396:                this .argumentsIntrospected = true;
397:            }
398:
399:            private boolean maybeBindJoinPoint(Class candidateParameterType) {
400:                if (candidateParameterType.equals(JoinPoint.class)) {
401:                    this .joinPointArgumentIndex = 0;
402:                    return true;
403:                } else {
404:                    return false;
405:                }
406:            }
407:
408:            private boolean maybeBindProceedingJoinPoint(
409:                    Class candidateParameterType) {
410:                if (candidateParameterType.equals(ProceedingJoinPoint.class)) {
411:                    if (!supportsProceedingJoinPoint()) {
412:                        throw new IllegalArgumentException(
413:                                "ProceedingJoinPoint is only supported for around advice");
414:                    }
415:                    this .joinPointArgumentIndex = 0;
416:                    return true;
417:                } else {
418:                    return false;
419:                }
420:            }
421:
422:            protected boolean supportsProceedingJoinPoint() {
423:                return false;
424:            }
425:
426:            private boolean maybeBindJoinPointStaticPart(
427:                    Class candidateParameterType) {
428:                if (candidateParameterType.equals(JoinPoint.StaticPart.class)) {
429:                    this .joinPointStaticPartArgumentIndex = 0;
430:                    return true;
431:                } else {
432:                    return false;
433:                }
434:            }
435:
436:            private void bindArgumentsByName(int numArgumentsExpectingToBind) {
437:                if (this .argumentNames == null) {
438:                    this .argumentNames = createParameterNameDiscoverer()
439:                            .getParameterNames(this .aspectJAdviceMethod);
440:                }
441:                if (this .argumentNames != null) {
442:                    // We have been able to determine the arg names.
443:                    bindExplicitArguments(numArgumentsExpectingToBind);
444:                } else {
445:                    throw new IllegalStateException(
446:                            "Advice method ["
447:                                    + this .aspectJAdviceMethod.getName()
448:                                    + "] "
449:                                    + "requires "
450:                                    + numArgumentsExpectingToBind
451:                                    + " arguments to be bound by name, but "
452:                                    + "the argument names were not specified and could not be discovered.");
453:                }
454:            }
455:
456:            /**
457:             * Create a ParameterNameDiscoverer to be used for argument binding.
458:             * <p>The default implementation creates a {@link PrioritizedParameterNameDiscoverer}
459:             * containing a {@link LocalVariableTableParameterNameDiscoverer} and an
460:             * {@link AspectJAdviceParameterNameDiscoverer}.
461:             */
462:            protected ParameterNameDiscoverer createParameterNameDiscoverer() {
463:                // We need to discover them, or if that fails, guess,
464:                // and if we can't guess with 100% accuracy, fail.
465:                PrioritizedParameterNameDiscoverer discoverer = new PrioritizedParameterNameDiscoverer();
466:                discoverer
467:                        .addDiscoverer(new LocalVariableTableParameterNameDiscoverer());
468:                AspectJAdviceParameterNameDiscoverer adviceParameterNameDiscoverer = new AspectJAdviceParameterNameDiscoverer(
469:                        this .pointcut.getExpression());
470:                adviceParameterNameDiscoverer
471:                        .setReturningName(this .returningName);
472:                adviceParameterNameDiscoverer
473:                        .setThrowingName(this .throwingName);
474:                // Last in chain, so if we're called and we fail, that's bad...
475:                adviceParameterNameDiscoverer.setRaiseExceptions(true);
476:                discoverer.addDiscoverer(adviceParameterNameDiscoverer);
477:                return discoverer;
478:            }
479:
480:            private void bindExplicitArguments(int numArgumentsLeftToBind) {
481:                this .argumentBindings = new HashMap();
482:
483:                int numExpectedArgumentNames = this .aspectJAdviceMethod
484:                        .getParameterTypes().length;
485:                if (this .argumentNames.length != numExpectedArgumentNames) {
486:                    throw new IllegalStateException(
487:                            "Expecting to find "
488:                                    + numExpectedArgumentNames
489:                                    + " arguments to bind by name in advice, but actually found "
490:                                    + this .argumentNames.length + " arguments.");
491:                }
492:
493:                // So we match in number...
494:                int argumentIndexOffset = this .adviceInvocationArgumentCount
495:                        - numArgumentsLeftToBind;
496:                for (int i = argumentIndexOffset; i < this .argumentNames.length; i++) {
497:                    this .argumentBindings.put(this .argumentNames[i],
498:                            new Integer(i));
499:                }
500:
501:                // Check that returning and throwing were in the argument names list if
502:                // specified, and find the discovered argument types.
503:                if (this .returningName != null) {
504:                    if (!this .argumentBindings.containsKey(this .returningName)) {
505:                        throw new IllegalStateException(
506:                                "Returning argument name '"
507:                                        + this .returningName
508:                                        + "' was not bound in advice arguments");
509:                    } else {
510:                        Integer index = (Integer) this .argumentBindings
511:                                .get(this .returningName);
512:                        this .discoveredReturningType = this .aspectJAdviceMethod
513:                                .getParameterTypes()[index.intValue()];
514:                        if (JdkVersion.isAtLeastJava15()) {
515:                            this .discoveredReturningGenericType = this .aspectJAdviceMethod
516:                                    .getGenericParameterTypes()[index
517:                                    .intValue()];
518:                        }
519:                    }
520:                }
521:                if (this .throwingName != null) {
522:                    if (!this .argumentBindings.containsKey(this .throwingName)) {
523:                        throw new IllegalStateException(
524:                                "Throwing argument name '" + this .throwingName
525:                                        + "' was not bound in advice arguments");
526:                    } else {
527:                        Integer index = (Integer) this .argumentBindings
528:                                .get(this .throwingName);
529:                        this .discoveredThrowingType = this .aspectJAdviceMethod
530:                                .getParameterTypes()[index.intValue()];
531:                    }
532:                }
533:
534:                // configure the pointcut expression accordingly.
535:                configurePointcutParameters(argumentIndexOffset);
536:            }
537:
538:            /**
539:             * All parameters from argumentIndexOffset onwards are candidates for
540:             * pointcut parameters - but returning and throwing vars are handled differently
541:             * and must be removed from the list if present.
542:             */
543:            private void configurePointcutParameters(int argumentIndexOffset) {
544:                int numParametersToRemove = argumentIndexOffset;
545:                if (this .returningName != null) {
546:                    numParametersToRemove++;
547:                }
548:                if (this .throwingName != null) {
549:                    numParametersToRemove++;
550:                }
551:                String[] pointcutParameterNames = new String[this .argumentNames.length
552:                        - numParametersToRemove];
553:                Class[] pointcutParameterTypes = new Class[pointcutParameterNames.length];
554:                Class[] methodParameterTypes = this .aspectJAdviceMethod
555:                        .getParameterTypes();
556:
557:                int index = 0;
558:                for (int i = 0; i < this .argumentNames.length; i++) {
559:                    if (i < argumentIndexOffset) {
560:                        continue;
561:                    }
562:                    if (this .argumentNames[i].equals(this .returningName)
563:                            || this .argumentNames[i].equals(this .throwingName)) {
564:                        continue;
565:                    }
566:                    pointcutParameterNames[index] = this .argumentNames[i];
567:                    pointcutParameterTypes[index] = methodParameterTypes[i];
568:                    index++;
569:                }
570:
571:                this .pointcut.setParameterNames(pointcutParameterNames);
572:                this .pointcut.setParameterTypes(pointcutParameterTypes);
573:            }
574:
575:            /**
576:             * Take the arguments at the method execution join point and output a set of arguments
577:             * to the advice method
578:             * @param jp the current JoinPoint
579:             * @param jpMatch the join point match that matched this execution join point
580:             * @param returnValue the return value from the method execution (may be null)
581:             * @param ex the exception thrown by the method execution (may be null)
582:             * @return the empty array if there are no arguments
583:             */
584:            protected Object[] argBinding(JoinPoint jp, JoinPointMatch jpMatch,
585:                    Object returnValue, Throwable ex) {
586:                calculateArgumentBindings();
587:
588:                // AMC start
589:                Object[] adviceInvocationArgs = new Object[this .adviceInvocationArgumentCount];
590:                int numBound = 0;
591:
592:                if (this .joinPointArgumentIndex != -1) {
593:                    adviceInvocationArgs[this .joinPointArgumentIndex] = jp;
594:                    numBound++;
595:                } else if (this .joinPointStaticPartArgumentIndex != -1) {
596:                    adviceInvocationArgs[this .joinPointStaticPartArgumentIndex] = jp
597:                            .getStaticPart();
598:                    numBound++;
599:                }
600:
601:                if (!CollectionUtils.isEmpty(this .argumentBindings)) {
602:                    // binding from pointcut match
603:                    if (jpMatch != null) {
604:                        PointcutParameter[] parameterBindings = jpMatch
605:                                .getParameterBindings();
606:                        for (int i = 0; i < parameterBindings.length; i++) {
607:                            PointcutParameter parameter = parameterBindings[i];
608:                            String name = parameter.getName();
609:                            Integer index = (Integer) this .argumentBindings
610:                                    .get(name);
611:                            adviceInvocationArgs[index.intValue()] = parameter
612:                                    .getBinding();
613:                            numBound++;
614:                        }
615:                    }
616:                    // binding from returning clause
617:                    if (this .returningName != null) {
618:                        Integer index = (Integer) this .argumentBindings
619:                                .get(this .returningName);
620:                        adviceInvocationArgs[index.intValue()] = returnValue;
621:                        numBound++;
622:                    }
623:                    // binding from thrown exception
624:                    if (this .throwingName != null) {
625:                        Integer index = (Integer) this .argumentBindings
626:                                .get(this .throwingName);
627:                        adviceInvocationArgs[index.intValue()] = ex;
628:                        numBound++;
629:                    }
630:                }
631:
632:                if (numBound != this .adviceInvocationArgumentCount) {
633:                    throw new IllegalStateException("Required to bind "
634:                            + this .adviceInvocationArgumentCount
635:                            + " arguments, but only bound " + numBound
636:                            + " (JoinPointMatch "
637:                            + (jpMatch == null ? "was NOT" : "WAS")
638:                            + " bound in invocation)");
639:                }
640:
641:                return adviceInvocationArgs;
642:            }
643:
644:            /**
645:             * Invoke the advice method.
646:             * @param jpMatch the JoinPointMatch that matched this execution join point
647:             * @param returnValue the return value from the method execution (may be null)
648:             * @param ex the exception thrown by the method execution (may be null)
649:             * @return the invocation result
650:             * @throws Throwable in case of invocation failure
651:             */
652:            protected Object invokeAdviceMethod(JoinPointMatch jpMatch,
653:                    Object returnValue, Throwable ex) throws Throwable {
654:                return invokeAdviceMethodWithGivenArgs(argBinding(
655:                        getJoinPoint(), jpMatch, returnValue, ex));
656:            }
657:
658:            // As above, but in this case we are given the join point.
659:            protected Object invokeAdviceMethod(JoinPoint jp,
660:                    JoinPointMatch jpMatch, Object returnValue, Throwable t)
661:                    throws Throwable {
662:
663:                return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch,
664:                        returnValue, t));
665:            }
666:
667:            protected Object invokeAdviceMethodWithGivenArgs(Object[] args)
668:                    throws Throwable {
669:                Object[] actualArgs = args;
670:                if (this .aspectJAdviceMethod.getParameterTypes().length == 0) {
671:                    actualArgs = null;
672:                }
673:                try {
674:                    ReflectionUtils.makeAccessible(this .aspectJAdviceMethod);
675:                    // TODO AopUtils.invokeJoinpointUsingReflection
676:                    return this .aspectJAdviceMethod.invoke(
677:                            this .aspectInstanceFactory.getAspectInstance(),
678:                            actualArgs);
679:                } catch (IllegalArgumentException ex) {
680:                    throw new AopInvocationException(
681:                            "Mismatch on arguments to advice method ["
682:                                    + this .aspectJAdviceMethod
683:                                    + "]; pointcut expression ["
684:                                    + this .pointcut.getPointcutExpression()
685:                                    + "]", ex);
686:                } catch (InvocationTargetException ex) {
687:                    throw ex.getTargetException();
688:                }
689:            }
690:
691:            /**
692:             * Overridden in around advice to return proceeding join point.
693:             */
694:            protected JoinPoint getJoinPoint() {
695:                return currentJoinPoint();
696:            }
697:
698:            /**
699:             * Get the current join point match at the join point we are being dispatched on.
700:             */
701:            protected JoinPointMatch getJoinPointMatch() {
702:                MethodInvocation mi = ExposeInvocationInterceptor
703:                        .currentInvocation();
704:                if (!(mi instanceof  ProxyMethodInvocation)) {
705:                    throw new IllegalStateException(
706:                            "MethodInvocation is not a Spring ProxyMethodInvocation: "
707:                                    + mi);
708:                }
709:                return getJoinPointMatch((ProxyMethodInvocation) mi);
710:            }
711:
712:            // Note: We can't use JoinPointMatch.getClass().getName() as the key, since
713:            // Spring AOP does all the matching at a join point, and then all the invocations.
714:            // Under this scenario, if we just use JoinPointMatch as the key, then
715:            // 'last man wins' which is not what we want at all.
716:            // Using the expression is guaranteed to be safe, since 2 identical expressions
717:            // are guaranteed to bind in exactly the same way.
718:            protected JoinPointMatch getJoinPointMatch(ProxyMethodInvocation pmi) {
719:                return (JoinPointMatch) pmi.getUserAttribute(this .pointcut
720:                        .getExpression());
721:            }
722:
723:            public String toString() {
724:                return getClass().getName() + ": advice method ["
725:                        + this .aspectJAdviceMethod + "]; " + "aspect name '"
726:                        + this .aspectName + "'";
727:            }
728:
729:            /**
730:             * MethodMatcher that excludes the specified advice method.
731:             * @see AbstractAspectJAdvice#buildSafePointcut()
732:             */
733:            private static class AdviceExcludingMethodMatcher extends
734:                    StaticMethodMatcher {
735:
736:                private final Method adviceMethod;
737:
738:                public AdviceExcludingMethodMatcher(Method adviceMethod) {
739:                    this .adviceMethod = adviceMethod;
740:                }
741:
742:                public boolean matches(Method method, Class targetClass) {
743:                    return !this.adviceMethod.equals(method);
744:                }
745:            }
746:
747:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.