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