View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 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       */
61      public JsrCallable(JsrCallable copy)
62      {
63          this(copy.getPojo(),copy.getMethod());
64          this.idxSession = copy.idxSession;
65          this.idxConfig = copy.idxConfig;
66          System.arraycopy(copy.params,0,this.params,0,params.length);
67          System.arraycopy(copy.args,0,this.args,0,args.length);
68      }
69  
70      protected void assertRoleRequired(int index, String description)
71      {
72          if (index < 0)
73          {
74              StringBuilder err = new StringBuilder();
75              err.append("Unable to find parameter with role [");
76              err.append(description).append("] in method: ");
77              err.append(ReflectUtils.toString(pojo,method));
78              throw new InvalidSignatureException(err.toString());
79          }
80      }
81  
82      /**
83       * Search the list of parameters for first one matching the role specified.
84       * 
85       * @param role
86       *            the role to look for
87       * @return the index for the role specified (or -1 if not found)
88       */
89      protected int findIndexForRole(Role role)
90      {
91          Param param = findParamForRole(role);
92          if (param != null)
93          {
94              return param.index;
95          }
96          return -1;
97      }
98  
99      /**
100      * Find first param for specified role.
101      * 
102      * @param role
103      *            the role specified
104      * @return the param (or null if not found)
105      */
106     protected Param findParamForRole(Role role)
107     {
108         for (Param param : params)
109         {
110             if (param.role == role)
111             {
112                 return param;
113             }
114         }
115         return null;
116     }
117 
118     public Param[] getParams()
119     {
120         return params;
121     }
122 
123     public void init(JsrSession session)
124     {
125         // Default for the session.
126         // Session is an optional parameter (always)
127         idxSession = findIndexForRole(Param.Role.SESSION);
128         if (idxSession >= 0)
129         {
130             args[idxSession] = session;
131         }
132 
133         // Optional EndpointConfig
134         idxConfig = findIndexForRole(Param.Role.ENDPOINT_CONFIG);
135         if (idxConfig >= 0)
136         {
137             args[idxConfig] = session.getEndpointConfig();
138         }
139 
140         // Default for the path parameters
141         // PathParam's are optional parameters (always)
142         Map<String, String> pathParams = session.getPathParameters();
143         if ((pathParams != null) && (pathParams.size() > 0))
144         {
145             for (Param param : params)
146             {
147                 if (param.role == Role.PATH_PARAM)
148                 {
149                     int idx = param.index;
150                     String rawvalue = pathParams.get(param.getPathParamName());
151 
152                     Decoder decoder = session.getDecoderFactory().getDecoderFor(param.type);
153                     if (decoder instanceof Decoder.Text<?>)
154                     {
155                         Decoder.Text<?> textDecoder = (Decoder.Text<?>)decoder;
156                         try
157                         {
158                             args[idx] = textDecoder.decode(rawvalue);
159                         }
160                         catch (DecodeException e)
161                         {
162                             session.notifyError(e);
163                         }
164                     }
165                     else
166                     {
167                         throw new InvalidWebSocketException("PathParam decoders must use Decoder.Text");
168                     }
169                 }
170             }
171         }
172     }
173 
174     public abstract void setDecoderClass(Class<? extends Decoder> decoderClass);
175 }