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.endpoints;
20  
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.io.Reader;
24  import java.nio.ByteBuffer;
25  import java.util.Map;
26  
27  import javax.websocket.CloseReason;
28  import javax.websocket.Endpoint;
29  import javax.websocket.MessageHandler;
30  import javax.websocket.MessageHandler.Whole;
31  
32  import org.eclipse.jetty.util.log.Log;
33  import org.eclipse.jetty.util.log.Logger;
34  import org.eclipse.jetty.websocket.api.WebSocketPolicy;
35  import org.eclipse.jetty.websocket.api.extensions.Frame;
36  import org.eclipse.jetty.websocket.common.events.EventDriver;
37  import org.eclipse.jetty.websocket.common.message.MessageInputStream;
38  import org.eclipse.jetty.websocket.common.message.MessageReader;
39  import org.eclipse.jetty.websocket.jsr356.JsrSession;
40  import org.eclipse.jetty.websocket.jsr356.MessageHandlerWrapper;
41  import org.eclipse.jetty.websocket.jsr356.MessageType;
42  import org.eclipse.jetty.websocket.jsr356.messages.BinaryPartialMessage;
43  import org.eclipse.jetty.websocket.jsr356.messages.BinaryWholeMessage;
44  import org.eclipse.jetty.websocket.jsr356.messages.TextPartialMessage;
45  import org.eclipse.jetty.websocket.jsr356.messages.TextWholeMessage;
46  
47  /**
48   * EventDriver for websocket that extend from {@link javax.websocket.Endpoint}
49   */
50  public class JsrEndpointEventDriver extends AbstractJsrEventDriver implements EventDriver
51  {
52      private static final Logger LOG = Log.getLogger(JsrEndpointEventDriver.class);
53  
54      private final Endpoint endpoint;
55      private Map<String, String> pathParameters;
56  
57      public JsrEndpointEventDriver(WebSocketPolicy policy, EndpointInstance endpointInstance)
58      {
59          super(policy,endpointInstance);
60          this.endpoint = (Endpoint)endpointInstance.getEndpoint();
61      }
62  
63      @Override
64      public void init(JsrSession jsrsession)
65      {
66          jsrsession.setPathParameters(pathParameters);
67      }
68  
69      @Override
70      public void onBinaryFrame(ByteBuffer buffer, boolean fin) throws IOException
71      {
72          if (activeMessage == null)
73          {
74              final MessageHandlerWrapper wrapper = jsrsession.getMessageHandlerWrapper(MessageType.BINARY);
75              if (wrapper == null)
76              {
77                  LOG.debug("No BINARY MessageHandler declared");
78                  return;
79              }
80              if (wrapper.wantsPartialMessages())
81              {
82                  activeMessage = new BinaryPartialMessage(wrapper);
83              }
84              else if (wrapper.wantsStreams())
85              {
86                  final MessageInputStream stream = new MessageInputStream(session.getConnection());
87                  activeMessage = stream;
88                  dispatch(new Runnable()
89                  {
90                      @SuppressWarnings("unchecked")
91                      @Override
92                      public void run()
93                      {
94                          MessageHandler.Whole<InputStream> handler = (Whole<InputStream>)wrapper.getHandler();
95                          handler.onMessage(stream);
96                      }
97                  });
98              }
99              else
100             {
101                 activeMessage = new BinaryWholeMessage(this,wrapper);
102             }
103         }
104 
105         activeMessage.appendMessage(buffer,fin);
106 
107         if (fin)
108         {
109             activeMessage.messageComplete();
110             activeMessage = null;
111         }
112     }
113 
114     @Override
115     public void onBinaryMessage(byte[] data)
116     {
117         /* Ignored, handled by BinaryWholeMessage */
118     }
119 
120     @Override
121     protected void onClose(CloseReason closereason)
122     {
123         endpoint.onClose(this.jsrsession,closereason);
124     }
125 
126     @Override
127     public void onConnect()
128     {
129         LOG.debug("onConnect({}, {})",jsrsession,config);
130         try
131         {
132             endpoint.onOpen(jsrsession,config);
133         }
134         catch (Throwable t)
135         {
136             LOG.warn("Uncaught exception",t);
137         }
138     }
139 
140     @Override
141     public void onError(Throwable cause)
142     {
143         endpoint.onError(jsrsession,cause);
144     }
145 
146     @Override
147     public void onFrame(Frame frame)
148     {
149         /* Ignored, not supported by JSR-356 */
150     }
151 
152     @Override
153     public void onInputStream(InputStream stream)
154     {
155         /* Ignored, handled by BinaryStreamMessage */
156     }
157 
158     @Override
159     public void onReader(Reader reader)
160     {
161         /* Ignored, handled by TextStreamMessage */
162     }
163 
164     @Override
165     public void onTextFrame(ByteBuffer buffer, boolean fin) throws IOException
166     {
167         if (activeMessage == null)
168         {
169             final MessageHandlerWrapper wrapper = jsrsession.getMessageHandlerWrapper(MessageType.TEXT);
170             if (wrapper == null)
171             {
172                 LOG.debug("No TEXT MessageHandler declared");
173                 return;
174             }
175             if (wrapper.wantsPartialMessages())
176             {
177                 activeMessage = new TextPartialMessage(wrapper);
178             }
179             else if (wrapper.wantsStreams())
180             {
181                 final MessageReader stream = new MessageReader(new MessageInputStream(session.getConnection()));
182                 activeMessage = stream;
183 
184                 dispatch(new Runnable()
185                 {
186                     @SuppressWarnings("unchecked")
187                     @Override
188                     public void run()
189                     {
190                         MessageHandler.Whole<Reader> handler = (Whole<Reader>)wrapper.getHandler();
191                         handler.onMessage(stream);
192                     }
193                 });
194             }
195             else
196             {
197                 activeMessage = new TextWholeMessage(this,wrapper);
198             }
199         }
200 
201         activeMessage.appendMessage(buffer,fin);
202 
203         if (fin)
204         {
205             activeMessage.messageComplete();
206             activeMessage = null;
207         }
208     }
209 
210     @Override
211     public void onTextMessage(String message)
212     {
213         /* Ignored, handled by TextWholeMessage */
214     }
215 
216     @Override
217     public void setPathParameters(Map<String, String> pathParameters)
218     {
219         this.pathParameters = pathParameters;
220     }
221 
222     @Override
223     public String toString()
224     {
225         return String.format("%s[%s]",JsrEndpointEventDriver.class.getSimpleName(),endpoint.getClass().getName());
226     }
227 }