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.common.events;
20  
21  import java.io.InputStream;
22  import java.io.Reader;
23  import java.lang.annotation.Annotation;
24  import java.lang.reflect.Method;
25  
26  import org.eclipse.jetty.util.log.Log;
27  import org.eclipse.jetty.util.log.Logger;
28  import org.eclipse.jetty.websocket.api.Session;
29  import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
30  import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
31  import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
32  import org.eclipse.jetty.websocket.api.annotations.OnWebSocketFrame;
33  import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
34  import org.eclipse.jetty.websocket.api.extensions.Frame;
35  import org.eclipse.jetty.websocket.common.events.annotated.AbstractMethodAnnotationScanner;
36  import org.eclipse.jetty.websocket.common.events.annotated.CallableMethod;
37  import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException;
38  import org.eclipse.jetty.websocket.common.events.annotated.OptionalSessionCallableMethod;
39  
40  public class JettyAnnotatedScanner extends AbstractMethodAnnotationScanner<JettyAnnotatedMetadata>
41  {
42      private static final Logger LOG = Log.getLogger(JettyAnnotatedScanner.class);
43  
44      /**
45       * Parameter list for &#064;OnWebSocketMessage (Binary mode)
46       */
47      private static final ParamList validBinaryParams;
48  
49      /**
50       * Parameter list for &#064;OnWebSocketConnect
51       */
52      private static final ParamList validConnectParams;
53  
54      /**
55       * Parameter list for &#064;OnWebSocketClose
56       */
57      private static final ParamList validCloseParams;
58  
59      /**
60       * Parameter list for &#064;OnWebSocketError
61       */
62      private static final ParamList validErrorParams;
63  
64      /**
65       * Parameter list for &#064;OnWebSocketFrame
66       */
67      private static final ParamList validFrameParams;
68  
69      /**
70       * Parameter list for &#064;OnWebSocketMessage (Text mode)
71       */
72      private static final ParamList validTextParams;
73  
74      static
75      {
76          validConnectParams = new ParamList();
77          validConnectParams.addParams(Session.class);
78  
79          validCloseParams = new ParamList();
80          validCloseParams.addParams(int.class,String.class);
81          validCloseParams.addParams(Session.class,int.class,String.class);
82  
83          validErrorParams = new ParamList();
84          validErrorParams.addParams(Throwable.class);
85          validErrorParams.addParams(Session.class,Throwable.class);
86  
87          validTextParams = new ParamList();
88          validTextParams.addParams(String.class);
89          validTextParams.addParams(Session.class,String.class);
90          validTextParams.addParams(Reader.class);
91          validTextParams.addParams(Session.class,Reader.class);
92  
93          validBinaryParams = new ParamList();
94          validBinaryParams.addParams(byte[].class,int.class,int.class);
95          validBinaryParams.addParams(Session.class,byte[].class,int.class,int.class);
96          validBinaryParams.addParams(InputStream.class);
97          validBinaryParams.addParams(Session.class,InputStream.class);
98  
99          validFrameParams = new ParamList();
100         validFrameParams.addParams(Frame.class);
101         validFrameParams.addParams(Session.class,Frame.class);
102     }
103 
104     @Override
105     public void onMethodAnnotation(JettyAnnotatedMetadata metadata, Class<?> pojo, Method method, Annotation annotation)
106     {
107         LOG.debug("onMethodAnnotation({}, {}, {}, {})",metadata,pojo,method,annotation);
108 
109         if (isAnnotation(annotation,OnWebSocketConnect.class))
110         {
111             assertValidSignature(method,OnWebSocketConnect.class,validConnectParams);
112             assertUnset(metadata.onConnect,OnWebSocketConnect.class,method);
113             metadata.onConnect = new CallableMethod(pojo,method);
114             return;
115         }
116 
117         if (isAnnotation(annotation,OnWebSocketMessage.class))
118         {
119             if (isSignatureMatch(method,validTextParams))
120             {
121                 // Text mode
122                 assertUnset(metadata.onText,OnWebSocketMessage.class,method);
123                 metadata.onText = new OptionalSessionCallableMethod(pojo,method);
124                 return;
125             }
126 
127             if (isSignatureMatch(method,validBinaryParams))
128             {
129                 // Binary Mode
130                 // TODO
131                 assertUnset(metadata.onBinary,OnWebSocketMessage.class,method);
132                 metadata.onBinary = new OptionalSessionCallableMethod(pojo,method);
133                 return;
134             }
135 
136             throw InvalidSignatureException.build(method,OnWebSocketMessage.class,validTextParams,validBinaryParams);
137         }
138 
139         if (isAnnotation(annotation,OnWebSocketClose.class))
140         {
141             assertValidSignature(method,OnWebSocketClose.class,validCloseParams);
142             assertUnset(metadata.onClose,OnWebSocketClose.class,method);
143             metadata.onClose = new OptionalSessionCallableMethod(pojo,method);
144             return;
145         }
146 
147         if (isAnnotation(annotation,OnWebSocketError.class))
148         {
149             assertValidSignature(method,OnWebSocketError.class,validErrorParams);
150             assertUnset(metadata.onError,OnWebSocketError.class,method);
151             metadata.onError = new OptionalSessionCallableMethod(pojo,method);
152             return;
153         }
154 
155         if (isAnnotation(annotation,OnWebSocketFrame.class))
156         {
157             assertValidSignature(method,OnWebSocketFrame.class,validFrameParams);
158             assertUnset(metadata.onFrame,OnWebSocketFrame.class,method);
159             metadata.onFrame = new OptionalSessionCallableMethod(pojo,method);
160             return;
161         }
162     }
163 
164     public JettyAnnotatedMetadata scan(Class<?> pojo)
165     {
166         JettyAnnotatedMetadata metadata = new JettyAnnotatedMetadata();
167         scanMethodAnnotations(metadata,pojo);
168         return metadata;
169     }
170 }