1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.websocket.jsr356.annotations;
20
21 import java.lang.reflect.Method;
22
23 import javax.websocket.Decoder;
24 import javax.websocket.Encoder;
25
26 import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException;
27 import org.eclipse.jetty.websocket.common.util.ReflectUtils;
28 import org.eclipse.jetty.websocket.jsr356.EncoderFactory;
29 import org.eclipse.jetty.websocket.jsr356.InitException;
30 import org.eclipse.jetty.websocket.jsr356.JsrSession;
31 import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role;
32
33 public class OnMessageCallable extends JsrCallable
34 {
35 protected final Class<?> returnType;
36 protected Encoder returnEncoder;
37 protected Class<? extends Decoder> decoderClass;
38 protected Decoder decoder;
39 protected int idxPartialMessageFlag = -1;
40 protected int idxMessageObject = -1;
41 protected boolean messageRoleAssigned = false;
42
43 public OnMessageCallable(Class<?> pojo, Method method)
44 {
45 super(pojo,method);
46 this.returnType = method.getReturnType();
47 }
48
49 public OnMessageCallable(OnMessageCallable copy)
50 {
51 super(copy);
52 this.returnType = copy.returnType;
53 this.decoderClass = copy.decoderClass;
54 this.decoder = copy.decoder;
55 this.idxPartialMessageFlag = copy.idxPartialMessageFlag;
56 this.idxMessageObject = copy.idxMessageObject;
57 }
58
59 protected void assertDecoderRequired()
60 {
61 if (getDecoder() == null)
62 {
63 StringBuilder err = new StringBuilder();
64 err.append("Unable to find a valid ");
65 err.append(Decoder.class.getName());
66 err.append(" for parameter #");
67 Param param = params[idxMessageObject];
68 err.append(param.index);
69 err.append(" [").append(param.type).append("] in method: ");
70 err.append(ReflectUtils.toString(pojo,method));
71 throw new InvalidSignatureException(err.toString());
72 }
73 }
74
75 private int findMessageObjectIndex()
76 {
77 int index = -1;
78
79 for (Param.Role role : Param.Role.getMessageRoles())
80 {
81 index = findIndexForRole(role);
82 if (index >= 0)
83 {
84 return index;
85 }
86 }
87
88 return -1;
89 }
90
91 public Decoder getDecoder()
92 {
93 return decoder;
94 }
95
96 public Class<? extends Decoder> getDecoderClass()
97 {
98 return decoderClass;
99 }
100
101 public Param getMessageObjectParam()
102 {
103 if (idxMessageObject < 0)
104 {
105 idxMessageObject = findMessageObjectIndex();
106
107 if (idxMessageObject < 0)
108 {
109 StringBuilder err = new StringBuilder();
110 err.append("A message type must be specified [TEXT, BINARY, DECODER, or PONG] : ");
111 err.append(ReflectUtils.toString(pojo,method));
112 throw new InvalidSignatureException(err.toString());
113 }
114 }
115
116 return super.params[idxMessageObject];
117 }
118
119 public Encoder getReturnEncoder()
120 {
121 return returnEncoder;
122 }
123
124 public Class<?> getReturnType()
125 {
126 return returnType;
127 }
128
129 @Override
130 public void init(JsrSession session)
131 {
132 super.init(session);
133 idxPartialMessageFlag = findIndexForRole(Role.MESSAGE_PARTIAL_FLAG);
134
135 EncoderFactory.Wrapper encoderWrapper = session.getEncoderFactory().getWrapperFor(returnType);
136 if (encoderWrapper != null)
137 {
138 this.returnEncoder = encoderWrapper.getEncoder();
139 }
140
141 if (decoderClass != null)
142 {
143 try
144 {
145 this.decoder = decoderClass.newInstance();
146 }
147 catch (InstantiationException | IllegalAccessException e)
148 {
149 throw new InitException("Unable to create decoder: " + decoderClass.getName(),e);
150 }
151 }
152 }
153
154 public boolean isMessageRoleAssigned()
155 {
156 return messageRoleAssigned;
157 }
158
159 public boolean isPartialMessageSupported()
160 {
161 return (idxPartialMessageFlag >= 0);
162 }
163
164 @Override
165 public void setDecoderClass(Class<? extends Decoder> decoderClass)
166 {
167 this.decoderClass = decoderClass;
168 messageRoleAssigned = true;
169 }
170
171 public void setPartialMessageFlag(Param param)
172 {
173 idxPartialMessageFlag = param.index;
174 }
175 }