1 3 23 24 package org.xsocket.stream; 25 26 import java.io.IOException ; 27 import java.lang.reflect.Array ; 28 import java.lang.reflect.Field ; 29 import java.util.ArrayList ; 30 import java.util.Arrays ; 31 import java.util.List ; 32 import java.util.logging.Level ; 33 import java.util.logging.Logger ; 34 35 import org.xsocket.Resource; 36 37 38 39 40 67 public final class HandlerChain implements IHandler, IConnectHandler, IDisconnectHandler, IDataHandler, ITimeoutHandler, IConnectionScoped, org.xsocket.ILifeCycle { 68 69 private static final Logger LOG = Logger.getLogger(HandlerChain.class.getName()); 70 71 private IHandler[] handlers = new IHandler[0]; 72 private Integer [] connectionScopedIndex = new Integer [0]; 73 74 private Integer [] connectHandlerChain = new Integer [0]; 75 private Integer [] disconnectHandlerChain = new Integer [0]; 76 private Integer [] dataHandlerChain = new Integer [0]; 77 private Integer [] timeoutHandlerChain = new Integer [0]; 78 private Integer [] lifeCycleChain = new Integer [0]; 79 80 private List <HandlerChain> enclosingChains = new ArrayList <HandlerChain>(); 81 82 83 @Resource 84 private IServerContext ctx = null; 85 86 87 88 89 93 public HandlerChain() { 94 95 } 96 97 98 103 public HandlerChain(List <IHandler> handlers) { 104 for (IHandler hdl : handlers) { 105 addLast(hdl); 106 } 107 } 108 109 114 public void addLast(IHandler handler) { 115 int pos = handlers.length; 116 handlers = incArray(handlers, handler); 117 118 if (handler instanceof IConnectHandler) { 119 connectHandlerChain = incArray(connectHandlerChain, pos); 120 } 121 122 if (handler instanceof IDisconnectHandler) { 123 disconnectHandlerChain = incArray(disconnectHandlerChain, pos); 124 } 125 126 127 if (handler instanceof IDataHandler) { 128 dataHandlerChain = incArray(dataHandlerChain, pos); 129 } 130 131 if (handler instanceof ITimeoutHandler) { 132 timeoutHandlerChain = incArray(timeoutHandlerChain, pos); 133 } 134 135 if (handler instanceof org.xsocket.ILifeCycle) { 136 lifeCycleChain = incArray(lifeCycleChain, pos); 137 } 138 139 140 if (handler instanceof HandlerChain) { 142 ((HandlerChain) handler).addEnclosingChain(this); 143 } 144 145 146 if (handler instanceof IConnectionScoped) { 148 updateScope(pos, true); 149 } else { 150 updateScope(pos, false); 151 } 152 } 153 154 155 private void addEnclosingChain(HandlerChain enclosingChain) { 156 if (enclosingChains == null) { 157 enclosingChains = new ArrayList <HandlerChain>(); 158 } 159 enclosingChains.add(enclosingChain); 160 } 161 162 163 private void updateScope(IHandler handler, boolean isConnectionScoped) { 164 for (int i = 0; i < handlers.length; i++) { 165 if (handlers[i] == handler) { 166 updateScope(i, isConnectionScoped); 167 return; 168 } 169 } 170 } 171 172 private void updateScope(int pos, boolean isConnectionScoped) { 173 if (isConnectionScoped) { 174 connectionScopedIndex = incArray(connectionScopedIndex, pos); 175 176 if (enclosingChains != null) { 177 for (HandlerChain chain : enclosingChains) { 178 chain.updateScope(this, true); 179 } 180 } 181 } 182 } 183 184 185 188 public void onInit() { 189 190 for (IHandler handler : handlers) { 191 Field [] fields = handler.getClass().getDeclaredFields(); 192 for (Field field : fields) { 193 if (field.getAnnotation(Resource.class) != null) { 194 field.setAccessible(true); 195 try { 196 field.set(handler, ctx); 197 } catch (IllegalAccessException iae) { 198 LOG.warning("couldn't set HandlerContext for attribute " + field.getName() + ". Reason " + iae.toString()); 199 } 200 201 } 202 } 203 } 204 205 206 for (Integer pos : lifeCycleChain) { 207 ((org.xsocket.ILifeCycle) handlers[pos]).onInit(); 208 } 209 } 210 211 212 215 public void onDestroy() { 216 for (Integer pos : lifeCycleChain) { 217 ((org.xsocket.ILifeCycle) handlers[pos]).onDestroy(); 218 } 219 } 220 221 222 225 public boolean onConnect(INonBlockingConnection connection) throws IOException { 226 for (Integer pos : connectHandlerChain) { 227 boolean result = ((IConnectHandler) handlers[pos]).onConnect(connection); 228 if (result == true) { 229 return true; 230 } 231 } 232 233 return false; 234 } 235 236 237 240 public boolean onDisconnect(INonBlockingConnection connection) throws IOException { 241 for (Integer pos : disconnectHandlerChain) { 242 boolean result = ((IDisconnectHandler) handlers[pos]).onDisconnect(connection); 243 if (result == true) { 244 return true; 245 } 246 } 247 248 return false; 249 } 250 251 254 public boolean onData(INonBlockingConnection connection) throws IOException { 255 for (Integer pos : dataHandlerChain) { 256 boolean result = ((IDataHandler) handlers[pos]).onData(connection); 257 if (result == true) { 258 return true; 259 } 260 } 261 262 return false; 263 } 264 265 266 269 public boolean onConnectionTimeout(INonBlockingConnection connection) throws IOException { 270 for (Integer pos : timeoutHandlerChain) { 271 boolean result = ((ITimeoutHandler) handlers[pos]).onConnectionTimeout(connection); 272 if (result == true) { 273 return true; 274 } 275 } 276 277 return false; 278 } 279 280 281 284 public boolean onIdleTimeout(INonBlockingConnection connection) throws IOException { 285 for (Integer pos : timeoutHandlerChain) { 286 boolean result = ((ITimeoutHandler) handlers[pos]).onIdleTimeout(connection); 287 if (result == true) { 288 return true; 289 } 290 } 291 292 return false; 293 294 } 295 296 297 303 IHandler getHandler(int pos) { 304 return handlers[pos]; 305 }; 306 307 308 309 312 @Override 313 public Object clone() throws CloneNotSupportedException { 314 315 if (connectionScopedIndex.length > 0) { 316 HandlerChain clone = (HandlerChain) super.clone(); 317 clone.handlers = handlers.clone(); 318 319 for (int i =0; i < connectionScopedIndex.length; i++) { 320 int position = connectionScopedIndex[i]; 321 clone.handlers[position] = (IHandler) ((IConnectionScoped) handlers[position]).clone(); 322 } 323 324 return clone; 325 326 } else { 327 if (LOG.isLoggable(Level.FINEST)) { 328 LOG.finest(this.getClass().getSimpleName() + " doesn't contain connection-specific handlers. return current instance as clone"); 329 } 330 return this; 331 } 332 } 333 334 @SuppressWarnings ("unchecked") 335 private static <T> T[] incArray(T[] original, T newElement) { 336 T[] newArray = (T[]) copyOf(original, original.length + 1, original.getClass()); 337 newArray[original.length] = newElement; 338 339 return newArray; 340 } 341 342 345 @SuppressWarnings ("unchecked") 346 private static <T,U> T[] copyOf(U[] original, int newLength, Class <? extends T[]> newType) { 347 T[] copy = ((Object )newType == (Object )Object [].class) 348 ? (T[]) new Object [newLength] 349 : (T[]) Array.newInstance(newType.getComponentType(), newLength); 350 System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); 351 return copy; 352 } 353 } 354 | Popular Tags |