1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package nginx.unit.websocket.pojo; 18 19 import java.io.InputStream; 20 import java.io.Reader; 21 import java.lang.annotation.Annotation; 22 import java.lang.reflect.Method; 23 import java.lang.reflect.Modifier; 24 import java.nio.ByteBuffer; 25 import java.util.ArrayList; 26 import java.util.Arrays; 27 import java.util.HashMap; 28 import java.util.HashSet; 29 import java.util.List; 30 import java.util.Map; 31 import java.util.Set; 32 33 import javax.websocket.CloseReason; 34 import javax.websocket.DecodeException; 35 import javax.websocket.Decoder; 36 import javax.websocket.DeploymentException; 37 import javax.websocket.EndpointConfig; 38 import javax.websocket.MessageHandler; 39 import javax.websocket.OnClose; 40 import javax.websocket.OnError; 41 import javax.websocket.OnMessage; 42 import javax.websocket.OnOpen; 43 import javax.websocket.PongMessage; 44 import javax.websocket.Session; 45 import javax.websocket.server.PathParam; 46 47 import org.apache.tomcat.util.res.StringManager; 48 import nginx.unit.websocket.DecoderEntry; 49 import nginx.unit.websocket.Util; 50 import nginx.unit.websocket.Util.DecoderMatch; 51 52 /** 53 * For a POJO class annotated with 54 * {@link javax.websocket.server.ServerEndpoint}, an instance of this class 55 * creates and caches the method handler, method information and parameter 56 * information for the onXXX calls. 57 */ 58 public class PojoMethodMapping { 59 60 private static final StringManager sm = 61 StringManager.getManager(PojoMethodMapping.class); 62 63 private final Method onOpen; 64 private final Method onClose; 65 private final Method onError; 66 private final PojoPathParam[] onOpenParams; 67 private final PojoPathParam[] onCloseParams; 68 private final PojoPathParam[] onErrorParams; 69 private final List<MessageHandlerInfo> onMessage = new ArrayList<>(); 70 private final String wsPath; 71 72 PojoMethodMapping(Class<?> clazzPojo, List<Class<? extends Decoder>> decoderClazzes, String wsPath)73 public PojoMethodMapping(Class<?> clazzPojo, 74 List<Class<? extends Decoder>> decoderClazzes, String wsPath) 75 throws DeploymentException { 76 77 this.wsPath = wsPath; 78 79 List<DecoderEntry> decoders = Util.getDecoders(decoderClazzes); 80 Method open = null; 81 Method close = null; 82 Method error = null; 83 Method[] clazzPojoMethods = null; 84 Class<?> currentClazz = clazzPojo; 85 while (!currentClazz.equals(Object.class)) { 86 Method[] currentClazzMethods = currentClazz.getDeclaredMethods(); 87 if (currentClazz == clazzPojo) { 88 clazzPojoMethods = currentClazzMethods; 89 } 90 for (Method method : currentClazzMethods) { 91 if (method.getAnnotation(OnOpen.class) != null) { 92 checkPublic(method); 93 if (open == null) { 94 open = method; 95 } else { 96 if (currentClazz == clazzPojo || 97 !isMethodOverride(open, method)) { 98 // Duplicate annotation 99 throw new DeploymentException(sm.getString( 100 "pojoMethodMapping.duplicateAnnotation", 101 OnOpen.class, currentClazz)); 102 } 103 } 104 } else if (method.getAnnotation(OnClose.class) != null) { 105 checkPublic(method); 106 if (close == null) { 107 close = method; 108 } else { 109 if (currentClazz == clazzPojo || 110 !isMethodOverride(close, method)) { 111 // Duplicate annotation 112 throw new DeploymentException(sm.getString( 113 "pojoMethodMapping.duplicateAnnotation", 114 OnClose.class, currentClazz)); 115 } 116 } 117 } else if (method.getAnnotation(OnError.class) != null) { 118 checkPublic(method); 119 if (error == null) { 120 error = method; 121 } else { 122 if (currentClazz == clazzPojo || 123 !isMethodOverride(error, method)) { 124 // Duplicate annotation 125 throw new DeploymentException(sm.getString( 126 "pojoMethodMapping.duplicateAnnotation", 127 OnError.class, currentClazz)); 128 } 129 } 130 } else if (method.getAnnotation(OnMessage.class) != null) { 131 checkPublic(method); 132 MessageHandlerInfo messageHandler = new MessageHandlerInfo(method, decoders); 133 boolean found = false; 134 for (MessageHandlerInfo otherMessageHandler : onMessage) { 135 if (messageHandler.targetsSameWebSocketMessageType(otherMessageHandler)) { 136 found = true; 137 if (currentClazz == clazzPojo || 138 !isMethodOverride(messageHandler.m, otherMessageHandler.m)) { 139 // Duplicate annotation 140 throw new DeploymentException(sm.getString( 141 "pojoMethodMapping.duplicateAnnotation", 142 OnMessage.class, currentClazz)); 143 } 144 } 145 } 146 if (!found) { 147 onMessage.add(messageHandler); 148 } 149 } else { 150 // Method not annotated 151 } 152 } 153 currentClazz = currentClazz.getSuperclass(); 154 } 155 // If the methods are not on clazzPojo and they are overridden 156 // by a non annotated method in clazzPojo, they should be ignored 157 if (open != null && open.getDeclaringClass() != clazzPojo) { 158 if (isOverridenWithoutAnnotation(clazzPojoMethods, open, OnOpen.class)) { 159 open = null; 160 } 161 } 162 if (close != null && close.getDeclaringClass() != clazzPojo) { 163 if (isOverridenWithoutAnnotation(clazzPojoMethods, close, OnClose.class)) { 164 close = null; 165 } 166 } 167 if (error != null && error.getDeclaringClass() != clazzPojo) { 168 if (isOverridenWithoutAnnotation(clazzPojoMethods, error, OnError.class)) { 169 error = null; 170 } 171 } 172 List<MessageHandlerInfo> overriddenOnMessage = new ArrayList<>(); 173 for (MessageHandlerInfo messageHandler : onMessage) { 174 if (messageHandler.m.getDeclaringClass() != clazzPojo 175 && isOverridenWithoutAnnotation(clazzPojoMethods, messageHandler.m, OnMessage.class)) { 176 overriddenOnMessage.add(messageHandler); 177 } 178 } 179 for (MessageHandlerInfo messageHandler : overriddenOnMessage) { 180 onMessage.remove(messageHandler); 181 } 182 this.onOpen = open; 183 this.onClose = close; 184 this.onError = error; 185 onOpenParams = getPathParams(onOpen, MethodType.ON_OPEN); 186 onCloseParams = getPathParams(onClose, MethodType.ON_CLOSE); 187 onErrorParams = getPathParams(onError, MethodType.ON_ERROR); 188 } 189 190 checkPublic(Method m)191 private void checkPublic(Method m) throws DeploymentException { 192 if (!Modifier.isPublic(m.getModifiers())) { 193 throw new DeploymentException(sm.getString( 194 "pojoMethodMapping.methodNotPublic", m.getName())); 195 } 196 } 197 198 isMethodOverride(Method method1, Method method2)199 private boolean isMethodOverride(Method method1, Method method2) { 200 return method1.getName().equals(method2.getName()) 201 && method1.getReturnType().equals(method2.getReturnType()) 202 && Arrays.equals(method1.getParameterTypes(), method2.getParameterTypes()); 203 } 204 205 isOverridenWithoutAnnotation(Method[] methods, Method superclazzMethod, Class<? extends Annotation> annotation)206 private boolean isOverridenWithoutAnnotation(Method[] methods, 207 Method superclazzMethod, Class<? extends Annotation> annotation) { 208 for (Method method : methods) { 209 if (isMethodOverride(method, superclazzMethod) 210 && (method.getAnnotation(annotation) == null)) { 211 return true; 212 } 213 } 214 return false; 215 } 216 217 getWsPath()218 public String getWsPath() { 219 return wsPath; 220 } 221 222 getOnOpen()223 public Method getOnOpen() { 224 return onOpen; 225 } 226 227 getOnOpenArgs(Map<String,String> pathParameters, Session session, EndpointConfig config)228 public Object[] getOnOpenArgs(Map<String,String> pathParameters, 229 Session session, EndpointConfig config) throws DecodeException { 230 return buildArgs(onOpenParams, pathParameters, session, config, null, 231 null); 232 } 233 234 getOnClose()235 public Method getOnClose() { 236 return onClose; 237 } 238 239 getOnCloseArgs(Map<String,String> pathParameters, Session session, CloseReason closeReason)240 public Object[] getOnCloseArgs(Map<String,String> pathParameters, 241 Session session, CloseReason closeReason) throws DecodeException { 242 return buildArgs(onCloseParams, pathParameters, session, null, null, 243 closeReason); 244 } 245 246 getOnError()247 public Method getOnError() { 248 return onError; 249 } 250 251 getOnErrorArgs(Map<String,String> pathParameters, Session session, Throwable throwable)252 public Object[] getOnErrorArgs(Map<String,String> pathParameters, 253 Session session, Throwable throwable) throws DecodeException { 254 return buildArgs(onErrorParams, pathParameters, session, null, 255 throwable, null); 256 } 257 258 hasMessageHandlers()259 public boolean hasMessageHandlers() { 260 return !onMessage.isEmpty(); 261 } 262 263 getMessageHandlers(Object pojo, Map<String,String> pathParameters, Session session, EndpointConfig config)264 public Set<MessageHandler> getMessageHandlers(Object pojo, 265 Map<String,String> pathParameters, Session session, 266 EndpointConfig config) { 267 Set<MessageHandler> result = new HashSet<>(); 268 for (MessageHandlerInfo messageMethod : onMessage) { 269 result.addAll(messageMethod.getMessageHandlers(pojo, pathParameters, 270 session, config)); 271 } 272 return result; 273 } 274 275 getPathParams(Method m, MethodType methodType)276 private static PojoPathParam[] getPathParams(Method m, 277 MethodType methodType) throws DeploymentException { 278 if (m == null) { 279 return new PojoPathParam[0]; 280 } 281 boolean foundThrowable = false; 282 Class<?>[] types = m.getParameterTypes(); 283 Annotation[][] paramsAnnotations = m.getParameterAnnotations(); 284 PojoPathParam[] result = new PojoPathParam[types.length]; 285 for (int i = 0; i < types.length; i++) { 286 Class<?> type = types[i]; 287 if (type.equals(Session.class)) { 288 result[i] = new PojoPathParam(type, null); 289 } else if (methodType == MethodType.ON_OPEN && 290 type.equals(EndpointConfig.class)) { 291 result[i] = new PojoPathParam(type, null); 292 } else if (methodType == MethodType.ON_ERROR 293 && type.equals(Throwable.class)) { 294 foundThrowable = true; 295 result[i] = new PojoPathParam(type, null); 296 } else if (methodType == MethodType.ON_CLOSE && 297 type.equals(CloseReason.class)) { 298 result[i] = new PojoPathParam(type, null); 299 } else { 300 Annotation[] paramAnnotations = paramsAnnotations[i]; 301 for (Annotation paramAnnotation : paramAnnotations) { 302 if (paramAnnotation.annotationType().equals( 303 PathParam.class)) { 304 // Check that the type is valid. "0" coerces to every 305 // valid type 306 try { 307 Util.coerceToType(type, "0"); 308 } catch (IllegalArgumentException iae) { 309 throw new DeploymentException(sm.getString( 310 "pojoMethodMapping.invalidPathParamType"), 311 iae); 312 } 313 result[i] = new PojoPathParam(type, 314 ((PathParam) paramAnnotation).value()); 315 break; 316 } 317 } 318 // Parameters without annotations are not permitted 319 if (result[i] == null) { 320 throw new DeploymentException(sm.getString( 321 "pojoMethodMapping.paramWithoutAnnotation", 322 type, m.getName(), m.getClass().getName())); 323 } 324 } 325 } 326 if (methodType == MethodType.ON_ERROR && !foundThrowable) { 327 throw new DeploymentException(sm.getString( 328 "pojoMethodMapping.onErrorNoThrowable", 329 m.getName(), m.getDeclaringClass().getName())); 330 } 331 return result; 332 } 333 334 buildArgs(PojoPathParam[] pathParams, Map<String,String> pathParameters, Session session, EndpointConfig config, Throwable throwable, CloseReason closeReason)335 private static Object[] buildArgs(PojoPathParam[] pathParams, 336 Map<String,String> pathParameters, Session session, 337 EndpointConfig config, Throwable throwable, CloseReason closeReason) 338 throws DecodeException { 339 Object[] result = new Object[pathParams.length]; 340 for (int i = 0; i < pathParams.length; i++) { 341 Class<?> type = pathParams[i].getType(); 342 if (type.equals(Session.class)) { 343 result[i] = session; 344 } else if (type.equals(EndpointConfig.class)) { 345 result[i] = config; 346 } else if (type.equals(Throwable.class)) { 347 result[i] = throwable; 348 } else if (type.equals(CloseReason.class)) { 349 result[i] = closeReason; 350 } else { 351 String name = pathParams[i].getName(); 352 String value = pathParameters.get(name); 353 try { 354 result[i] = Util.coerceToType(type, value); 355 } catch (Exception e) { 356 throw new DecodeException(value, sm.getString( 357 "pojoMethodMapping.decodePathParamFail", 358 value, type), e); 359 } 360 } 361 } 362 return result; 363 } 364 365 366 private static class MessageHandlerInfo { 367 368 private final Method m; 369 private int indexString = -1; 370 private int indexByteArray = -1; 371 private int indexByteBuffer = -1; 372 private int indexPong = -1; 373 private int indexBoolean = -1; 374 private int indexSession = -1; 375 private int indexInputStream = -1; 376 private int indexReader = -1; 377 private int indexPrimitive = -1; 378 private Class<?> primitiveType = null; 379 private Map<Integer,PojoPathParam> indexPathParams = new HashMap<>(); 380 private int indexPayload = -1; 381 private DecoderMatch decoderMatch = null; 382 private long maxMessageSize = -1; 383 MessageHandlerInfo(Method m, List<DecoderEntry> decoderEntries)384 public MessageHandlerInfo(Method m, List<DecoderEntry> decoderEntries) { 385 this.m = m; 386 387 Class<?>[] types = m.getParameterTypes(); 388 Annotation[][] paramsAnnotations = m.getParameterAnnotations(); 389 390 for (int i = 0; i < types.length; i++) { 391 boolean paramFound = false; 392 Annotation[] paramAnnotations = paramsAnnotations[i]; 393 for (Annotation paramAnnotation : paramAnnotations) { 394 if (paramAnnotation.annotationType().equals( 395 PathParam.class)) { 396 indexPathParams.put( 397 Integer.valueOf(i), new PojoPathParam(types[i], 398 ((PathParam) paramAnnotation).value())); 399 paramFound = true; 400 break; 401 } 402 } 403 if (paramFound) { 404 continue; 405 } 406 if (String.class.isAssignableFrom(types[i])) { 407 if (indexString == -1) { 408 indexString = i; 409 } else { 410 throw new IllegalArgumentException(sm.getString( 411 "pojoMethodMapping.duplicateMessageParam", 412 m.getName(), m.getDeclaringClass().getName())); 413 } 414 } else if (Reader.class.isAssignableFrom(types[i])) { 415 if (indexReader == -1) { 416 indexReader = i; 417 } else { 418 throw new IllegalArgumentException(sm.getString( 419 "pojoMethodMapping.duplicateMessageParam", 420 m.getName(), m.getDeclaringClass().getName())); 421 } 422 } else if (boolean.class == types[i]) { 423 if (indexBoolean == -1) { 424 indexBoolean = i; 425 } else { 426 throw new IllegalArgumentException(sm.getString( 427 "pojoMethodMapping.duplicateLastParam", 428 m.getName(), m.getDeclaringClass().getName())); 429 } 430 } else if (ByteBuffer.class.isAssignableFrom(types[i])) { 431 if (indexByteBuffer == -1) { 432 indexByteBuffer = i; 433 } else { 434 throw new IllegalArgumentException(sm.getString( 435 "pojoMethodMapping.duplicateMessageParam", 436 m.getName(), m.getDeclaringClass().getName())); 437 } 438 } else if (byte[].class == types[i]) { 439 if (indexByteArray == -1) { 440 indexByteArray = i; 441 } else { 442 throw new IllegalArgumentException(sm.getString( 443 "pojoMethodMapping.duplicateMessageParam", 444 m.getName(), m.getDeclaringClass().getName())); 445 } 446 } else if (InputStream.class.isAssignableFrom(types[i])) { 447 if (indexInputStream == -1) { 448 indexInputStream = i; 449 } else { 450 throw new IllegalArgumentException(sm.getString( 451 "pojoMethodMapping.duplicateMessageParam", 452 m.getName(), m.getDeclaringClass().getName())); 453 } 454 } else if (Util.isPrimitive(types[i])) { 455 if (indexPrimitive == -1) { 456 indexPrimitive = i; 457 primitiveType = types[i]; 458 } else { 459 throw new IllegalArgumentException(sm.getString( 460 "pojoMethodMapping.duplicateMessageParam", 461 m.getName(), m.getDeclaringClass().getName())); 462 } 463 } else if (Session.class.isAssignableFrom(types[i])) { 464 if (indexSession == -1) { 465 indexSession = i; 466 } else { 467 throw new IllegalArgumentException(sm.getString( 468 "pojoMethodMapping.duplicateSessionParam", 469 m.getName(), m.getDeclaringClass().getName())); 470 } 471 } else if (PongMessage.class.isAssignableFrom(types[i])) { 472 if (indexPong == -1) { 473 indexPong = i; 474 } else { 475 throw new IllegalArgumentException(sm.getString( 476 "pojoMethodMapping.duplicatePongMessageParam", 477 m.getName(), m.getDeclaringClass().getName())); 478 } 479 } else { 480 if (decoderMatch != null && decoderMatch.hasMatches()) { 481 throw new IllegalArgumentException(sm.getString( 482 "pojoMethodMapping.duplicateMessageParam", 483 m.getName(), m.getDeclaringClass().getName())); 484 } 485 decoderMatch = new DecoderMatch(types[i], decoderEntries); 486 487 if (decoderMatch.hasMatches()) { 488 indexPayload = i; 489 } 490 } 491 } 492 493 // Additional checks required 494 if (indexString != -1) { 495 if (indexPayload != -1) { 496 throw new IllegalArgumentException(sm.getString( 497 "pojoMethodMapping.duplicateMessageParam", 498 m.getName(), m.getDeclaringClass().getName())); 499 } else { 500 indexPayload = indexString; 501 } 502 } 503 if (indexReader != -1) { 504 if (indexPayload != -1) { 505 throw new IllegalArgumentException(sm.getString( 506 "pojoMethodMapping.duplicateMessageParam", 507 m.getName(), m.getDeclaringClass().getName())); 508 } else { 509 indexPayload = indexReader; 510 } 511 } 512 if (indexByteArray != -1) { 513 if (indexPayload != -1) { 514 throw new IllegalArgumentException(sm.getString( 515 "pojoMethodMapping.duplicateMessageParam", 516 m.getName(), m.getDeclaringClass().getName())); 517 } else { 518 indexPayload = indexByteArray; 519 } 520 } 521 if (indexByteBuffer != -1) { 522 if (indexPayload != -1) { 523 throw new IllegalArgumentException(sm.getString( 524 "pojoMethodMapping.duplicateMessageParam", 525 m.getName(), m.getDeclaringClass().getName())); 526 } else { 527 indexPayload = indexByteBuffer; 528 } 529 } 530 if (indexInputStream != -1) { 531 if (indexPayload != -1) { 532 throw new IllegalArgumentException(sm.getString( 533 "pojoMethodMapping.duplicateMessageParam", 534 m.getName(), m.getDeclaringClass().getName())); 535 } else { 536 indexPayload = indexInputStream; 537 } 538 } 539 if (indexPrimitive != -1) { 540 if (indexPayload != -1) { 541 throw new IllegalArgumentException(sm.getString( 542 "pojoMethodMapping.duplicateMessageParam", 543 m.getName(), m.getDeclaringClass().getName())); 544 } else { 545 indexPayload = indexPrimitive; 546 } 547 } 548 if (indexPong != -1) { 549 if (indexPayload != -1) { 550 throw new IllegalArgumentException(sm.getString( 551 "pojoMethodMapping.pongWithPayload", 552 m.getName(), m.getDeclaringClass().getName())); 553 } else { 554 indexPayload = indexPong; 555 } 556 } 557 if (indexPayload == -1 && indexPrimitive == -1 && 558 indexBoolean != -1) { 559 // The boolean we found is a payload, not a last flag 560 indexPayload = indexBoolean; 561 indexPrimitive = indexBoolean; 562 primitiveType = Boolean.TYPE; 563 indexBoolean = -1; 564 } 565 if (indexPayload == -1) { 566 throw new IllegalArgumentException(sm.getString( 567 "pojoMethodMapping.noPayload", 568 m.getName(), m.getDeclaringClass().getName())); 569 } 570 if (indexPong != -1 && indexBoolean != -1) { 571 throw new IllegalArgumentException(sm.getString( 572 "pojoMethodMapping.partialPong", 573 m.getName(), m.getDeclaringClass().getName())); 574 } 575 if(indexReader != -1 && indexBoolean != -1) { 576 throw new IllegalArgumentException(sm.getString( 577 "pojoMethodMapping.partialReader", 578 m.getName(), m.getDeclaringClass().getName())); 579 } 580 if(indexInputStream != -1 && indexBoolean != -1) { 581 throw new IllegalArgumentException(sm.getString( 582 "pojoMethodMapping.partialInputStream", 583 m.getName(), m.getDeclaringClass().getName())); 584 } 585 if (decoderMatch != null && decoderMatch.hasMatches() && 586 indexBoolean != -1) { 587 throw new IllegalArgumentException(sm.getString( 588 "pojoMethodMapping.partialObject", 589 m.getName(), m.getDeclaringClass().getName())); 590 } 591 592 maxMessageSize = m.getAnnotation(OnMessage.class).maxMessageSize(); 593 } 594 595 targetsSameWebSocketMessageType(MessageHandlerInfo otherHandler)596 public boolean targetsSameWebSocketMessageType(MessageHandlerInfo otherHandler) { 597 if (otherHandler == null) { 598 return false; 599 } 600 if (indexByteArray >= 0 && otherHandler.indexByteArray >= 0) { 601 return true; 602 } 603 if (indexByteBuffer >= 0 && otherHandler.indexByteBuffer >= 0) { 604 return true; 605 } 606 if (indexInputStream >= 0 && otherHandler.indexInputStream >= 0) { 607 return true; 608 } 609 if (indexPong >= 0 && otherHandler.indexPong >= 0) { 610 return true; 611 } 612 if (indexPrimitive >= 0 && otherHandler.indexPrimitive >= 0 613 && primitiveType == otherHandler.primitiveType) { 614 return true; 615 } 616 if (indexReader >= 0 && otherHandler.indexReader >= 0) { 617 return true; 618 } 619 if (indexString >= 0 && otherHandler.indexString >= 0) { 620 return true; 621 } 622 if (decoderMatch != null && otherHandler.decoderMatch != null 623 && decoderMatch.getTarget().equals(otherHandler.decoderMatch.getTarget())) { 624 return true; 625 } 626 return false; 627 } 628 629 getMessageHandlers(Object pojo, Map<String,String> pathParameters, Session session, EndpointConfig config)630 public Set<MessageHandler> getMessageHandlers(Object pojo, 631 Map<String,String> pathParameters, Session session, 632 EndpointConfig config) { 633 Object[] params = new Object[m.getParameterTypes().length]; 634 635 for (Map.Entry<Integer,PojoPathParam> entry : 636 indexPathParams.entrySet()) { 637 PojoPathParam pathParam = entry.getValue(); 638 String valueString = pathParameters.get(pathParam.getName()); 639 Object value = null; 640 try { 641 value = Util.coerceToType(pathParam.getType(), valueString); 642 } catch (Exception e) { 643 DecodeException de = new DecodeException(valueString, 644 sm.getString( 645 "pojoMethodMapping.decodePathParamFail", 646 valueString, pathParam.getType()), e); 647 params = new Object[] { de }; 648 break; 649 } 650 params[entry.getKey().intValue()] = value; 651 } 652 653 Set<MessageHandler> results = new HashSet<>(2); 654 if (indexBoolean == -1) { 655 // Basic 656 if (indexString != -1 || indexPrimitive != -1) { 657 MessageHandler mh = new PojoMessageHandlerWholeText(pojo, m, 658 session, config, null, params, indexPayload, false, 659 indexSession, maxMessageSize); 660 results.add(mh); 661 } else if (indexReader != -1) { 662 MessageHandler mh = new PojoMessageHandlerWholeText(pojo, m, 663 session, config, null, params, indexReader, true, 664 indexSession, maxMessageSize); 665 results.add(mh); 666 } else if (indexByteArray != -1) { 667 MessageHandler mh = new PojoMessageHandlerWholeBinary(pojo, 668 m, session, config, null, params, indexByteArray, 669 true, indexSession, false, maxMessageSize); 670 results.add(mh); 671 } else if (indexByteBuffer != -1) { 672 MessageHandler mh = new PojoMessageHandlerWholeBinary(pojo, 673 m, session, config, null, params, indexByteBuffer, 674 false, indexSession, false, maxMessageSize); 675 results.add(mh); 676 } else if (indexInputStream != -1) { 677 MessageHandler mh = new PojoMessageHandlerWholeBinary(pojo, 678 m, session, config, null, params, indexInputStream, 679 true, indexSession, true, maxMessageSize); 680 results.add(mh); 681 } else if (decoderMatch != null && decoderMatch.hasMatches()) { 682 if (decoderMatch.getBinaryDecoders().size() > 0) { 683 MessageHandler mh = new PojoMessageHandlerWholeBinary( 684 pojo, m, session, config, 685 decoderMatch.getBinaryDecoders(), params, 686 indexPayload, true, indexSession, true, 687 maxMessageSize); 688 results.add(mh); 689 } 690 if (decoderMatch.getTextDecoders().size() > 0) { 691 MessageHandler mh = new PojoMessageHandlerWholeText( 692 pojo, m, session, config, 693 decoderMatch.getTextDecoders(), params, 694 indexPayload, true, indexSession, maxMessageSize); 695 results.add(mh); 696 } 697 } else { 698 MessageHandler mh = new PojoMessageHandlerWholePong(pojo, m, 699 session, params, indexPong, false, indexSession); 700 results.add(mh); 701 } 702 } else { 703 // ASync 704 if (indexString != -1) { 705 MessageHandler mh = new PojoMessageHandlerPartialText(pojo, 706 m, session, params, indexString, false, 707 indexBoolean, indexSession, maxMessageSize); 708 results.add(mh); 709 } else if (indexByteArray != -1) { 710 MessageHandler mh = new PojoMessageHandlerPartialBinary( 711 pojo, m, session, params, indexByteArray, true, 712 indexBoolean, indexSession, maxMessageSize); 713 results.add(mh); 714 } else { 715 MessageHandler mh = new PojoMessageHandlerPartialBinary( 716 pojo, m, session, params, indexByteBuffer, false, 717 indexBoolean, indexSession, maxMessageSize); 718 results.add(mh); 719 } 720 } 721 return results; 722 } 723 } 724 725 726 private enum MethodType { 727 ON_OPEN, 728 ON_CLOSE, 729 ON_ERROR 730 } 731 } 732