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.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         if (LOG.isDebugEnabled())
108             LOG.debug("onMethodAnnotation({}, {}, {}, {})",metadata,pojo,method,annotation);
109 
110         if (isAnnotation(annotation,OnWebSocketConnect.class))
111         {
112             assertValidSignature(method,OnWebSocketConnect.class,validConnectParams);
113             assertUnset(metadata.onConnect,OnWebSocketConnect.class,method);
114             metadata.onConnect = new CallableMethod(pojo,method);
115             return;
116         }
117 
118         if (isAnnotation(annotation,OnWebSocketMessage.class))
119         {
120             if (isSignatureMatch(method,validTextParams))
121             {
122                 // Text mode
123                 assertUnset(metadata.onText,OnWebSocketMessage.class,method);
124                 metadata.onText = new OptionalSessionCallableMethod(pojo,method);
125                 return;
126             }
127 
128             if (isSignatureMatch(method,validBinaryParams))
129             {
130                 // Binary Mode
131                 // TODO
132                 assertUnset(metadata.onBinary,OnWebSocketMessage.class,method);
133                 metadata.onBinary = new OptionalSessionCallableMethod(pojo,method);
134                 return;
135             }
136 
137             throw InvalidSignatureException.build(method,OnWebSocketMessage.class,validTextParams,validBinaryParams);
138         }
139 
140         if (isAnnotation(annotation,OnWebSocketClose.class))
141         {
142             assertValidSignature(method,OnWebSocketClose.class,validCloseParams);
143             assertUnset(metadata.onClose,OnWebSocketClose.class,method);
144             metadata.onClose = new OptionalSessionCallableMethod(pojo,method);
145             return;
146         }
147 
148         if (isAnnotation(annotation,OnWebSocketError.class))
149         {
150             assertValidSignature(method,OnWebSocketError.class,validErrorParams);
151             assertUnset(metadata.onError,OnWebSocketError.class,method);
152             metadata.onError = new OptionalSessionCallableMethod(pojo,method);
153             return;
154         }
155 
156         if (isAnnotation(annotation,OnWebSocketFrame.class))
157         {
158             assertValidSignature(method,OnWebSocketFrame.class,validFrameParams);
159             assertUnset(metadata.onFrame,OnWebSocketFrame.class,method);
160             metadata.onFrame = new OptionalSessionCallableMethod(pojo,method);
161             return;
162         }
163     }
164 
165     public JettyAnnotatedMetadata scan(Class<?> pojo)
166     {
167         JettyAnnotatedMetadata metadata = new JettyAnnotatedMetadata();
168         scanMethodAnnotations(metadata,pojo);
169         return metadata;
170     }
171 }