001/*
002 * Copyright 2002-2014 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 *      https://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
017package org.springframework.aop.support;
018
019import java.io.Serializable;
020
021import org.aopalliance.aop.Advice;
022
023import org.springframework.aop.Pointcut;
024import org.springframework.util.ObjectUtils;
025
026/**
027 * Convenient class for regexp method pointcuts that hold an Advice,
028 * making them an {@link org.springframework.aop.Advisor}.
029 *
030 * <p>Configure this class using the "pattern" and "patterns"
031 * pass-through properties. These are analogous to the pattern
032 * and patterns properties of {@link AbstractRegexpMethodPointcut}.
033 *
034 * <p>Can delegate to any {@link AbstractRegexpMethodPointcut} subclass.
035 * By default, {@link JdkRegexpMethodPointcut} will be used. To choose
036 * a specific one, override the {@link #createPointcut} method.
037 *
038 * @author Rod Johnson
039 * @author Juergen Hoeller
040 * @see #setPattern
041 * @see #setPatterns
042 * @see JdkRegexpMethodPointcut
043 */
044@SuppressWarnings("serial")
045public class RegexpMethodPointcutAdvisor extends AbstractGenericPointcutAdvisor {
046
047        private String[] patterns;
048
049        private AbstractRegexpMethodPointcut pointcut;
050
051        private final Object pointcutMonitor = new SerializableMonitor();
052
053
054        /**
055         * Create an empty RegexpMethodPointcutAdvisor.
056         * @see #setPattern
057         * @see #setPatterns
058         * @see #setAdvice
059         */
060        public RegexpMethodPointcutAdvisor() {
061        }
062
063        /**
064         * Create a RegexpMethodPointcutAdvisor for the given advice.
065         * The pattern still needs to be specified afterwards.
066         * @param advice the advice to use
067         * @see #setPattern
068         * @see #setPatterns
069         */
070        public RegexpMethodPointcutAdvisor(Advice advice) {
071                setAdvice(advice);
072        }
073
074        /**
075         * Create a RegexpMethodPointcutAdvisor for the given advice.
076         * @param pattern the pattern to use
077         * @param advice the advice to use
078         */
079        public RegexpMethodPointcutAdvisor(String pattern, Advice advice) {
080                setPattern(pattern);
081                setAdvice(advice);
082        }
083
084        /**
085         * Create a RegexpMethodPointcutAdvisor for the given advice.
086         * @param patterns the patterns to use
087         * @param advice the advice to use
088         */
089        public RegexpMethodPointcutAdvisor(String[] patterns, Advice advice) {
090                setPatterns(patterns);
091                setAdvice(advice);
092        }
093
094
095        /**
096         * Set the regular expression defining methods to match.
097         * <p>Use either this method or {@link #setPatterns}, not both.
098         * @see #setPatterns
099         */
100        public void setPattern(String pattern) {
101                setPatterns(pattern);
102        }
103
104        /**
105         * Set the regular expressions defining methods to match.
106         * To be passed through to the pointcut implementation.
107         * <p>Matching will be the union of all these; if any of the
108         * patterns matches, the pointcut matches.
109         * @see AbstractRegexpMethodPointcut#setPatterns
110         */
111        public void setPatterns(String... patterns) {
112                this.patterns = patterns;
113        }
114
115
116        /**
117         * Initialize the singleton Pointcut held within this Advisor.
118         */
119        @Override
120        public Pointcut getPointcut() {
121                synchronized (this.pointcutMonitor) {
122                        if (this.pointcut == null) {
123                                this.pointcut = createPointcut();
124                                this.pointcut.setPatterns(this.patterns);
125                        }
126                        return pointcut;
127                }
128        }
129
130        /**
131         * Create the actual pointcut: By default, a {@link JdkRegexpMethodPointcut}
132         * will be used.
133         * @return the Pointcut instance (never {@code null})
134         */
135        protected AbstractRegexpMethodPointcut createPointcut() {
136                return new JdkRegexpMethodPointcut();
137        }
138
139        @Override
140        public String toString() {
141                return getClass().getName() + ": advice [" + getAdvice() +
142                                "], pointcut patterns " + ObjectUtils.nullSafeToString(this.patterns);
143        }
144
145
146        /**
147         * Empty class used for a serializable monitor object.
148         */
149        private static class SerializableMonitor implements Serializable {
150        }
151
152}