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.config;
018:
019: import java.util.ArrayList;
020: import java.util.List;
021:
022: import org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator;
023: import org.springframework.aop.framework.autoproxy.InfrastructureAdvisorAutoProxyCreator;
024: import org.springframework.beans.factory.config.BeanDefinition;
025: import org.springframework.beans.factory.support.BeanDefinitionRegistry;
026: import org.springframework.beans.factory.support.RootBeanDefinition;
027: import org.springframework.core.JdkVersion;
028: import org.springframework.core.Ordered;
029: import org.springframework.util.Assert;
030: import org.springframework.util.ClassUtils;
031:
032: /**
033: * Utility class for handling registration of AOP auto-proxy creators.
034: *
035: * <p>Only a single auto-proxy creator can be registered yet multiple concrete
036: * implementations are available. Therefore this class wraps a simple escalation
037: * protocol, allowing classes to request a particular auto-proxy creator and know
038: * that class, <code>or a subclass thereof</code>, will eventually be resident
039: * in the application context.
040: *
041: * @author Rob Harrop
042: * @author Juergen Hoeller
043: * @author Mark Fisher
044: * @since 2.5
045: */
046: public abstract class AopConfigUtils {
047:
048: /**
049: * The bean name of the internally managed auto-proxy creator.
050: */
051: public static final String AUTO_PROXY_CREATOR_BEAN_NAME = "org.springframework.aop.config.internalAutoProxyCreator";
052:
053: /**
054: * The class name of the <code>AnnotationAwareAspectJAutoProxyCreator</code> class.
055: * Only available with AspectJ and Java 5.
056: */
057: private static final String ASPECTJ_ANNOTATION_AUTO_PROXY_CREATOR_CLASS_NAME = "org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator";
058:
059: /**
060: * Stores the auto proxy creator classes in escalation order.
061: */
062: private static final List APC_PRIORITY_LIST = new ArrayList();
063:
064: /**
065: * Setup the escalation list.
066: */
067: static {
068: APC_PRIORITY_LIST
069: .add(InfrastructureAdvisorAutoProxyCreator.class
070: .getName());
071: APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class
072: .getName());
073: APC_PRIORITY_LIST
074: .add(ASPECTJ_ANNOTATION_AUTO_PROXY_CREATOR_CLASS_NAME);
075: }
076:
077: public static BeanDefinition registerAutoProxyCreatorIfNecessary(
078: BeanDefinitionRegistry registry) {
079: return registerAutoProxyCreatorIfNecessary(registry, null);
080: }
081:
082: public static BeanDefinition registerAutoProxyCreatorIfNecessary(
083: BeanDefinitionRegistry registry, Object source) {
084: return registerOrEscalateApcAsRequired(
085: InfrastructureAdvisorAutoProxyCreator.class, registry,
086: source);
087: }
088:
089: public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(
090: BeanDefinitionRegistry registry) {
091: return registerAspectJAutoProxyCreatorIfNecessary(registry,
092: null);
093: }
094:
095: public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(
096: BeanDefinitionRegistry registry, Object source) {
097: return registerOrEscalateApcAsRequired(
098: AspectJAwareAdvisorAutoProxyCreator.class, registry,
099: source);
100: }
101:
102: public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
103: BeanDefinitionRegistry registry) {
104: return registerAspectJAnnotationAutoProxyCreatorIfNecessary(
105: registry, null);
106: }
107:
108: public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
109: BeanDefinitionRegistry registry, Object source) {
110: Class cls = getAspectJAnnotationAutoProxyCreatorClassIfPossible();
111: return registerOrEscalateApcAsRequired(cls, registry, source);
112: }
113:
114: public static void forceAutoProxyCreatorToUseClassProxying(
115: BeanDefinitionRegistry registry) {
116: if (registry
117: .containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
118: BeanDefinition definition = registry
119: .getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
120: definition.getPropertyValues().addPropertyValue(
121: "proxyTargetClass", Boolean.TRUE);
122: }
123: }
124:
125: private static BeanDefinition registerOrEscalateApcAsRequired(
126: Class cls, BeanDefinitionRegistry registry, Object source) {
127: Assert.notNull(registry,
128: "BeanDefinitionRegistry must not be null");
129: if (registry
130: .containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
131: BeanDefinition apcDefinition = registry
132: .getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
133: if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
134: int currentPriority = findPriorityForClass(apcDefinition
135: .getBeanClassName());
136: int requiredPriority = findPriorityForClass(cls
137: .getName());
138: if (currentPriority < requiredPriority) {
139: apcDefinition.setBeanClassName(cls.getName());
140: }
141: }
142: return null;
143: }
144: RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
145: beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
146: beanDefinition.setSource(source);
147: beanDefinition.getPropertyValues().addPropertyValue("order",
148: new Integer(Ordered.HIGHEST_PRECEDENCE));
149: registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME,
150: beanDefinition);
151: return beanDefinition;
152: }
153:
154: private static Class getAspectJAnnotationAutoProxyCreatorClassIfPossible() {
155: if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_15) {
156: throw new IllegalStateException(
157: "AnnotationAwareAspectJAutoProxyCreator is only available on Java 1.5 and higher");
158: }
159: try {
160: return ClassUtils.forName(
161: ASPECTJ_ANNOTATION_AUTO_PROXY_CREATOR_CLASS_NAME,
162: AopConfigUtils.class.getClassLoader());
163: } catch (Throwable ex) {
164: throw new IllegalStateException(
165: "Unable to load Java 1.5 dependent class ["
166: + ASPECTJ_ANNOTATION_AUTO_PROXY_CREATOR_CLASS_NAME
167: + "]", ex);
168: }
169: }
170:
171: private static int findPriorityForClass(String className) {
172: Assert.notNull(className, "Class name must not be null");
173: for (int i = 0; i < APC_PRIORITY_LIST.size(); i++) {
174: String str = (String) APC_PRIORITY_LIST.get(i);
175: if (className.equals(str)) {
176: return i;
177: }
178: }
179: throw new IllegalArgumentException("Class name [" + className
180: + "] is not a known auto-proxy creator class");
181: }
182:
183: }
|