View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
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 }