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.IOException;
22  import java.io.InputStream;
23  import java.io.Reader;
24  import java.nio.ByteBuffer;
25  
26  import org.eclipse.jetty.util.log.Log;
27  import org.eclipse.jetty.util.log.Logger;
28  import org.eclipse.jetty.websocket.api.WebSocketConnectionListener;
29  import org.eclipse.jetty.websocket.api.WebSocketFrameListener;
30  import org.eclipse.jetty.websocket.api.WebSocketListener;
31  import org.eclipse.jetty.websocket.api.WebSocketPartialListener;
32  import org.eclipse.jetty.websocket.api.WebSocketPingPongListener;
33  import org.eclipse.jetty.websocket.api.WebSocketPolicy;
34  import org.eclipse.jetty.websocket.api.extensions.Frame;
35  import org.eclipse.jetty.websocket.api.extensions.Frame.Type;
36  import org.eclipse.jetty.websocket.common.CloseInfo;
37  import org.eclipse.jetty.websocket.common.frames.ReadOnlyDelegatedFrame;
38  import org.eclipse.jetty.websocket.common.message.SimpleBinaryMessage;
39  import org.eclipse.jetty.websocket.common.message.SimpleTextMessage;
40  import org.eclipse.jetty.websocket.common.util.Utf8PartialBuilder;
41  
42  /**
43   * Handler for {@link WebSocketListener} based User WebSocket implementations.
44   */
45  public class JettyListenerEventDriver extends AbstractEventDriver
46  {
47      private static final Logger LOG = Log.getLogger(JettyListenerEventDriver.class);
48      private final WebSocketConnectionListener listener;
49      private Utf8PartialBuilder utf8Partial;
50      private boolean hasCloseBeenCalled = false;
51  
52      public JettyListenerEventDriver(WebSocketPolicy policy, WebSocketConnectionListener listener)
53      {
54          super(policy,listener);
55          this.listener = listener;
56      }
57  
58      @Override
59      public void onBinaryFrame(ByteBuffer buffer, boolean fin) throws IOException
60      {
61          if (listener instanceof WebSocketListener)
62          {
63              if (activeMessage == null)
64              {
65                  activeMessage = new SimpleBinaryMessage(this);
66              }
67  
68              appendMessage(buffer,fin);
69          }
70  
71          if (listener instanceof WebSocketPartialListener)
72          {
73              ((WebSocketPartialListener)listener).onWebSocketPartialBinary(buffer.slice().asReadOnlyBuffer(),fin);
74          }
75      }
76  
77      @Override
78      public void onBinaryMessage(byte[] data)
79      {
80          if (listener instanceof WebSocketListener)
81          {
82              ((WebSocketListener)listener).onWebSocketBinary(data,0,data.length);
83          }
84      }
85  
86      @Override
87      public void onClose(CloseInfo close)
88      {
89          if (hasCloseBeenCalled)
90          {
91              // avoid duplicate close events (possible when using harsh Session.disconnect())
92              return;
93          }
94          hasCloseBeenCalled = true;
95  
96          int statusCode = close.getStatusCode();
97          String reason = close.getReason();
98          listener.onWebSocketClose(statusCode,reason);
99      }
100 
101     @Override
102     public void onConnect()
103     {
104         if (LOG.isDebugEnabled())
105             LOG.debug("onConnect()");
106         listener.onWebSocketConnect(session);
107     }
108 
109     @Override
110     public void onError(Throwable cause)
111     {
112         listener.onWebSocketError(cause);
113     }
114 
115     @Override
116     public void onFrame(Frame frame)
117     {
118         if (listener instanceof WebSocketFrameListener)
119         {
120             ((WebSocketFrameListener)listener).onWebSocketFrame(new ReadOnlyDelegatedFrame(frame));
121         }
122 
123         if (listener instanceof WebSocketPingPongListener)
124         {
125             if (frame.getType() == Type.PING)
126             {
127                 ((WebSocketPingPongListener)listener).onWebSocketPing(frame.getPayload().asReadOnlyBuffer());
128             }
129             else if (frame.getType() == Type.PONG)
130             {
131                 ((WebSocketPingPongListener)listener).onWebSocketPong(frame.getPayload().asReadOnlyBuffer());
132             }
133         }
134     }
135 
136     @Override
137     public void onInputStream(InputStream stream)
138     {
139         /* not supported in Listener mode (yet) */
140     }
141 
142     @Override
143     public void onReader(Reader reader)
144     {
145         /* not supported in Listener mode (yet) */
146     }
147 
148     @Override
149     public void onTextFrame(ByteBuffer buffer, boolean fin) throws IOException
150     {
151         if (listener instanceof WebSocketListener)
152         {
153             if (activeMessage == null)
154             {
155                 activeMessage = new SimpleTextMessage(this);
156             }
157 
158             appendMessage(buffer,fin);
159         }
160 
161         if (listener instanceof WebSocketPartialListener)
162         {
163             if (utf8Partial == null)
164             {
165                 utf8Partial = new Utf8PartialBuilder();
166             }
167             
168             String partial = utf8Partial.toPartialString(buffer);
169             
170             ((WebSocketPartialListener)listener).onWebSocketPartialText(partial,fin);
171             
172             if (fin)
173             {
174                 partial = null;
175             }
176         }
177     }
178 
179     /**
180      * Whole Message event.
181      * 
182      * @param message the whole message
183      */
184     @Override
185     public void onTextMessage(String message)
186     {
187         if (listener instanceof WebSocketListener)
188         {
189             ((WebSocketListener)listener).onWebSocketText(message);
190         }
191     }
192 
193     @Override
194     public String toString()
195     {
196         return String.format("%s[%s]",JettyListenerEventDriver.class.getSimpleName(),listener.getClass().getName());
197     }
198 }