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.Method;
020:
021: import org.aspectj.lang.JoinPoint;
022: import org.aspectj.lang.ProceedingJoinPoint;
023: import org.aspectj.lang.Signature;
024: import org.aspectj.lang.reflect.MethodSignature;
025: import org.aspectj.lang.reflect.SourceLocation;
026: import org.aspectj.runtime.internal.AroundClosure;
027:
028: import org.springframework.aop.ProxyMethodInvocation;
029: import org.springframework.util.Assert;
030:
031: /**
032: * Implementation of AspectJ ProceedingJoinPoint interface
033: * wrapping an AOP Alliance MethodInvocation.
034: *
035: * <p><b>Note</b>: the <code>getThis()</code> method returns the current Spring AOP proxy.
036: * The <code>getTarget()</code> method returns the current Spring AOP target (which may be
037: * <code>null</code> if there is no target), and is a plain POJO without any advice.
038: * <b>If you want to call the object and have the advice take effect, use
039: * <code>getThis()</code>.</b> A common example is casting the object to an
040: * introduced interface in the implementation of an introduction.
041: *
042: * <p>Of course there is no such distinction between target and proxy in AspectJ.
043: *
044: * @author Rod Johnson
045: * @author Juergen Hoeller
046: * @author Adrian Colyer
047: * @since 2.0
048: */
049: public class MethodInvocationProceedingJoinPoint implements
050: ProceedingJoinPoint, JoinPoint.StaticPart {
051:
052: private final ProxyMethodInvocation methodInvocation;
053:
054: private Object[] defensiveCopyOfArgs;
055:
056: /** Lazily initialized signature object */
057: private Signature signature;
058:
059: /** Lazily initialized source location object */
060: private SourceLocation sourceLocation;
061:
062: /**
063: * Create a new MethodInvocationProceedingJoinPoint, wrapping the given
064: * Spring ProxyMethodInvocation object.
065: * @param methodInvocation the Spring ProxyMethodInvocation object
066: */
067: public MethodInvocationProceedingJoinPoint(
068: ProxyMethodInvocation methodInvocation) {
069: Assert.notNull(methodInvocation,
070: "MethodInvocation must not be null");
071: this .methodInvocation = methodInvocation;
072: }
073:
074: public void set$AroundClosure(AroundClosure aroundClosure) {
075: throw new UnsupportedOperationException();
076: }
077:
078: public Object proceed() throws Throwable {
079: return this .methodInvocation.invocableClone().proceed();
080: }
081:
082: public Object proceed(Object[] arguments) throws Throwable {
083: Assert.notNull(arguments,
084: "Argument array passed to proceed cannot be null");
085: if (arguments.length != this .methodInvocation.getArguments().length) {
086: throw new IllegalArgumentException("Expecting "
087: + this .methodInvocation.getArguments().length
088: + " arguments to proceed, " + "but was passed "
089: + arguments.length + " arguments");
090: }
091: this .methodInvocation.setArguments(arguments);
092: return this .methodInvocation.invocableClone(arguments)
093: .proceed();
094: }
095:
096: /**
097: * Returns the Spring AOP proxy. Cannot be <code>null</code>.
098: */
099: public Object getThis() {
100: return this .methodInvocation.getProxy();
101: }
102:
103: /**
104: * Returns the Spring AOP target. May be <code>null</code> if there is no target.
105: */
106: public Object getTarget() {
107: return this .methodInvocation.getThis();
108: }
109:
110: public Object[] getArgs() {
111: if (this .defensiveCopyOfArgs == null) {
112: Object[] argsSource = this .methodInvocation.getArguments();
113: this .defensiveCopyOfArgs = new Object[argsSource.length];
114: System.arraycopy(argsSource, 0, this .defensiveCopyOfArgs,
115: 0, argsSource.length);
116: }
117: return this .defensiveCopyOfArgs;
118: }
119:
120: public Signature getSignature() {
121: if (this .signature == null) {
122: this .signature = new MethodSignatureImpl();
123: }
124: return signature;
125: }
126:
127: public SourceLocation getSourceLocation() {
128: if (this .sourceLocation == null) {
129: this .sourceLocation = new SourceLocationImpl();
130: }
131: return this .sourceLocation;
132: }
133:
134: public String getKind() {
135: return ProceedingJoinPoint.METHOD_EXECUTION;
136: }
137:
138: public JoinPoint.StaticPart getStaticPart() {
139: return this ;
140: }
141:
142: public String toShortString() {
143: return "execution("
144: + this .methodInvocation.getMethod().getName() + ")";
145: }
146:
147: public String toLongString() {
148: return getClass().getName() + ": execution: ["
149: + this .methodInvocation + "]";
150: }
151:
152: public String toString() {
153: return getClass().getName() + ": " + toShortString();
154: }
155:
156: /**
157: * Lazily initialized MethodSignature.
158: */
159: private class MethodSignatureImpl implements Signature,
160: MethodSignature {
161:
162: public String toShortString() {
163: return methodInvocation.getMethod().getName();
164: }
165:
166: public String toLongString() {
167: return methodInvocation.getMethod().toString();
168: }
169:
170: public String getName() {
171: return methodInvocation.getMethod().getName();
172: }
173:
174: public int getModifiers() {
175: return methodInvocation.getMethod().getModifiers();
176: }
177:
178: public Class getDeclaringType() {
179: return methodInvocation.getMethod().getDeclaringClass();
180: }
181:
182: public String getDeclaringTypeName() {
183: return methodInvocation.getMethod().getDeclaringClass()
184: .getName();
185: }
186:
187: public Class getReturnType() {
188: return methodInvocation.getMethod().getReturnType();
189: }
190:
191: public Method getMethod() {
192: return methodInvocation.getMethod();
193: }
194:
195: public Class[] getParameterTypes() {
196: return methodInvocation.getMethod().getParameterTypes();
197: }
198:
199: public String[] getParameterNames() {
200: // TODO consider allowing use of ParameterNameDiscoverer, or tying into
201: // parameter names exposed for argument binding...
202: throw new UnsupportedOperationException(
203: "Parameter names cannot be determined unless compiled by AspectJ compiler");
204: }
205:
206: public Class[] getExceptionTypes() {
207: return methodInvocation.getMethod().getExceptionTypes();
208: }
209: }
210:
211: /**
212: * Lazily initialized SourceLocation.
213: */
214: private class SourceLocationImpl implements SourceLocation {
215:
216: public Class getWithinType() {
217: if (methodInvocation.getThis() == null) {
218: throw new UnsupportedOperationException(
219: "No source location joinpoint available: target is null");
220: }
221: return methodInvocation.getThis().getClass();
222: }
223:
224: public String getFileName() {
225: throw new UnsupportedOperationException();
226: }
227:
228: public int getLine() {
229: throw new UnsupportedOperationException();
230: }
231:
232: public int getColumn() {
233: throw new UnsupportedOperationException();
234: }
235: }
236:
237: }
|