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;
20  
21  import java.io.IOException;
22  import java.nio.ByteBuffer;
23  import java.util.concurrent.Future;
24  
25  import javax.websocket.EncodeException;
26  import javax.websocket.Encoder;
27  import javax.websocket.RemoteEndpoint;
28  import javax.websocket.SendHandler;
29  
30  import org.eclipse.jetty.util.BufferUtil;
31  import org.eclipse.jetty.util.log.Log;
32  import org.eclipse.jetty.util.log.Logger;
33  import org.eclipse.jetty.websocket.common.WebSocketRemoteEndpoint;
34  import org.eclipse.jetty.websocket.common.io.FutureWriteCallback;
35  import org.eclipse.jetty.websocket.common.message.MessageOutputStream;
36  import org.eclipse.jetty.websocket.common.message.MessageWriter;
37  import org.eclipse.jetty.websocket.jsr356.encoders.EncodeFailedFuture;
38  
39  public abstract class AbstractJsrRemote implements RemoteEndpoint
40  {
41      private static final Logger LOG = Log.getLogger(AbstractJsrRemote.class);
42  
43      protected final JsrSession session;
44      protected final WebSocketRemoteEndpoint jettyRemote;
45      protected final EncoderFactory encoders;
46  
47      protected AbstractJsrRemote(JsrSession session)
48      {
49          this.session = session;
50          if (!(session.getRemote() instanceof WebSocketRemoteEndpoint))
51          {
52              StringBuilder err = new StringBuilder();
53              err.append("Unexpected implementation [");
54              err.append(session.getRemote().getClass().getName());
55              err.append("].  Expected an instanceof [");
56              err.append(WebSocketRemoteEndpoint.class.getName());
57              err.append("]");
58              throw new IllegalStateException(err.toString());
59          }
60          this.jettyRemote = (WebSocketRemoteEndpoint)session.getRemote();
61          this.encoders = session.getEncoderFactory();
62      }
63  
64      protected void assertMessageNotNull(Object data)
65      {
66          if (data == null)
67          {
68              throw new IllegalArgumentException("message cannot be null");
69          }
70      }
71  
72      protected void assertSendHandlerNotNull(SendHandler handler)
73      {
74          if (handler == null)
75          {
76              throw new IllegalArgumentException("SendHandler cannot be null");
77          }
78      }
79  
80      @Override
81      public void flushBatch() throws IOException
82      {
83          // TODO Auto-generated method stub
84      }
85  
86      @Override
87      public boolean getBatchingAllowed()
88      {
89          // TODO Auto-generated method stub
90          return false;
91      }
92  
93      @SuppressWarnings(
94      { "rawtypes", "unchecked" })
95      public Future<Void> sendObjectViaFuture(Object data)
96      {
97          assertMessageNotNull(data);
98          if (LOG.isDebugEnabled())
99          {
100             LOG.debug("sendObject({})",data);
101         }
102 
103         Encoder encoder = encoders.getEncoderFor(data.getClass());
104         if (encoder == null)
105         {
106             throw new IllegalArgumentException("No encoder for type: " + data.getClass());
107         }
108 
109         if (encoder instanceof Encoder.Text)
110         {
111             Encoder.Text etxt = (Encoder.Text)encoder;
112             try
113             {
114                 String msg = etxt.encode(data);
115                 return jettyRemote.sendStringByFuture(msg);
116             }
117             catch (EncodeException e)
118             {
119                 return new EncodeFailedFuture(data,etxt,Encoder.Text.class,e);
120             }
121         }
122         else if (encoder instanceof Encoder.TextStream)
123         {
124             Encoder.TextStream etxt = (Encoder.TextStream)encoder;
125             FutureWriteCallback callback = new FutureWriteCallback();
126             try (MessageWriter writer = new MessageWriter(session))
127             {
128                 writer.setCallback(callback);
129                 etxt.encode(data,writer);
130                 return callback;
131             }
132             catch (EncodeException | IOException e)
133             {
134                 return new EncodeFailedFuture(data,etxt,Encoder.Text.class,e);
135             }
136         }
137         else if (encoder instanceof Encoder.Binary)
138         {
139             Encoder.Binary ebin = (Encoder.Binary)encoder;
140             try
141             {
142                 ByteBuffer buf = ebin.encode(data);
143                 return jettyRemote.sendBytesByFuture(buf);
144             }
145             catch (EncodeException e)
146             {
147                 return new EncodeFailedFuture(data,ebin,Encoder.Binary.class,e);
148             }
149         }
150         else if (encoder instanceof Encoder.BinaryStream)
151         {
152             Encoder.BinaryStream ebin = (Encoder.BinaryStream)encoder;
153             FutureWriteCallback callback = new FutureWriteCallback();
154             try (MessageOutputStream out = new MessageOutputStream(session))
155             {
156                 out.setCallback(callback);
157                 ebin.encode(data,out);
158                 return callback;
159             }
160             catch (EncodeException | IOException e)
161             {
162                 return new EncodeFailedFuture(data,ebin,Encoder.Binary.class,e);
163             }
164         }
165 
166         throw new IllegalArgumentException("Unknown encoder type: " + encoder);
167     }
168 
169     @Override
170     public void sendPing(ByteBuffer data) throws IOException, IllegalArgumentException
171     {
172         if (LOG.isDebugEnabled())
173         {
174             LOG.debug("sendPing({})",BufferUtil.toDetailString(data));
175         }
176         jettyRemote.sendPing(data);
177     }
178 
179     @Override
180     public void sendPong(ByteBuffer data) throws IOException, IllegalArgumentException
181     {
182         if (LOG.isDebugEnabled())
183         {
184             LOG.debug("sendPong({})",BufferUtil.toDetailString(data));
185         }
186         jettyRemote.sendPong(data);
187     }
188 
189     @Override
190     public void setBatchingAllowed(boolean allowed) throws IOException
191     {
192         // TODO Auto-generated method stub
193     }
194 }