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.interceptor;
018:
019: import org.aopalliance.intercept.MethodInterceptor;
020: import org.aopalliance.intercept.MethodInvocation;
021:
022: import org.springframework.aop.Advisor;
023: import org.springframework.aop.ProxyMethodInvocation;
024: import org.springframework.aop.support.DefaultIntroductionAdvisor;
025: import org.springframework.aop.support.DefaultPointcutAdvisor;
026: import org.springframework.aop.support.DelegatingIntroductionInterceptor;
027: import org.springframework.beans.factory.NamedBean;
028:
029: /**
030: * Convenient methods for creating advisors that may be used when autoproxying beans
031: * created with the Spring IoC container, binding the bean name to the current
032: * invocation. May support a <code>bean()</code> pointcut designator with AspectJ.
033: *
034: * <p>Typically used in Spring auto-proxying, where the bean name is known
035: * at proxy creation time.
036: *
037: * @author Rod Johnson
038: * @author Juergen Hoeller
039: * @since 2.0
040: * @see org.springframework.beans.factory.NamedBean
041: */
042: public abstract class ExposeBeanNameAdvisors {
043:
044: /**
045: * Binding for the bean name of the bean which is currently being invoked
046: * in the ReflectiveMethodInvocation userAttributes Map.
047: */
048: private static final String BEAN_NAME_ATTRIBUTE = ExposeBeanNameAdvisors.class
049: .getName()
050: + ".beanName";
051:
052: /**
053: * Find the bean name for the current invocation. Assumes that an ExposeBeanNameAdvisor
054: * has been included in the interceptor chain, and that the invocation is exposed
055: * with ExposeInvocationInterceptor.
056: * @return the bean name (never <code>null</code>)
057: * @throws IllegalStateException if the bean name has not been exposed
058: */
059: public static String getBeanName() throws IllegalStateException {
060: return getBeanName(ExposeInvocationInterceptor
061: .currentInvocation());
062: }
063:
064: /**
065: * Find the bean name for the given invocation. Assumes that an ExposeBeanNameAdvisor
066: * has been included in the interceptor chain.
067: * @param mi MethodInvocation that should contain the bean name as an attribute
068: * @return the bean name (never <code>null</code>)
069: * @throws IllegalStateException if the bean name has not been exposed
070: */
071: public static String getBeanName(MethodInvocation mi)
072: throws IllegalStateException {
073: if (!(mi instanceof ProxyMethodInvocation)) {
074: throw new IllegalArgumentException(
075: "MethodInvocation is not a Spring ProxyMethodInvocation: "
076: + mi);
077: }
078: ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
079: String beanName = (String) pmi
080: .getUserAttribute(BEAN_NAME_ATTRIBUTE);
081: if (beanName == null) {
082: throw new IllegalStateException(
083: "Cannot get bean name; not set on MethodInvocation: "
084: + mi);
085: }
086: return beanName;
087: }
088:
089: /**
090: * Create a new advisor that will expose the given bean name,
091: * with no introduction
092: * @param beanName bean name to expose
093: */
094: public static Advisor createAdvisorWithoutIntroduction(
095: String beanName) {
096: return new DefaultPointcutAdvisor(
097: new ExposeBeanNameInterceptor(beanName));
098: }
099:
100: /**
101: * Create a new advisor that will expose the given bean name, introducing
102: * the NamedBean interface to make the bean name accessible without forcing
103: * the target object to be aware of this Spring IoC concept.
104: * @param beanName the bean name to expose
105: */
106: public static Advisor createAdvisorIntroducingNamedBean(
107: String beanName) {
108: return new DefaultIntroductionAdvisor(
109: new ExposeBeanNameIntroduction(beanName));
110: }
111:
112: /**
113: * Interceptor that exposes the specified bean name as invocation attribute.
114: */
115: private static class ExposeBeanNameInterceptor implements
116: MethodInterceptor {
117:
118: private final String beanName;
119:
120: public ExposeBeanNameInterceptor(String beanName) {
121: this .beanName = beanName;
122: }
123:
124: public Object invoke(MethodInvocation mi) throws Throwable {
125: if (!(mi instanceof ProxyMethodInvocation)) {
126: throw new IllegalStateException(
127: "MethodInvocation is not a Spring ProxyMethodInvocation: "
128: + mi);
129: }
130: ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
131: pmi.setUserAttribute(BEAN_NAME_ATTRIBUTE, beanName);
132: return mi.proceed();
133: }
134: }
135:
136: /**
137: * Introduction that exposes the specified bean name as invocation attribute.
138: */
139: private static class ExposeBeanNameIntroduction extends
140: DelegatingIntroductionInterceptor implements NamedBean {
141:
142: private final String beanName;
143:
144: public ExposeBeanNameIntroduction(String beanName) {
145: this .beanName = beanName;
146: }
147:
148: public Object invoke(MethodInvocation mi) throws Throwable {
149: if (!(mi instanceof ProxyMethodInvocation)) {
150: throw new IllegalStateException(
151: "MethodInvocation is not a Spring ProxyMethodInvocation: "
152: + mi);
153: }
154: ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
155: pmi.setUserAttribute(BEAN_NAME_ATTRIBUTE, beanName);
156: return super .invoke(mi);
157: }
158:
159: public String getBeanName() {
160: return this.beanName;
161: }
162: }
163:
164: }
|