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.annotation.Annotation;
22  import java.lang.reflect.Method;
23  import java.util.Map;
24  
25  import javax.websocket.DecodeException;
26  import javax.websocket.Decoder;
27  
28  import org.eclipse.jetty.websocket.api.InvalidWebSocketException;
29  import org.eclipse.jetty.websocket.common.events.annotated.CallableMethod;
30  import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException;
31  import org.eclipse.jetty.websocket.common.util.ReflectUtils;
32  import org.eclipse.jetty.websocket.jsr356.JsrSession;
33  import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role;
34  
35  public abstract class JsrCallable extends CallableMethod
36  {
37      protected final Param[] params;
38      protected final Object[] args;
39      protected int idxSession = -1;
40      protected int idxConfig = -1;
41  
42      public JsrCallable(Class<?> pojo, Method method)
43      {
44          super(pojo,method);
45  
46          Class<?> ptypes[] = method.getParameterTypes();
47          Annotation pannos[][] = method.getParameterAnnotations();
48          int len = ptypes.length;
49          params = new Param[len];
50          for (int i = 0; i < len; i++)
51          {
52              params[i] = new Param(i,ptypes[i],pannos[i]);
53          }
54  
55          args = new Object[len];
56      }
57  
58      /**
59       * Copy Constructor
60       * @param copy the JsrCallable to copy from 
61       */
62      public JsrCallable(JsrCallable copy)
63      {
64          this(copy.getPojo(),copy.getMethod());
65          this.idxSession = copy.idxSession;
66          this.idxConfig = copy.idxConfig;
67          System.arraycopy(copy.params,0,this.params,0,params.length);
68          System.arraycopy(copy.args,0,this.args,0,args.length);
69      }
70  
71      protected void assertRoleRequired(int index, String description)
72      {
73          if (index < 0)
74          {
75              StringBuilder err = new StringBuilder();
76              err.append("Unable to find parameter with role [");
77              err.append(description).append("] in method: ");
78              err.append(ReflectUtils.toString(pojo,method));
79              throw new InvalidSignatureException(err.toString());
80          }
81      }
82  
83      /**
84       * Search the list of parameters for first one matching the role specified.
85       * 
86       * @param role
87       *            the role to look for
88       * @return the index for the role specified (or -1 if not found)
89       */
90      protected int findIndexForRole(Role role)
91      {
92          Param param = findParamForRole(role);
93          if (param != null)
94          {
95              return param.index;
96          }
97          return -1;
98      }
99  
100     /**
101      * Find first param for specified role.
102      * 
103      * @param role
104      *            the role specified
105      * @return the param (or null if not found)
106      */
107     protected Param findParamForRole(Role role)
108     {
109         for (Param param : params)
110         {
111             if (param.role == role)
112             {
113                 return param;
114             }
115         }
116         return null;
117     }
118 
119     public Param[] getParams()
120     {
121         return params;
122     }
123 
124     public void init(JsrSession session)
125     {
126         // Default for the session.
127         // Session is an optional parameter (always)
128         idxSession = findIndexForRole(Param.Role.SESSION);
129         if (idxSession >= 0)
130         {
131             args[idxSession] = session;
132         }
133 
134         // Optional EndpointConfig
135         idxConfig = findIndexForRole(Param.Role.ENDPOINT_CONFIG);
136         if (idxConfig >= 0)
137         {
138             args[idxConfig] = session.getEndpointConfig();
139         }
140 
141         // Default for the path parameters
142         // PathParam's are optional parameters (always)
143         Map<String, String> pathParams = session.getPathParameters();
144         if ((pathParams != null) && (pathParams.size() > 0))
145         {
146             for (Param param : params)
147             {
148                 if (param.role == Role.PATH_PARAM)
149                 {
150                     int idx = param.index;
151                     String rawvalue = pathParams.get(param.getPathParamName());
152 
153                     Decoder decoder = session.getDecoderFactory().getDecoderFor(param.type);
154                     if (decoder instanceof Decoder.Text<?>)
155                     {
156                         Decoder.Text<?> textDecoder = (Decoder.Text<?>)decoder;
157                         try
158                         {
159                             args[idx] = textDecoder.decode(rawvalue);
160                         }
161                         catch (DecodeException e)
162                         {
163                             session.notifyError(e);
164                         }
165                     }
166                     else
167                     {
168                         throw new InvalidWebSocketException("PathParam decoders must use Decoder.Text");
169                     }
170                 }
171             }
172         }
173     }
174 
175     public abstract void setDecoderClass(Class<? extends Decoder> decoderClass);
176 }