1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
84 }
85
86 @Override
87 public boolean getBatchingAllowed()
88 {
89
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
193 }
194 }