| Index: plugins/org.chromium.sdk.wipbackend.wk118685/src/org/chromium/sdk/internal/websocket/AbstractWsConnection.java
|
| diff --git a/plugins/org.chromium.sdk.wipbackend.wk118685/src/org/chromium/sdk/internal/websocket/AbstractWsConnection.java b/plugins/org.chromium.sdk.wipbackend.wk118685/src/org/chromium/sdk/internal/websocket/AbstractWsConnection.java
|
| deleted file mode 100644
|
| index b0e204e618969755b4f7af9cd60e138e0df83969..0000000000000000000000000000000000000000
|
| --- a/plugins/org.chromium.sdk.wipbackend.wk118685/src/org/chromium/sdk/internal/websocket/AbstractWsConnection.java
|
| +++ /dev/null
|
| @@ -1,316 +0,0 @@
|
| -// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -package org.chromium.sdk.internal.websocket;
|
| -
|
| -import java.io.IOException;
|
| -import java.nio.ByteBuffer;
|
| -import java.nio.CharBuffer;
|
| -import java.nio.charset.Charset;
|
| -import java.nio.charset.CharsetDecoder;
|
| -import java.nio.charset.CharsetEncoder;
|
| -import java.nio.charset.CoderResult;
|
| -import java.util.concurrent.BlockingQueue;
|
| -import java.util.concurrent.LinkedBlockingQueue;
|
| -import java.util.logging.Level;
|
| -import java.util.logging.Logger;
|
| -
|
| -import org.chromium.sdk.ConnectionLogger;
|
| -import org.chromium.sdk.RelayOk;
|
| -import org.chromium.sdk.SyncCallback;
|
| -import org.chromium.sdk.internal.transport.AbstractSocketWrapper;
|
| -import org.chromium.sdk.util.SignalRelay;
|
| -import org.chromium.sdk.util.SignalRelay.AlreadySignalledException;
|
| -import org.chromium.sdk.util.SignalRelay.SignalConverter;
|
| -
|
| -public abstract class AbstractWsConnection<INPUT, OUTPUT> implements WsConnection {
|
| - protected static final Charset UTF_8_CHARSET = Charset.forName("UTF-8");
|
| - private static final Logger LOGGER = Logger.getLogger(Hybi00WsConnection.class.getName());
|
| - private final AbstractSocketWrapper<INPUT, OUTPUT> socketWrapper;
|
| - private final ConnectionLogger connectionLogger;
|
| - private volatile boolean isClosingGracefully = false;
|
| -
|
| - private final BlockingQueue<MessageDispatcher> dispatchQueue =
|
| - new LinkedBlockingQueue<MessageDispatcher>();
|
| -
|
| - // Access must be synchronized on dispatchQueue.
|
| - private boolean isDispatchQueueClosed = false;
|
| -
|
| - // Access must be synchronized on this.
|
| - private boolean isOutputClosed = false;
|
| -
|
| - protected AbstractWsConnection(AbstractSocketWrapper<INPUT, OUTPUT> socketWrapper,
|
| - ConnectionLogger connectionLogger) {
|
| - this.socketWrapper = socketWrapper;
|
| - this.connectionLogger = connectionLogger;
|
| - try {
|
| - linkedCloser.bind(socketWrapper.getShutdownRelay(), null, SOCKET_TO_CONNECTION);
|
| - } catch (AlreadySignalledException e) {
|
| - throw new IllegalStateException(e);
|
| - }
|
| - }
|
| -
|
| - public enum CloseReason {
|
| - /** Socket has been shut down. */
|
| - CONNECTION_CLOSED,
|
| -
|
| - /**
|
| - * Some exception has terminated stream read thread.
|
| - * Occasionally {@link #CONNECTION_CLOSED} may be replaced with this reason (we are not
|
| - * accurate enough here).
|
| - */
|
| - INPUT_STREAM_PROBLEM,
|
| -
|
| - /**
|
| - * Closed as requested by {@link WsConnection#close()}.
|
| - */
|
| - USER_REQUEST,
|
| -
|
| - /**
|
| - * Connection close has been requested from remote side.
|
| - */
|
| - REMOTE_CLOSE_REQUEST,
|
| -
|
| - /**
|
| - * Remote side silently closed connection (without breaking a message).
|
| - */
|
| - REMOTE_SILENTLY_CLOSED,
|
| - }
|
| -
|
| - @Override
|
| - public RelayOk runInDispatchThread(final Runnable runnable, final SyncCallback syncCallback) {
|
| - MessageDispatcher messageDispatcher = new MessageDispatcher() {
|
| - @Override
|
| - boolean dispatch(Listener userListener) {
|
| - RuntimeException ex = null;
|
| - try {
|
| - runnable.run();
|
| - } catch (RuntimeException e) {
|
| - ex = e;
|
| - throw e;
|
| - } finally {
|
| - syncCallback.callbackDone(ex);
|
| - }
|
| - return false;
|
| - }
|
| - };
|
| - synchronized (dispatchQueue) {
|
| - if (isDispatchQueueClosed) {
|
| - throw new IllegalStateException("Connection is closed");
|
| - }
|
| - dispatchQueue.add(messageDispatcher);
|
| - }
|
| - return DISPATCH_THREAD_PROMISES_TO_RELAY_OK;
|
| - }
|
| -
|
| - @Override
|
| - public void startListening(final Listener listener) {
|
| - final INPUT loggableReader = socketWrapper.getLoggableInput();
|
| - Runnable listenRunnable = new Runnable() {
|
| - @Override
|
| - public void run() {
|
| - Exception closeCause = null;
|
| - CloseReason closeReason = null;
|
| - try {
|
| - closeReason = runListenLoop(loggableReader);
|
| - if (closeReason == CloseReason.REMOTE_SILENTLY_CLOSED) {
|
| - LOGGER.log(Level.INFO,
|
| - "Remote side silently closed connection without 'close' message");
|
| - }
|
| - } catch (IOException e) {
|
| - closeCause = e;
|
| - LOGGER.log(Level.SEVERE, "Connection read failure", e);
|
| - } catch (InterruptedException e) {
|
| - closeCause = e;
|
| - closeReason = CloseReason.USER_REQUEST;
|
| - LOGGER.log(Level.SEVERE, "Thread interruption", e);
|
| - } finally {
|
| - synchronized (dispatchQueue) {
|
| - dispatchQueue.add(EOS_MESSAGE_DISPATCHER);
|
| - isDispatchQueueClosed = true;
|
| - }
|
| -
|
| - if (connectionLogger != null) {
|
| - connectionLogger.handleEos();
|
| - }
|
| - if (closeReason == null) {
|
| - closeReason = CloseReason.INPUT_STREAM_PROBLEM;
|
| - }
|
| - linkedCloser.sendSignal(closeReason, closeCause);
|
| - }
|
| - }
|
| - };
|
| - Thread readThread = new Thread(listenRunnable, "WebSocket listen thread");
|
| - readThread.setDaemon(true);
|
| - readThread.start();
|
| - if (connectionLogger != null) {
|
| - connectionLogger.start();
|
| - }
|
| -
|
| - Runnable dispatchRunnable = new Runnable() {
|
| - @Override
|
| - public void run() {
|
| - try {
|
| - runImpl();
|
| - } catch (InterruptedException e) {
|
| - LOGGER.log(Level.SEVERE, "Thread interruption", e);
|
| - }
|
| - }
|
| - private void runImpl() throws InterruptedException {
|
| - while (true) {
|
| - MessageDispatcher next = dispatchQueue.take();
|
| - try {
|
| - boolean isLast = next.dispatch(listener);
|
| - if (isLast) {
|
| - return;
|
| - }
|
| - } catch (RuntimeException e) {
|
| - LOGGER.log(Level.SEVERE, "Exception in dispatch thread", e);
|
| - }
|
| - }
|
| - }
|
| - };
|
| - Thread dispatchThread = new Thread(dispatchRunnable, "WebSocket dispatch thread");
|
| - dispatchThread.setDaemon(true);
|
| - dispatchThread.start();
|
| - }
|
| -
|
| - @Override
|
| - public abstract void sendTextualMessage(String message) throws IOException;
|
| -
|
| - protected abstract CloseReason runListenLoop(INPUT loggableReader)
|
| - throws IOException, InterruptedException;
|
| -
|
| - public SignalRelay<?> getCloser() {
|
| - return linkedCloser;
|
| - }
|
| -
|
| - protected AbstractSocketWrapper<INPUT, OUTPUT> getSocketWrapper() {
|
| - return socketWrapper;
|
| - }
|
| -
|
| - protected boolean isClosingGracefully() {
|
| - return isClosingGracefully;
|
| - }
|
| -
|
| - /**
|
| - * Caller must be synchronized on this.
|
| - */
|
| - protected boolean isOutputClosed() {
|
| - return isOutputClosed;
|
| - }
|
| -
|
| - /**
|
| - * Caller must be synchronized on this.
|
| - */
|
| - protected void setOutputClosed(boolean isOutputClosed) {
|
| - this.isOutputClosed = isOutputClosed;
|
| - }
|
| -
|
| - protected BlockingQueue<MessageDispatcher> getDispatchQueue() {
|
| - return dispatchQueue;
|
| - }
|
| -
|
| - private final SignalRelay<CloseReason> linkedCloser =
|
| - SignalRelay.create(new SignalRelay.Callback<CloseReason>() {
|
| - @Override public void onSignal(CloseReason param, Exception cause) {
|
| - isClosingGracefully = true;
|
| - }
|
| - });
|
| -
|
| - /**
|
| - * A debug charset that simply encodes all non-ascii symbols as %DDD.
|
| - * We need it for log console because web-socket connection is essentially a random
|
| - * sequence of bytes.
|
| - */
|
| - protected static final Charset LOGGER_CHARSET =
|
| - new Charset("Chromium_Logger_Charset", new String[0]) {
|
| - @Override
|
| - public boolean contains(Charset cs) {
|
| - return this == cs;
|
| - }
|
| -
|
| - @Override
|
| - public CharsetDecoder newDecoder() {
|
| - return new CharsetDecoder(this, 4 / 2, 4) {
|
| - @Override
|
| - protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
|
| - while (in.hasRemaining()) {
|
| - byte b = in.get();
|
| - if (b < 20 && b != (byte) '\n') {
|
| - if (out.remaining() < 4) {
|
| - return CoderResult.OVERFLOW;
|
| - }
|
| - out.put('%');
|
| - int code = b;
|
| - int d1 = code / 100 % 10;
|
| - int d2 = code / 10 % 10;
|
| - int d3 = code % 10;
|
| - out.put((char) ('0' + d1));
|
| - out.put((char) ('0' + d2));
|
| - out.put((char) ('0' + d3));
|
| - } else {
|
| - char ch = (char) b;
|
| - if (ch == '%') {
|
| - if (out.remaining() < 2) {
|
| - return CoderResult.OVERFLOW;
|
| - }
|
| - out.put('%');
|
| - out.put('%');
|
| - } else {
|
| - if (!out.hasRemaining()) {
|
| - return CoderResult.OVERFLOW;
|
| - }
|
| - out.put(ch);
|
| - }
|
| - }
|
| - }
|
| - return CoderResult.UNDERFLOW;
|
| - }
|
| - };
|
| - }
|
| -
|
| - @Override
|
| - public CharsetEncoder newEncoder() {
|
| - throw new UnsupportedOperationException();
|
| - }
|
| - };
|
| -
|
| - protected static void dumpByte(byte b, StringBuilder output) {
|
| - output.append('%');
|
| - int code = (b + 256) % 256;
|
| - int d1 = code / 100 % 10;
|
| - int d2 = code / 10 % 10;
|
| - int d3 = code % 10;
|
| - output.append((char) ('0' + d1));
|
| - output.append((char) ('0' + d2));
|
| - output.append((char) ('0' + d3));
|
| - }
|
| -
|
| - static abstract class MessageDispatcher {
|
| - /**
|
| - * Dispatches message to user.
|
| - * @return true if it was a last message in queue
|
| - */
|
| - abstract boolean dispatch(Listener userListener);
|
| - }
|
| -
|
| - private static final MessageDispatcher EOS_MESSAGE_DISPATCHER = new MessageDispatcher() {
|
| - @Override
|
| - boolean dispatch(Listener userListener) {
|
| - userListener.eofMessage();
|
| - return true;
|
| - }
|
| - };
|
| -
|
| - private static final SignalConverter<AbstractSocketWrapper.ShutdownSignal, CloseReason>
|
| - SOCKET_TO_CONNECTION =
|
| - new SignalConverter<AbstractSocketWrapper.ShutdownSignal, CloseReason>() {
|
| - @Override public CloseReason convert(AbstractSocketWrapper.ShutdownSignal source) {
|
| - return CloseReason.CONNECTION_CLOSED;
|
| - }
|
| - };
|
| -
|
| - private static final RelayOk DISPATCH_THREAD_PROMISES_TO_RELAY_OK = new RelayOk() {};
|
| -}
|
|
|