View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2014 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.IOException;
22  import java.io.InputStream;
23  import java.io.Reader;
24  import java.nio.ByteBuffer;
25  
26  import org.eclipse.jetty.websocket.api.WebSocketPolicy;
27  import org.eclipse.jetty.websocket.api.annotations.WebSocket;
28  import org.eclipse.jetty.websocket.api.extensions.Frame;
29  import org.eclipse.jetty.websocket.common.CloseInfo;
30  import org.eclipse.jetty.websocket.common.message.MessageAppender;
31  import org.eclipse.jetty.websocket.common.message.MessageInputStream;
32  import org.eclipse.jetty.websocket.common.message.MessageReader;
33  import org.eclipse.jetty.websocket.common.message.SimpleBinaryMessage;
34  import org.eclipse.jetty.websocket.common.message.SimpleTextMessage;
35  
36  /**
37   * Handler for Annotated User WebSocket objects.
38   */
39  public class JettyAnnotatedEventDriver extends AbstractEventDriver
40  {
41      private final JettyAnnotatedMetadata events;
42      private boolean hasCloseBeenCalled = false;
43  
44      public JettyAnnotatedEventDriver(WebSocketPolicy policy, Object websocket, JettyAnnotatedMetadata events)
45      {
46          super(policy,websocket);
47          this.events = events;
48  
49          WebSocket anno = websocket.getClass().getAnnotation(WebSocket.class);
50          // Setup the policy
51          if (anno.maxTextMessageSize() > 0)
52          {
53              this.policy.setMaxTextMessageSize(anno.maxTextMessageSize());
54          }
55          if (anno.maxBinaryMessageSize() > 0)
56          {
57              this.policy.setMaxBinaryMessageSize(anno.maxBinaryMessageSize());
58          }
59          if (anno.inputBufferSize() > 0)
60          {
61              this.policy.setInputBufferSize(anno.inputBufferSize());
62          }
63          if (anno.maxIdleTime() > 0)
64          {
65              this.policy.setIdleTimeout(anno.maxIdleTime());
66          }
67      }
68  
69      @Override
70      public void onBinaryFrame(ByteBuffer buffer, boolean fin) throws IOException
71      {
72          if (events.onBinary == null)
73          {
74              // not interested in binary events
75              return;
76          }
77  
78          if (activeMessage == null)
79          {
80              if (events.onBinary.isStreaming())
81              {
82                  activeMessage = new MessageInputStream();
83                  final MessageAppender msg = activeMessage;
84                  dispatch(new Runnable()
85                  {
86                      @Override
87                      public void run()
88                      {
89                          events.onBinary.call(websocket,session,msg);
90                      }
91                  });
92              }
93              else
94              {
95                  activeMessage = new SimpleBinaryMessage(this);
96              }
97          }
98  
99          appendMessage(buffer,fin);
100     }
101 
102     @Override
103     public void onBinaryMessage(byte[] data)
104     {
105         if (events.onBinary != null)
106         {
107             events.onBinary.call(websocket,session,data,0,data.length);
108         }
109     }
110 
111     @Override
112     public void onClose(CloseInfo close)
113     {
114         if (hasCloseBeenCalled)
115         {
116             // avoid duplicate close events (possible when using harsh Session.disconnect())
117             return;
118         }
119         hasCloseBeenCalled = true;
120         if (events.onClose != null)
121         {
122             events.onClose.call(websocket,session,close.getStatusCode(),close.getReason());
123         }
124     }
125 
126     @Override
127     public void onConnect()
128     {
129         if (events.onConnect != null)
130         {
131             events.onConnect.call(websocket,session);
132         }
133     }
134 
135     @Override
136     public void onError(Throwable cause)
137     {
138         if (events.onError != null)
139         {
140             events.onError.call(websocket,session,cause);
141         }
142     }
143 
144     @Override
145     public void onFrame(Frame frame)
146     {
147         if (events.onFrame != null)
148         {
149             events.onFrame.call(websocket,session,frame);
150         }
151     }
152 
153     @Override
154     public void onInputStream(InputStream stream)
155     {
156         if (events.onBinary != null)
157         {
158             events.onBinary.call(websocket,session,stream);
159         }
160     }
161 
162     @Override
163     public void onReader(Reader reader)
164     {
165         if (events.onText != null)
166         {
167             events.onText.call(websocket,session,reader);
168         }
169     }
170 
171     @Override
172     public void onTextFrame(ByteBuffer buffer, boolean fin) throws IOException
173     {
174         if (events.onText == null)
175         {
176             // not interested in text events
177             return;
178         }
179 
180         if (activeMessage == null)
181         {
182             if (events.onText.isStreaming())
183             {
184                 activeMessage = new MessageReader(new MessageInputStream());
185                 final MessageAppender msg = activeMessage;
186                 dispatch(new Runnable()
187                 {
188                     @Override
189                     public void run()
190                     {
191                         events.onText.call(websocket,session,msg);
192                     }
193                 });
194             }
195             else
196             {
197                 activeMessage = new SimpleTextMessage(this);
198             }
199         }
200 
201         appendMessage(buffer,fin);
202     }
203 
204     @Override
205     public void onTextMessage(String message)
206     {
207         if (events.onText != null)
208         {
209             events.onText.call(websocket,session,message);
210         }
211     }
212 
213     @Override
214     public String toString()
215     {
216         return String.format("%s[%s]", this.getClass().getSimpleName(), websocket);
217     }
218 }