001/* 002 * Copyright 2002-2013 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.springframework.aop.ClassFilter; 022import org.springframework.util.Assert; 023import org.springframework.util.ObjectUtils; 024 025/** 026 * Static utility methods for composing {@link ClassFilter ClassFilters}. 027 * 028 * @author Rod Johnson 029 * @author Rob Harrop 030 * @author Juergen Hoeller 031 * @since 11.11.2003 032 * @see MethodMatchers 033 * @see Pointcuts 034 */ 035public abstract class ClassFilters { 036 037 /** 038 * Match all classes that <i>either</i> (or both) of the given ClassFilters matches. 039 * @param cf1 the first ClassFilter 040 * @param cf2 the second ClassFilter 041 * @return a distinct ClassFilter that matches all classes that either 042 * of the given ClassFilter matches 043 */ 044 public static ClassFilter union(ClassFilter cf1, ClassFilter cf2) { 045 Assert.notNull(cf1, "First ClassFilter must not be null"); 046 Assert.notNull(cf2, "Second ClassFilter must not be null"); 047 return new UnionClassFilter(new ClassFilter[] {cf1, cf2}); 048 } 049 050 /** 051 * Match all classes that <i>either</i> (or all) of the given ClassFilters matches. 052 * @param classFilters the ClassFilters to match 053 * @return a distinct ClassFilter that matches all classes that either 054 * of the given ClassFilter matches 055 */ 056 public static ClassFilter union(ClassFilter[] classFilters) { 057 Assert.notEmpty(classFilters, "ClassFilter array must not be empty"); 058 return new UnionClassFilter(classFilters); 059 } 060 061 /** 062 * Match all classes that <i>both</i> of the given ClassFilters match. 063 * @param cf1 the first ClassFilter 064 * @param cf2 the second ClassFilter 065 * @return a distinct ClassFilter that matches all classes that both 066 * of the given ClassFilter match 067 */ 068 public static ClassFilter intersection(ClassFilter cf1, ClassFilter cf2) { 069 Assert.notNull(cf1, "First ClassFilter must not be null"); 070 Assert.notNull(cf2, "Second ClassFilter must not be null"); 071 return new IntersectionClassFilter(new ClassFilter[] {cf1, cf2}); 072 } 073 074 /** 075 * Match all classes that <i>all</i> of the given ClassFilters match. 076 * @param classFilters the ClassFilters to match 077 * @return a distinct ClassFilter that matches all classes that both 078 * of the given ClassFilter match 079 */ 080 public static ClassFilter intersection(ClassFilter[] classFilters) { 081 Assert.notEmpty(classFilters, "ClassFilter array must not be empty"); 082 return new IntersectionClassFilter(classFilters); 083 } 084 085 086 /** 087 * ClassFilter implementation for a union of the given ClassFilters. 088 */ 089 @SuppressWarnings("serial") 090 private static class UnionClassFilter implements ClassFilter, Serializable { 091 092 private ClassFilter[] filters; 093 094 public UnionClassFilter(ClassFilter[] filters) { 095 this.filters = filters; 096 } 097 098 @Override 099 public boolean matches(Class<?> clazz) { 100 for (ClassFilter filter : this.filters) { 101 if (filter.matches(clazz)) { 102 return true; 103 } 104 } 105 return false; 106 } 107 108 @Override 109 public boolean equals(Object other) { 110 return (this == other || (other instanceof UnionClassFilter && 111 ObjectUtils.nullSafeEquals(this.filters, ((UnionClassFilter) other).filters))); 112 } 113 114 @Override 115 public int hashCode() { 116 return ObjectUtils.nullSafeHashCode(this.filters); 117 } 118 } 119 120 121 /** 122 * ClassFilter implementation for an intersection of the given ClassFilters. 123 */ 124 @SuppressWarnings("serial") 125 private static class IntersectionClassFilter implements ClassFilter, Serializable { 126 127 private ClassFilter[] filters; 128 129 public IntersectionClassFilter(ClassFilter[] filters) { 130 this.filters = filters; 131 } 132 133 @Override 134 public boolean matches(Class<?> clazz) { 135 for (ClassFilter filter : this.filters) { 136 if (!filter.matches(clazz)) { 137 return false; 138 } 139 } 140 return true; 141 } 142 143 @Override 144 public boolean equals(Object other) { 145 return (this == other || (other instanceof IntersectionClassFilter && 146 ObjectUtils.nullSafeEquals(this.filters, ((IntersectionClassFilter) other).filters))); 147 } 148 149 @Override 150 public int hashCode() { 151 return ObjectUtils.nullSafeHashCode(this.filters); 152 } 153 } 154 155}