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.io.StringReader; 21 import java.lang.reflect.Method; 22 import java.util.ArrayList; 23 import java.util.List; 24 25 import javax.websocket.DecodeException; 26 import javax.websocket.Decoder; 27 import javax.websocket.Decoder.Text; 28 import javax.websocket.Decoder.TextStream; 29 import javax.websocket.EndpointConfig; 30 import javax.websocket.Session; 31 32 import org.apache.tomcat.util.res.StringManager; 33 import nginx.unit.websocket.Util; 34 35 36 /** 37 * Text specific concrete implementation for handling whole messages. 38 */ 39 public class PojoMessageHandlerWholeText 40 extends PojoMessageHandlerWholeBase<String> { 41 42 private static final StringManager sm = 43 StringManager.getManager(PojoMessageHandlerWholeText.class); 44 45 private final List<Decoder> decoders = new ArrayList<>(); 46 private final Class<?> primitiveType; 47 PojoMessageHandlerWholeText(Object pojo, Method method, Session session, EndpointConfig config, List<Class<? extends Decoder>> decoderClazzes, Object[] params, int indexPayload, boolean convert, int indexSession, long maxMessageSize)48 public PojoMessageHandlerWholeText(Object pojo, Method method, 49 Session session, EndpointConfig config, 50 List<Class<? extends Decoder>> decoderClazzes, Object[] params, 51 int indexPayload, boolean convert, int indexSession, 52 long maxMessageSize) { 53 super(pojo, method, session, params, indexPayload, convert, 54 indexSession, maxMessageSize); 55 56 // Update max text size handled by session 57 if (maxMessageSize > -1 && maxMessageSize > session.getMaxTextMessageBufferSize()) { 58 if (maxMessageSize > Integer.MAX_VALUE) { 59 throw new IllegalArgumentException(sm.getString( 60 "pojoMessageHandlerWhole.maxBufferSize")); 61 } 62 session.setMaxTextMessageBufferSize((int) maxMessageSize); 63 } 64 65 // Check for primitives 66 Class<?> type = method.getParameterTypes()[indexPayload]; 67 if (Util.isPrimitive(type)) { 68 primitiveType = type; 69 return; 70 } else { 71 primitiveType = null; 72 } 73 74 try { 75 if (decoderClazzes != null) { 76 for (Class<? extends Decoder> decoderClazz : decoderClazzes) { 77 if (Text.class.isAssignableFrom(decoderClazz)) { 78 Text<?> decoder = (Text<?>) decoderClazz.getConstructor().newInstance(); 79 decoder.init(config); 80 decoders.add(decoder); 81 } else if (TextStream.class.isAssignableFrom( 82 decoderClazz)) { 83 TextStream<?> decoder = 84 (TextStream<?>) decoderClazz.getConstructor().newInstance(); 85 decoder.init(config); 86 decoders.add(decoder); 87 } else { 88 // Binary decoder - ignore it 89 } 90 } 91 } 92 } catch (ReflectiveOperationException e) { 93 throw new IllegalArgumentException(e); 94 } 95 } 96 97 98 @Override decode(String message)99 protected Object decode(String message) throws DecodeException { 100 // Handle primitives 101 if (primitiveType != null) { 102 return Util.coerceToType(primitiveType, message); 103 } 104 // Handle full decoders 105 for (Decoder decoder : decoders) { 106 if (decoder instanceof Text) { 107 if (((Text<?>) decoder).willDecode(message)) { 108 return ((Text<?>) decoder).decode(message); 109 } 110 } else { 111 StringReader r = new StringReader(message); 112 try { 113 return ((TextStream<?>) decoder).decode(r); 114 } catch (IOException ioe) { 115 throw new DecodeException(message, sm.getString( 116 "pojoMessageHandlerWhole.decodeIoFail"), ioe); 117 } 118 } 119 } 120 return null; 121 } 122 123 124 @Override convert(String message)125 protected Object convert(String message) { 126 return new StringReader(message); 127 } 128 129 130 @Override onClose()131 protected void onClose() { 132 for (Decoder decoder : decoders) { 133 decoder.destroy(); 134 } 135 } 136 } 137