Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You 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 org.apache.tomcat.websocket.server;
 
 
 
This is the server side javax.websocket.RemoteEndpoint implementation - i.e. what the server uses to send data to the client. Communication is over a javax.servlet.ServletOutputStream.
 
 
     private static final Queue<OnResultRunnableonResultRunnables =
             new ConcurrentLinkedQueue<OnResultRunnable>();
 
     private final AbstractServletOutputStream sos;
     private final WsWriteTimeout wsWriteTimeout;
     private final ExecutorService executorService;
     private volatile SendHandler handler = null;
     private volatile ByteBuffer[] buffers = null;
     private final Object connectionWriteLock = new Object();
 
     private volatile long timeoutExpiry = -1;
     private volatile boolean close;
 
 
             WsServerContainer serverContainer) {
         this. = sos;
         this. = serverContainer.getTimeout();
         this. = serverContainer.getExecutorService();
     }
 
 
     @Override
     protected final boolean isMasked() {
         return false;
     }
 
 
     @Override
     protected void doWrite(SendHandler handlerByteBuffer... buffers) {
         this. = handler;
         this. = buffers;
         // This is definitely the same thread that triggered the write so a
         // dispatch will be required.
         onWritePossible(true);
     }
 
 
     public void onWritePossible(boolean useDispatch) {
         synchronized () {
             if ( == null) {
                 // Servlet 3.1 will call the write listener once even if nothing
                 // was written
                 return;
             }
             boolean complete = true;
             try {
                 // If this is false there will be a call back when it is true
                 while (.isReady()) {
                     complete = true;
                     for (ByteBuffer buffer : ) {
                         synchronized (buffer) {
                             if (buffer.hasRemaining()) {
                                 complete = false;
                                 .write(buffer.array(), buffer.arrayOffset(),
                                         buffer.limit());
                                 buffer.position(buffer.limit());
                                 break;
                            }
                        }
                    }
                    if (complete) {
                        .flush();
                        complete = .isReady();
                        if (complete) {
                            .unregister(this);
                            clearHandler(nulluseDispatch);
                            if () {
                                close();
                            }
                        }
                        break;
                    }
                }
            } catch (IOException ioe) {
                .unregister(this);
                clearHandler(ioeuseDispatch);
                close();
            }
            if (!complete) {
                // Async write is in progress
                long timeout = getSendTimeout();
                if (timeout > 0) {
                    // Register with timeout thread
                     = timeout + System.currentTimeMillis();
                    .register(this);
                }
            }
        }
    }
    @Override
    protected void doClose() {
        if ( != null) {
            // close() can be triggered by a wide range of scenarios. It is far
            // simpler just to always use a dispatch than it is to try and track
            // whether or not this method was called by the same thread that
            // triggered the write
            clearHandler(new EOFException(), true);
        }
        try {
            .close();
        } catch (IOException e) {
            ..closeFailed(e);
        }
        .unregister(this);
    }
    protected long getTimeoutExpiry() {
        return ;
    }
    /*
     * Currently this is only called from the background thread so we could just
     * call clearHandler() with useDispatch == false but the method parameter
     * was added in case other callers started to use this method to make sure
     * that those callers think through what the correct value of useDispatch is
     * for them.
     */
    protected void onTimeout(boolean useDispatch) {
        if ( != null) {
            clearHandler(new SocketTimeoutException(), useDispatch);
        }
        close();
    }
    @Override
    protected void setTransformation(Transformation transformation) {
        // Overridden purely so it is visible to other classes in this package
        super.setTransformation(transformation);
    }


    

Parameters:
t The throwable associated with any error that occurred
useDispatch Should javax.websocket.SendHandler.onResult(javax.websocket.SendResult) be called from a new thread, keeping in mind the requirements of javax.websocket.RemoteEndpoint.Async
    private void clearHandler(Throwable tboolean useDispatch) {
        // Setting the result marks this (partial) message as
        // complete which means the next one may be sent which
        // could update the value of the handler. Therefore, keep a
        // local copy before signalling the end of the (partial)
        // message.
        SendHandler sh = ;
         = null;
         = null;
        if (sh != null) {
            if (useDispatch) {
                OnResultRunnable r = .poll();
                if (r == null) {
                    r = new OnResultRunnable();
                }
                r.init(sht);
                if ( == null || .isShutdown()) {
                    // Can't use the executor so call the runnable directly.
                    // This may not be strictly specification compliant in all
                    // cases but during shutdown only close messages are going
                    // to be sent so there should not be the issue of nested
                    // calls leading to stack overflow as described in bug
                    // 55715. The issues with nested calls was the reason for
                    // the separate thread requirement in the specification.
                    r.run();
                } else {
                    .execute(r);
                }
            } else {
                if (t == null) {
                    sh.onResult(new SendResult());
                } else {
                    sh.onResult(new SendResult(t));
                }
            }
        }
    }
    private static class OnResultRunnable implements Runnable {
        private final Queue<OnResultRunnablequeue;
        private volatile SendHandler sh;
        private volatile Throwable t;
        private OnResultRunnable(Queue<OnResultRunnablequeue) {
            this. = queue;
        }
        private void init(SendHandler shThrowable t) {
            this. = sh;
            this. = t;
        }
        @Override
        public void run() {
            if ( == null) {
                .onResult(new SendResult());
            } else {
                .onResult(new SendResult());
            }
             = null;
             = null;
            // Return the Runnable to the queue when it has been finished with
            // Note if this method takes an age to finish there shouldn't be any
            // thread safety issues as the fields are cleared above.
            .add(this);
        }
    }
New to GrepCode? Check out our FAQ X