1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 * 19 */ 20 package org.apache.mina.common; 21 22 import java.net.SocketAddress; 23 24 import org.apache.mina.filter.ReferenceCountingIoFilter; 25 26 /** 27 * A filter which intercepts {@link IoHandler} events like Servlet 28 * filters. Filters can be used for these purposes: 29 * <ul> 30 * <li>Event logging,</li> 31 * <li>Performance measurement,</li> 32 * <li>Authorization,</li> 33 * <li>Overload control,</li> 34 * <li>Message transformation (e.g. encryption and decryption, ...),</li> 35 * <li>and many more.</li> 36 * </ul> 37 * <p> 38 * <strong>Please NEVER implement your filters to wrap 39 * {@link IoSession}s.</strong> Users can cache the reference to the 40 * session, which might malfunction if any filters are added or removed later. 41 * 42 * <h3>The Life Cycle</h3> 43 * {@link IoFilter}s are activated only when they are inside {@link IoFilterChain}. 44 * <p> 45 * When you add an {@link IoFilter} to an {@link IoFilterChain}: 46 * <ol> 47 * <li>{@link #init()} is invoked by {@link ReferenceCountingIoFilter} if 48 * the filter is added at the first time.</li> 49 * <li>{@link #onPreAdd(IoFilterChain, String, NextFilter)} is invoked to notify 50 * that the filter will be added to the chain.</li> 51 * <li>The filter is added to the chain, and all events and I/O requests 52 * pass through the filter from now.</li> 53 * <li>{@link #onPostAdd(IoFilterChain, String, NextFilter)} is invoked to notify 54 * that the filter is added to the chain.</li> 55 * <li>The filter is removed from the chain if {@link #onPostAdd(IoFilterChain, String, org.apache.mina.common.IoFilter.NextFilter)} 56 * threw an exception. {@link #destroy()} is also invoked by 57 * {@link ReferenceCountingIoFilter} if the filter is the last filter which 58 * was added to {@link IoFilterChain}s.</li> 59 * </ol> 60 * <p> 61 * When you remove an {@link IoFilter} from an {@link IoFilterChain}: 62 * <ol> 63 * <li>{@link #onPreRemove(IoFilterChain, String, NextFilter)} is invoked to 64 * notify that the filter will be removed from the chain.</li> 65 * <li>The filter is removed from the chain, and any events and I/O requests 66 * don't pass through the filter from now.</li> 67 * <li>{@link #onPostRemove(IoFilterChain, String, NextFilter)} is invoked to 68 * notify that the filter is removed from the chain.</li> 69 * <li>{@link #destroy()} is invoked by {@link ReferenceCountingIoFilter} if 70 * the removed filter was the last one.</li> 71 * </ol> 72 * 73 * @author The Apache Directory Project (mina-dev@directory.apache.org) 74 * @version $Rev: 599822 $, $Date: 2007-11-30 22:54:07 +0900 (Fri, 30 Nov 2007) $ 75 * 76 * @see IoFilterAdapter 77 */ 78 public interface IoFilter { 79 /** 80 * Invoked by {@link ReferenceCountingIoFilter} when this filter 81 * is added to a {@link IoFilterChain} at the first time, so you can 82 * initialize shared resources. Please note that this method is never 83 * called if you don't wrap a filter with {@link ReferenceCountingIoFilter}. 84 */ 85 void init() throws Exception; 86 87 /** 88 * Invoked by {@link ReferenceCountingIoFilter} when this filter 89 * is not used by any {@link IoFilterChain} anymore, so you can destroy 90 * shared resources. Please note that this method is never called if 91 * you don't wrap a filter with {@link ReferenceCountingIoFilter}. 92 */ 93 void destroy() throws Exception; 94 95 /** 96 * Invoked before this filter is added to the specified <tt>parent</tt>. 97 * Please note that this method can be invoked more than once if 98 * this filter is added to more than one parents. This method is not 99 * invoked before {@link #init()} is invoked. 100 * 101 * @param parent the parent who called this method 102 * @param name the name assigned to this filter 103 * @param nextFilter the {@link NextFilter} for this filter. You can reuse 104 * this object until this filter is removed from the chain. 105 */ 106 void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) 107 throws Exception; 108 109 /** 110 * Invoked after this filter is added to the specified <tt>parent</tt>. 111 * Please note that this method can be invoked more than once if 112 * this filter is added to more than one parents. This method is not 113 * invoked before {@link #init()} is invoked. 114 * 115 * @param parent the parent who called this method 116 * @param name the name assigned to this filter 117 * @param nextFilter the {@link NextFilter} for this filter. You can reuse 118 * this object until this filter is removed from the chain. 119 */ 120 void onPostAdd(IoFilterChain parent, String name, NextFilter nextFilter) 121 throws Exception; 122 123 /** 124 * Invoked before this filter is removed from the specified <tt>parent</tt>. 125 * Please note that this method can be invoked more than once if 126 * this filter is removed from more than one parents. 127 * This method is always invoked before {@link #destroy()} is invoked. 128 * 129 * @param parent the parent who called this method 130 * @param name the name assigned to this filter 131 * @param nextFilter the {@link NextFilter} for this filter. You can reuse 132 * this object until this filter is removed from the chain. 133 */ 134 void onPreRemove(IoFilterChain parent, String name, NextFilter nextFilter) 135 throws Exception; 136 137 /** 138 * Invoked after this filter is removed from the specified <tt>parent</tt>. 139 * Please note that this method can be invoked more than once if 140 * this filter is removed from more than one parents. 141 * This method is always invoked before {@link #destroy()} is invoked. 142 * 143 * @param parent the parent who called this method 144 * @param name the name assigned to this filter 145 * @param nextFilter the {@link NextFilter} for this filter. You can reuse 146 * this object until this filter is removed from the chain. 147 */ 148 void onPostRemove(IoFilterChain parent, String name, NextFilter nextFilter) 149 throws Exception; 150 151 /** 152 * Filters {@link IoHandler#sessionCreated(IoSession)} event. 153 */ 154 void sessionCreated(NextFilter nextFilter, IoSession session) 155 throws Exception; 156 157 /** 158 * Filters {@link IoHandler#sessionOpened(IoSession)} event. 159 */ 160 void sessionOpened(NextFilter nextFilter, IoSession session) 161 throws Exception; 162 163 /** 164 * Filters {@link IoHandler#sessionClosed(IoSession)} event. 165 */ 166 void sessionClosed(NextFilter nextFilter, IoSession session) 167 throws Exception; 168 169 /** 170 * Filters {@link IoHandler#sessionIdle(IoSession,IdleStatus)} 171 * event. 172 */ 173 void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) 174 throws Exception; 175 176 /** 177 * Filters {@link IoHandler#exceptionCaught(IoSession,Throwable)} 178 * event. 179 */ 180 void exceptionCaught(NextFilter nextFilter, IoSession session, 181 Throwable cause) throws Exception; 182 183 /** 184 * Filters {@link IoHandler#messageReceived(IoSession,Object)} 185 * event. 186 */ 187 void messageReceived(NextFilter nextFilter, IoSession session, 188 Object message) throws Exception; 189 190 /** 191 * Filters {@link IoHandler#messageSent(IoSession,Object)} 192 * event. 193 */ 194 void messageSent(NextFilter nextFilter, IoSession session, Object message) 195 throws Exception; 196 197 /** 198 * Filters {@link IoSession#close()} method invocation. 199 */ 200 void filterClose(NextFilter nextFilter, IoSession session) throws Exception; 201 202 /** 203 * Filters {@link IoSession#write(Object)} method invocation. 204 */ 205 void filterWrite(NextFilter nextFilter, IoSession session, 206 WriteRequest writeRequest) throws Exception; 207 208 /** 209 * Represents the next {@link IoFilter} in {@link IoFilterChain}. 210 */ 211 public interface NextFilter { 212 /** 213 * Forwards <tt>sessionCreated</tt> event to next filter. 214 */ 215 void sessionCreated(IoSession session); 216 217 /** 218 * Forwards <tt>sessionOpened</tt> event to next filter. 219 */ 220 void sessionOpened(IoSession session); 221 222 /** 223 * Forwards <tt>sessionClosed</tt> event to next filter. 224 */ 225 void sessionClosed(IoSession session); 226 227 /** 228 * Forwards <tt>sessionIdle</tt> event to next filter. 229 */ 230 void sessionIdle(IoSession session, IdleStatus status); 231 232 /** 233 * Forwards <tt>exceptionCaught</tt> event to next filter. 234 */ 235 void exceptionCaught(IoSession session, Throwable cause); 236 237 /** 238 * Forwards <tt>messageReceived</tt> event to next filter. 239 */ 240 void messageReceived(IoSession session, Object message); 241 242 /** 243 * Forwards <tt>messageSent</tt> event to next filter. 244 */ 245 void messageSent(IoSession session, Object message); 246 247 /** 248 * Forwards <tt>filterWrite</tt> event to next filter. 249 */ 250 void filterWrite(IoSession session, WriteRequest writeRequest); 251 252 /** 253 * Forwards <tt>filterClose</tt> event to next filter. 254 */ 255 void filterClose(IoSession session); 256 } 257 258 /** 259 * Represents write request fired by {@link IoSession#write(Object)}. 260 */ 261 public static class WriteRequest { 262 private static final WriteFuture UNUSED_FUTURE = new WriteFuture() { 263 public boolean isWritten() { 264 return false; 265 } 266 267 public void setWritten(boolean written) { 268 } 269 270 public IoSession getSession() { 271 return null; 272 } 273 274 public void join() { 275 } 276 277 public boolean join(long timeoutInMillis) { 278 return true; 279 } 280 281 public boolean isReady() { 282 return true; 283 } 284 285 public void addListener(IoFutureListener listener) { 286 throw new IllegalStateException( 287 "You can't add a listener to a dummy future."); 288 } 289 290 public void removeListener(IoFutureListener listener) { 291 throw new IllegalStateException( 292 "You can't add a listener to a dummy future."); 293 } 294 295 public Object getLock() { 296 return this; 297 } 298 }; 299 300 private final Object message; 301 302 private final WriteFuture future; 303 304 private final SocketAddress destination; 305 306 /** 307 * Creates a new instance without {@link WriteFuture}. You'll get 308 * an instance of {@link WriteFuture} even if you called this constructor 309 * because {@link #getFuture()} will return a bogus future. 310 */ 311 public WriteRequest(Object message) { 312 this(message, null, null); 313 } 314 315 /** 316 * Creates a new instance with {@link WriteFuture}. 317 */ 318 public WriteRequest(Object message, WriteFuture future) { 319 this(message, future, null); 320 } 321 322 /** 323 * Creates a new instance. 324 * 325 * @param message a message to write 326 * @param future a future that needs to be notified when an operation is finished 327 * @param destination the destination of the message. This property will be 328 * ignored unless the transport supports it. 329 */ 330 public WriteRequest(Object message, WriteFuture future, 331 SocketAddress destination) { 332 if (message == null) { 333 throw new NullPointerException("message"); 334 } 335 336 if (future == null) { 337 future = UNUSED_FUTURE; 338 } 339 340 this.message = message; 341 this.future = future; 342 this.destination = destination; 343 } 344 345 /** 346 * Returns {@link WriteFuture} that is associated with this write request. 347 */ 348 public WriteFuture getFuture() { 349 return future; 350 } 351 352 /** 353 * Returns a message object to be written. 354 */ 355 public Object getMessage() { 356 return message; 357 } 358 359 /** 360 * Returne the destination of this write request. 361 * 362 * @return <tt>null</tt> for the default destination 363 */ 364 public SocketAddress getDestination() { 365 return destination; 366 } 367 368 @Override 369 public String toString() { 370 return message.toString(); 371 } 372 } 373 }