protected abstract GuacamoleTunnel doConnect()

in guacamole-common/src/main/java/org/apache/guacamole/servlet/GuacamoleHTTPTunnelServlet.java [363:495]


    protected abstract GuacamoleTunnel doConnect(HttpServletRequest request)
            throws GuacamoleException;

    /**
     * Called whenever the JavaScript Guacamole client makes a read request.
     * This function should in general not be overridden, as it already
     * contains a proper implementation of the read operation.
     *
     * @param request
     *     The HttpServletRequest associated with the read request received.
     *
     * @param response
     *     The HttpServletResponse associated with the write request received.
     *     Any data to be sent to the client in response to the write request
     *     should be written to the response body of this HttpServletResponse.
     *
     * @param tunnelSessionToken
     *     The tunnel-specific session token of the HTTP tunnel to read from,
     *     as specified in the read request. This tunnel must have been created
     *     by a previous call to doConnect().
     *
     * @throws GuacamoleException
     *     If an error occurs while handling the read request.
     */
    protected void doRead(HttpServletRequest request,
            HttpServletResponse response, String tunnelSessionToken)
            throws GuacamoleException {

        // Get tunnel, ensure tunnel exists
        GuacamoleTunnel tunnel = getTunnel(tunnelSessionToken);

        // Ensure tunnel is open
        if (!tunnel.isOpen())
            throw new GuacamoleResourceNotFoundException("Tunnel is closed.");

        // Obtain exclusive read access
        GuacamoleReader reader = tunnel.acquireReader();

        try {

            // Note that although we are sending text, Webkit browsers will
            // buffer 1024 bytes before starting a normal stream if we use
            // anything but application/octet-stream.
            response.setContentType("application/octet-stream");
            response.setHeader("Cache-Control", "no-cache");

            // Get writer for response
            Writer out = new BufferedWriter(new OutputStreamWriter(
                    response.getOutputStream(), "UTF-8"));

            // Stream data to response, ensuring output stream is closed
            try {

                // Deregister tunnel and throw error if we reach EOF without
                // having ever sent any data
                char[] message = reader.read();
                if (message == null)
                    throw new GuacamoleConnectionClosedException("Tunnel reached end of stream.");

                // For all messages, until another stream is ready (we send at least one message)
                do {

                    // Get message output bytes
                    out.write(message, 0, message.length);

                    // Flush if we expect to wait
                    if (!reader.available()) {
                        out.flush();
                        response.flushBuffer();
                    }

                    // No more messages another stream can take over
                    if (tunnel.hasQueuedReaderThreads())
                        break;

                } while (tunnel.isOpen() && (message = reader.read()) != null);

                // Close tunnel immediately upon EOF
                if (message == null) {
                    deregisterTunnel(tunnelSessionToken);
                    tunnel.close();
                }

                // End-of-instructions marker
                out.write("0.;");
                out.flush();
                response.flushBuffer();
            }

            // Send end-of-stream marker and close tunnel if connection is closed
            catch (GuacamoleConnectionClosedException e) {

                // Deregister and close
                deregisterTunnel(tunnelSessionToken);
                tunnel.close();

                // End-of-instructions marker
                out.write("0.;");
                out.flush();
                response.flushBuffer();

            }

            catch (GuacamoleException e) {

                // Deregister and close
                deregisterTunnel(tunnelSessionToken);
                tunnel.close();

                throw e;
            }

            // Always close output stream
            finally {
                out.close();
            }

        }
        catch (IOException e) {

            // Log typically frequent I/O error if desired
            logger.debug("Error writing to servlet output stream", e);

            // Deregister and close
            deregisterTunnel(tunnelSessionToken);
            tunnel.close();

        }
        finally {
            tunnel.releaseReader();
        }

    }