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