001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.protocol.ws.javax; 018 019import java.io.IOException; 020import java.nio.ByteBuffer; 021import java.util.concurrent.Future; 022 023import javax.websocket.CloseReason; 024import javax.websocket.RemoteEndpoint; 025import javax.websocket.Session; 026 027import org.apache.wicket.protocol.ws.api.AbstractWebSocketConnection; 028import org.apache.wicket.protocol.ws.api.AbstractWebSocketProcessor; 029import org.apache.wicket.protocol.ws.api.IWebSocketConnection; 030import org.apache.wicket.util.lang.Args; 031import org.slf4j.Logger; 032import org.slf4j.LoggerFactory; 033 034/** 035 * A wrapper around JSR 356's native Session. 036 * 037 * @since 7.0.0 038 */ 039public class JavaxWebSocketConnection extends AbstractWebSocketConnection 040{ 041 private static final Logger LOG = LoggerFactory.getLogger(JavaxWebSocketConnection.class); 042 043 private final Session session; 044 045 /** 046 * Constructor. 047 * 048 * @param session 049 * the WebSocket session 050 */ 051 public JavaxWebSocketConnection(Session session, AbstractWebSocketProcessor webSocketProcessor) 052 { 053 super(webSocketProcessor); 054 this.session = Args.notNull(session, "session"); 055 } 056 057 @Override 058 public boolean isOpen() 059 { 060 return session.isOpen(); 061 } 062 063 @Override 064 public synchronized void close(int code, String reason) 065 { 066 if (isOpen()) 067 { 068 try 069 { 070 session.close(new CloseReason(new CloseCode(code), reason)); 071 } catch (IOException iox) 072 { 073 LOG.error("An error occurred while closing WebSocket session", iox); 074 } 075 } 076 } 077 078 @Override 079 public synchronized IWebSocketConnection sendMessage(String message) throws IOException 080 { 081 checkClosed(); 082 083 session.getBasicRemote().sendText(message); 084 return this; 085 } 086 087 @Override 088 public Future<Void> sendMessageAsync(String message) 089 { 090 checkClosed(); 091 092 return session.getAsyncRemote().sendText(message); 093 } 094 095 @Override 096 public Future<Void> sendMessageAsync(String message, long timeOut) 097 { 098 checkClosed(); 099 100 RemoteEndpoint.Async remoteEndpoint = session.getAsyncRemote(); 101 remoteEndpoint.setSendTimeout(timeOut); 102 return remoteEndpoint.sendText(message); 103 } 104 105 @Override 106 public synchronized IWebSocketConnection sendMessage(byte[] message, int offset, int length) 107 throws IOException 108 { 109 checkClosed(); 110 111 ByteBuffer buf = ByteBuffer.wrap(message, offset, length); 112 session.getBasicRemote().sendBinary(buf); 113 return this; 114 } 115 116 @Override 117 public Future<Void> sendMessageAsync(byte[] message, int offset, int length) 118 { 119 checkClosed(); 120 121 ByteBuffer buf = ByteBuffer.wrap(message, offset, length); 122 return session.getAsyncRemote().sendBinary(buf); 123 } 124 125 @Override 126 127 public Future<Void> sendMessageAsync(byte[] message, int offset, int length, long timeOut) 128 { 129 checkClosed(); 130 131 RemoteEndpoint.Async remoteEndpoint = session.getAsyncRemote(); 132 remoteEndpoint.setSendTimeout(timeOut); 133 ByteBuffer buf = ByteBuffer.wrap(message, offset, length); 134 return remoteEndpoint.sendBinary(buf); 135 } 136 137 private void checkClosed() 138 { 139 if (!isOpen()) 140 { 141 throw new IllegalStateException("The connection is closed."); 142 } 143 } 144 145 private static class CloseCode implements CloseReason.CloseCode 146 { 147 private final int code; 148 149 private CloseCode(int code) 150 { 151 this.code = code; 152 } 153 154 @Override 155 public int getCode() 156 { 157 return code; 158 } 159 } 160}