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 org.aopalliance.aop.Advice;
020:
021: import org.springframework.aop.ClassFilter;
022: import org.springframework.aop.IntroductionAdvisor;
023: import org.springframework.aop.support.ClassFilters;
024: import org.springframework.aop.support.DelegatePerTargetObjectIntroductionInterceptor;
025: import org.springframework.aop.support.DelegatingIntroductionInterceptor;
026:
027: /**
028: * Introduction advisor delegating to the given object.
029: * Implements AspectJ annotation-style behavior for the DeclareParents annotation.
030: *
031: * @author Rod Johnson
032: * @author Ramnivas Laddad
033: * @since 2.0
034: */
035: public class DeclareParentsAdvisor implements IntroductionAdvisor {
036:
037: private final Class introducedInterface;
038:
039: private final ClassFilter typePatternClassFilter;
040:
041: private final Advice advice;
042:
043: /**
044: * Create a new advisor for this DeclareParents field.
045: * @param interfaceType static field defining the introduction
046: * @param typePattern type pattern the introduction is restricted to
047: * @param defaultImpl the default implementation class
048: */
049: public DeclareParentsAdvisor(Class interfaceType,
050: String typePattern, Class defaultImpl) {
051: this (interfaceType, typePattern, defaultImpl,
052: new DelegatePerTargetObjectIntroductionInterceptor(
053: defaultImpl, interfaceType));
054: }
055:
056: /**
057: * Create a new advisor for this DeclareParents field.
058: * @param interfaceType static field defining the introduction
059: * @param typePattern type pattern the introduction is restricted to
060: * @param delegateRef the delegate implementation object
061: */
062: public DeclareParentsAdvisor(Class interfaceType,
063: String typePattern, Object delegateRef) {
064: this (interfaceType, typePattern, delegateRef.getClass(),
065: new DelegatingIntroductionInterceptor(delegateRef));
066: }
067:
068: /**
069: * Private constructor to share common code between impl-based delegate and reference-based delegate
070: * (cannot use method such as init() to share common code, due the the use of final fields)
071: * @param interfaceType static field defining the introduction
072: * @param typePattern type pattern the introduction is restricted to
073: * @param implementationClass implementation class
074: * @param advice delegation advice
075: */
076: private DeclareParentsAdvisor(Class interfaceType,
077: String typePattern, Class implementationClass, Advice advice) {
078: this .introducedInterface = interfaceType;
079: ClassFilter typePatternFilter = new TypePatternClassFilter(
080: typePattern);
081:
082: // Excludes methods implemented.
083: ClassFilter exclusion = new ClassFilter() {
084: public boolean matches(Class clazz) {
085: return !(introducedInterface.isAssignableFrom(clazz));
086: }
087: };
088:
089: this .typePatternClassFilter = ClassFilters.intersection(
090: typePatternFilter, exclusion);
091: this .advice = advice;
092: }
093:
094: public ClassFilter getClassFilter() {
095: return this .typePatternClassFilter;
096: }
097:
098: public void validateInterfaces() throws IllegalArgumentException {
099: // Do nothing
100: }
101:
102: public boolean isPerInstance() {
103: return true;
104: }
105:
106: public Advice getAdvice() {
107: return this .advice;
108: }
109:
110: public Class[] getInterfaces() {
111: return new Class[] { this.introducedInterface };
112: }
113:
114: }
|