View Javadoc
1   /*
2    * Copyright 2013 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.channel.group;
17  
18  import io.netty.channel.Channel;
19  import io.netty.channel.ServerChannel;
20  
21  /**
22   * Helper class which provides often used {@link ChannelMatcher} implementations.
23   */
24  public final class ChannelMatchers {
25  
26      private static final ChannelMatcher ALL_MATCHER = new ChannelMatcher() {
27          @Override
28          public boolean matches(Channel channel) {
29              return true;
30          }
31      };
32  
33      private static final ChannelMatcher SERVER_CHANNEL_MATCHER = isInstanceOf(ServerChannel.class);
34      private static final ChannelMatcher NON_SERVER_CHANNEL_MATCHER = isNotInstanceOf(ServerChannel.class);
35  
36      private ChannelMatchers() {
37          // static methods only
38      }
39  
40      /**
41       * Returns a {@link ChannelMatcher} that matches all {@link Channel}s.
42       */
43      public static ChannelMatcher all() {
44          return ALL_MATCHER;
45      }
46  
47      /**
48       * Returns a {@link ChannelMatcher} that matches all {@link Channel}s except the given.
49       */
50      public static ChannelMatcher isNot(Channel channel) {
51          return invert(is(channel));
52      }
53  
54      /**
55       * Returns a {@link ChannelMatcher} that matches the given {@link Channel}.
56       */
57      public static ChannelMatcher is(Channel channel) {
58          return new InstanceMatcher(channel);
59      }
60  
61      /**
62       * Returns a {@link ChannelMatcher} that matches all {@link Channel}s that are an instance of sub-type of
63       * the given class.
64       */
65      public static ChannelMatcher isInstanceOf(Class<? extends Channel> clazz) {
66          return new ClassMatcher(clazz);
67      }
68  
69      /**
70       * Returns a {@link ChannelMatcher} that matches all {@link Channel}s that are <strong>not</strong> an
71       * instance of sub-type of the given class.
72       */
73      public static ChannelMatcher isNotInstanceOf(Class<? extends Channel> clazz) {
74          return invert(isInstanceOf(clazz));
75      }
76  
77      /**
78       * Returns a {@link ChannelMatcher} that matches all {@link Channel}s that are of type {@link ServerChannel}.
79       */
80      public static ChannelMatcher isServerChannel() {
81           return SERVER_CHANNEL_MATCHER;
82      }
83  
84      /**
85       * Returns a {@link ChannelMatcher} that matches all {@link Channel}s that are <strong>not</strong> of type
86       * {@link ServerChannel}.
87       */
88      public static ChannelMatcher isNonServerChannel() {
89          return NON_SERVER_CHANNEL_MATCHER;
90      }
91  
92      /**
93       * Invert the given {@link ChannelMatcher}.
94       */
95      public static ChannelMatcher invert(ChannelMatcher matcher) {
96          return new InvertMatcher(matcher);
97      }
98  
99      /**
100      * Return a composite of the given {@link ChannelMatcher}s. This means all {@link ChannelMatcher} must
101      * return {@code true} to match.
102      */
103     public static ChannelMatcher compose(ChannelMatcher... matchers) {
104         if (matchers.length < 1) {
105             throw new IllegalArgumentException("matchers must at least contain one element");
106         }
107         if (matchers.length == 1) {
108             return matchers[0];
109         }
110         return new CompositeMatcher(matchers);
111     }
112 
113     private static final class CompositeMatcher implements ChannelMatcher {
114         private final ChannelMatcher[] matchers;
115 
116         CompositeMatcher(ChannelMatcher... matchers) {
117             this.matchers = matchers;
118         }
119 
120         @Override
121         public boolean matches(Channel channel) {
122             for (ChannelMatcher m: matchers) {
123                 if (!m.matches(channel)) {
124                     return false;
125                 }
126             }
127             return true;
128         }
129     }
130 
131     private static final class InvertMatcher implements ChannelMatcher {
132         private final ChannelMatcher matcher;
133 
134         InvertMatcher(ChannelMatcher matcher) {
135             this.matcher = matcher;
136         }
137 
138         @Override
139         public boolean matches(Channel channel) {
140             return !matcher.matches(channel);
141         }
142     }
143 
144     private static final class InstanceMatcher implements ChannelMatcher {
145         private final Channel channel;
146 
147         InstanceMatcher(Channel channel) {
148             this.channel = channel;
149         }
150 
151         @Override
152         public boolean matches(Channel ch) {
153             return channel == ch;
154         }
155     }
156 
157     private static final class ClassMatcher implements ChannelMatcher {
158         private final Class<? extends Channel> clazz;
159 
160         ClassMatcher(Class<? extends Channel> clazz) {
161             this.clazz = clazz;
162         }
163 
164         @Override
165         public boolean matches(Channel ch) {
166             return clazz.isInstance(ch);
167         }
168     }
169 }