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.IOException; 20 import java.lang.reflect.Method; 21 import java.nio.ByteBuffer; 22 23 import javax.websocket.EncodeException; 24 import javax.websocket.MessageHandler; 25 import javax.websocket.RemoteEndpoint; 26 import javax.websocket.Session; 27 28 import org.apache.tomcat.util.ExceptionUtils; 29 import nginx.unit.websocket.WrappedMessageHandler; 30 31 /** 32 * Common implementation code for the POJO message handlers. 33 * 34 * @param <T> The type of message to handle 35 */ 36 public abstract class PojoMessageHandlerBase<T> 37 implements WrappedMessageHandler { 38 39 protected final Object pojo; 40 protected final Method method; 41 protected final Session session; 42 protected final Object[] params; 43 protected final int indexPayload; 44 protected final boolean convert; 45 protected final int indexSession; 46 protected final long maxMessageSize; 47 PojoMessageHandlerBase(Object pojo, Method method, Session session, Object[] params, int indexPayload, boolean convert, int indexSession, long maxMessageSize)48 public PojoMessageHandlerBase(Object pojo, Method method, 49 Session session, Object[] params, int indexPayload, boolean convert, 50 int indexSession, long maxMessageSize) { 51 this.pojo = pojo; 52 this.method = method; 53 // TODO: The method should already be accessible here but the following 54 // code seems to be necessary in some as yet not fully understood cases. 55 try { 56 this.method.setAccessible(true); 57 } catch (Exception e) { 58 // It is better to make sure the method is accessible, but 59 // ignore exceptions and hope for the best 60 } 61 this.session = session; 62 this.params = params; 63 this.indexPayload = indexPayload; 64 this.convert = convert; 65 this.indexSession = indexSession; 66 this.maxMessageSize = maxMessageSize; 67 } 68 69 processResult(Object result)70 protected final void processResult(Object result) { 71 if (result == null) { 72 return; 73 } 74 75 RemoteEndpoint.Basic remoteEndpoint = session.getBasicRemote(); 76 try { 77 if (result instanceof String) { 78 remoteEndpoint.sendText((String) result); 79 } else if (result instanceof ByteBuffer) { 80 remoteEndpoint.sendBinary((ByteBuffer) result); 81 } else if (result instanceof byte[]) { 82 remoteEndpoint.sendBinary(ByteBuffer.wrap((byte[]) result)); 83 } else { 84 remoteEndpoint.sendObject(result); 85 } 86 } catch (IOException | EncodeException ioe) { 87 throw new IllegalStateException(ioe); 88 } 89 } 90 91 92 /** 93 * Expose the POJO if it is a message handler so the Session is able to 94 * match requests to remove handlers if the original handler has been 95 * wrapped. 96 */ 97 @Override getWrappedHandler()98 public final MessageHandler getWrappedHandler() { 99 if (pojo instanceof MessageHandler) { 100 return (MessageHandler) pojo; 101 } else { 102 return null; 103 } 104 } 105 106 107 @Override getMaxMessageSize()108 public final long getMaxMessageSize() { 109 return maxMessageSize; 110 } 111 112 handlePojoMethodException(Throwable t)113 protected final void handlePojoMethodException(Throwable t) { 114 t = ExceptionUtils.unwrapInvocationTargetException(t); 115 ExceptionUtils.handleThrowable(t); 116 if (t instanceof RuntimeException) { 117 throw (RuntimeException) t; 118 } else { 119 throw new RuntimeException(t.getMessage(), t); 120 } 121 } 122 } 123