/* Copyright (c) 2011 Danish Maritime Authority. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.maritimecloud.internal.mms.client; import net.maritimecloud.internal.mms.messages.Welcome; import net.maritimecloud.internal.mms.messages.spi.MmsMessage; import net.maritimecloud.message.Message; import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection; import javax.websocket.CloseReason; import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.RemoteEndpoint.Basic; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import static java.util.Objects.requireNonNull; /** * * @author Kasper Nielsen */ @ServerEndpoint(value = "/") public class TestClientEndpoint { public final CountDownLatch closed = new CountDownLatch(1); public BlockingQueue<MmsMessage> m = new ArrayBlockingQueue<>(10000); public CloseReason reason; Session session; public void disconnect() { WebSocketSession ss = (WebSocketSession) session; ss.getConnection().disconnect(); AbstractWebSocketConnection cc = (AbstractWebSocketConnection) ss.getConnection(); cc.getEndPoint().getTransport();// socket session = null; } public void closeNormally() throws IOException { session.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, "normal closure")); } public void close(int code, String reason) throws IOException { session.close(new CloseReason(() -> code, reason)); } public void close() throws IOException { session.close(new CloseReason(CloseReason.CloseCodes.UNEXPECTED_CONDITION, "TestClientEndpoint.close()")); } public void closeIt() { try { close(); } catch (IOException e) { throw new RuntimeException(e); } } public boolean isOpen() { Session session = this.session; return session != null && session.isOpen(); } @OnMessage public final void messageReceived(String msg, Session userSession) throws InterruptedException { if (session != userSession) { return;// ignore } MmsMessage tm = MmsMessage.parseTextMessage(msg); m.put(tm); } @OnMessage public final void messageReceived(byte[] msg, Session userSession) throws InterruptedException, IOException { if (session != userSession) { return;// ignore } MmsMessage tm = MmsMessage.parseBinaryMessage(msg); m.put(tm); } @OnClose public final void onClose(CloseReason reason) { this.reason = reason; closed.countDown(); } @OnOpen public final void onWebsocketOpen(Session session) { this.session = session; m.clear(); send(new Welcome().addProtocolVersion(1).setServerId("123").putProperties("implementation", "enavServer/1.0")); } protected <T extends Message> T poll(Class<T> c) { return c.cast(m.poll()); } public void send(Message m) { send(m, 0, 0); } public void send(Message m, long msgId, long latestReceivedId) { MmsMessage mms = new MmsMessage(); mms.setM(m); if (mms.isConnectionMessage()) { mms.setMessageId(msgId); mms.setLatestReceivedId(latestReceivedId); } Basic r = session.getBasicRemote(); try { r.sendText(mms.toText()); } catch (IOException e) { throw new AssertionError(e); } } public <T extends BlockingQueue<MmsMessage>> T setQueue(T q) { this.m = requireNonNull(q); return q; } public MmsMessage t() { try { return requireNonNull(m.poll(5, TimeUnit.SECONDS)); } catch (InterruptedException e) { throw new RuntimeException(e); } } public <T extends Message> T take(Class<T> c) { try { return requireNonNull(c.cast(m.poll(5, TimeUnit.SECONDS).getM())); } catch (InterruptedException e) { throw new RuntimeException(e); } } }