001: /*
002: * Copyright 2002-2006 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.autoproxy;
018:
019: import java.util.Comparator;
020:
021: import org.springframework.aop.Advisor;
022: import org.springframework.aop.aspectj.AspectJAopUtils;
023: import org.springframework.aop.aspectj.AspectJPrecedenceInformation;
024: import org.springframework.core.OrderComparator;
025: import org.springframework.util.Assert;
026:
027: /**
028: * Orders AspectJ advice/advisors by precedence (<i>not</i> invocation order).
029: *
030: * <p>Given two pieces of advice, <code>a</code> and <code>b</code>:
031: * <ul>
032: * <li>if <code>a</code> and <code>b</code> are defined in different
033: * aspects, then the advice in the aspect with the lowest order
034: * value has the highest precedence</li>
035: * <li>if <code>a</code> and <code>b</code> are defined in the same
036: * aspect, then if one of <code>a</code> or <code>b</code> is a form of
037: * after advice, then the advice declared last in the aspect has the
038: * highest precedence. If neither <code>a</code> nor <code>b</code> is a
039: * form of after advice, then the advice declared first in the aspect has
040: * the highest precedence.</li>
041: * </ul>
042: *
043: * <p>Important: Note that unlike a normal comparator a return of 0 means
044: * we don't care about the ordering, not that the two elements must be sorted
045: * identically. Used with AspectJ PartialOrder class.
046: *
047: * @author Adrian Colyer
048: * @author Juergen Hoeller
049: * @since 2.0
050: */
051: class AspectJPrecedenceComparator implements Comparator {
052:
053: private static final int HIGHER_PRECEDENCE = -1;
054: private static final int SAME_PRECEDENCE = 0;
055: private static final int LOWER_PRECEDENCE = 1;
056: private static final int NOT_COMPARABLE = 0;
057:
058: private final Comparator advisorComparator;
059:
060: /**
061: * Create a default AspectJPrecedenceComparator.
062: */
063: public AspectJPrecedenceComparator() {
064: this .advisorComparator = new OrderComparator();
065: }
066:
067: /**
068: * Create a AspectJPrecedenceComparator, using the given Comparator
069: * for comparing {@link org.springframework.aop.Advisor} instances.
070: * @param advisorComparator the Comparator to use for Advisors
071: */
072: public AspectJPrecedenceComparator(Comparator advisorComparator) {
073: Assert.notNull(advisorComparator,
074: "Advisor comparator must not be null");
075: this .advisorComparator = advisorComparator;
076: }
077:
078: public int compare(Object o1, Object o2) {
079: if (!(o1 instanceof Advisor && o2 instanceof Advisor)) {
080: throw new IllegalArgumentException(
081: "AspectJPrecedenceComparator can only compare the order of Advisors, "
082: + "but was passed [" + o1 + "] and [" + o2
083: + "]");
084: }
085:
086: Advisor advisor1 = (Advisor) o1;
087: Advisor advisor2 = (Advisor) o2;
088:
089: boolean oneOrOtherIsAfterAdvice = (AspectJAopUtils
090: .isAfterAdvice(advisor1) || AspectJAopUtils
091: .isAfterAdvice(advisor2));
092: boolean oneOrOtherIsBeforeAdvice = (AspectJAopUtils
093: .isBeforeAdvice(advisor1) || AspectJAopUtils
094: .isBeforeAdvice(advisor2));
095: if (oneOrOtherIsAfterAdvice && oneOrOtherIsBeforeAdvice) {
096: return NOT_COMPARABLE;
097: } else {
098: int advisorPrecedence = this .advisorComparator.compare(
099: advisor1, advisor2);
100: if (advisorPrecedence == SAME_PRECEDENCE
101: && declaredInSameAspect(advisor1, advisor2)) {
102: advisorPrecedence = comparePrecedenceWithinAspect(
103: advisor1, advisor2);
104: }
105: return advisorPrecedence;
106: }
107: }
108:
109: private int comparePrecedenceWithinAspect(Advisor advisor1,
110: Advisor advisor2) {
111: boolean oneOrOtherIsAfterAdvice = (AspectJAopUtils
112: .isAfterAdvice(advisor1) || AspectJAopUtils
113: .isAfterAdvice(advisor2));
114: int adviceDeclarationOrderDelta = getAspectDeclarationOrder(advisor1)
115: - getAspectDeclarationOrder(advisor2);
116:
117: if (oneOrOtherIsAfterAdvice) {
118: // the advice declared last has higher precedence
119: if (adviceDeclarationOrderDelta < 0) {
120: // advice1 was declared before advice2
121: // so advice1 has lower precedence
122: return LOWER_PRECEDENCE;
123: } else if (adviceDeclarationOrderDelta == 0) {
124: return SAME_PRECEDENCE;
125: } else {
126: return HIGHER_PRECEDENCE;
127: }
128: } else {
129: // the advice declared first has higher precedence
130: if (adviceDeclarationOrderDelta < 0) {
131: // advice1 was declared before advice2
132: // so advice1 has higher precedence
133: return HIGHER_PRECEDENCE;
134: } else if (adviceDeclarationOrderDelta == 0) {
135: return SAME_PRECEDENCE;
136: } else {
137: return LOWER_PRECEDENCE;
138: }
139: }
140: }
141:
142: private boolean declaredInSameAspect(Advisor advisor1,
143: Advisor advisor2) {
144: if (!(hasAspectName(advisor1) && hasAspectName(advisor2))) {
145: return false;
146: } else {
147: return getAspectName(advisor1).equals(
148: getAspectName(advisor2));
149: }
150: }
151:
152: private boolean hasAspectName(Advisor anAdvisor) {
153: return (anAdvisor instanceof AspectJPrecedenceInformation || anAdvisor
154: .getAdvice() instanceof AspectJPrecedenceInformation);
155: }
156:
157: // pre-condition is that hasAspectName returned true
158: private String getAspectName(Advisor anAdvisor) {
159: return AspectJAopUtils.getAspectJPrecedenceInformationFor(
160: anAdvisor).getAspectName();
161: }
162:
163: private int getAspectDeclarationOrder(Advisor anAdvisor) {
164: AspectJPrecedenceInformation precedenceInfo = AspectJAopUtils
165: .getAspectJPrecedenceInformationFor(anAdvisor);
166: if (precedenceInfo != null) {
167: return precedenceInfo.getDeclarationOrder();
168: } else {
169: return 0;
170: }
171: }
172:
173: }
|