text:
package com.programmaticallyspeaking.tinyws;

import javax.net.ssl.*;
import java.io.*;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.*;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * A WebSocket server. Usage:
 *
 *

 *
Create an instance of this class.
 *
Add one or more handler factories using the {@link Server#addHandlerFactory(String, Supplier)} method.
 *
Start the server using {@link Server#start()}.
 *
Connect clients...
 *
Stop using {@link Server#stop()}.
 *

 *
 * The server implementation passes all tests of
 * Autobahn|Testsuite (version 0.10.9) except 12.* and 13.* (compression using the permessage-deflate extension).
 */
public class Server {
    public static final String ServerName = "TinyWS Server";
    public static final String ServerVersion = "@VERSION@";

    private static final String HANDSHAKE_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
    private static final int SupportedVersion = 13;

    private final Executor mainExecutor;
    private final Options options;
    private final Logger logger;

    private ServerSocket serverSocket;
    private Map<String, Supplier<WebSocketHandler>> handlerFactories = new HashMap<>();

    private FallbackHandler fallbackHandler = new DefaultFallbackHandler();

    /**
     * Constructs a new server instance but doesn't start listening for client connections.
     *
     * @param mainExecutor the {@link Executor} instance that will be used to run the main listener task as well as
     *                     tasks for handling connected clients. Please note that each task will use excessive blocking
     *                     I/O, so use an appropriate executor.
     * @param options server options
     */
    public Server(Executor mainExecutor, Options options) {
        this.mainExecutor = mainExecutor;
        this.options = options;
        this.logger = new Logger() {
            public void log(LogLevel level, String message, Throwable error) {
                if (isEnabledAt(level)) {
                    try {
                        options.logger.log(level, message, error);
                    } catch (Exception ignore) {
                        // ignore logging errors
                    }
                }
            }

            @Override
            public boolean isEnabledAt(LogLevel level) {
                return options.logger != null && options.logger.isEnabledAt(level);
            }
        };
    }

    private void lazyLog(LogLevel level, Supplier<String> msgFun) {
        if (logger.isEnabledAt(level)) logger.log(level, msgFun.get(), null);
    }

    /**
     * Adds a factory for creating handlerFactories for a specific endpoint. Handler factories must be added before the server
     * is started. The endpoint must match a requested resource exactly to be used. The root handler factory must thus
     * be registered for the "/" endpoint.
     *
     * @param endpoint non-{@code null}, non-empty endpoint
     * @param handlerFactory a handler factory
     * @exception IllegalStateException if the server has been started
     */
    public void addHandlerFactory(String endpoint, Supplier<WebSocketHandler> handlerFactory) {
        if (endpoint == null || "".equals(endpoint)) throw new IllegalArgumentException("Endpoint must be non-empty.");
        if (serverSocket != null) throw new IllegalStateException("Please add handler factories before starting the server.");
        handlerFactories.put(endpoint, handlerFactory);
    }

    /**
     * Sets the fallback handler to use for endpoints with no registered handler factory. Fallback handler must be set
     * before the server is started.
     *
     * @param handler the fallback handler; {@code null} restores the default handler (which responds 404)
     */
    public void setFallbackHandler(FallbackHandler handler) {
        if (serverSocket != null) throw new IllegalStateException("Please add fallback handler before starting the server.");
        if (handler == null) handler = new DefaultFallbackHandler();
        fallbackHandler = handler;
    }

    /**
     * Starts listening for client connections, using the port specified in the options passed to the constructor. If
     * a backlog was not specified in the options, the Java-default backlog (50 for Java 8) is used.
     *
     * The server socket is created on the current thread, in the interest of fail-fast. The main executor is then
     * used to start the listening task.
     *
     * @exception IOException if creating the server socket fails
     * @exception GeneralSecurityException if an SSL related error occurs
     */
    public void start() throws IOException, GeneralSecurityException {
        serverSocket = createServerSocket();
        mainExecutor.execute(this::acceptInLoop);
    }

    private ServerSocket createServerSocket() throws IOException, GeneralSecurityException {
        // Using backlog 0 will force ServerSocket to use the default (50).
        int backlog = options.backlog != null ? options.backlog : 0;

        if (options.shouldUseSSL()) {
            SSLServerSocketFactory sslServerSocketFactory = options.sslContext.getServerSocketFactory();
            return sslServerSocketFactory.createServerSocket(options.port, backlog, options.address);
        }

        return new ServerSocket(options.port, backlog, options.address);
    }

    /**
     * Stops listening for client connection. Does nothing if the server has already been stopped (or hasn't been started
     * to begin with). Any exception from closing the server socket is suppressed but will be logged at WARN level to
     * any supplied logger.
     */
    public void stop() {
        if (serverSocket == null) return;
        try {
            serverSocket.close();
        } catch (IOException e) {
            logger.log(LogLevel.WARN, "Failed to close server socket.", e);
        }
        serverSocket = null;
    }

    private void acceptInLoop() {
        try {
            lazyLog(LogLevel.INFO, () -> "Receiving WebSocket clients at " + serverSocket.getLocalSocketAddress());

            while (true) {
                Socket clientSocket = serverSocket.accept();

                // We need this on Linux. Without it the close frame sent just before closing the
                // socket won't be seen by the WebSocket client.
                clientSocket.setTcpNoDelay(true);

                mainExecutor.execute(new ClientHandler(clientSocket));
            }
        } catch (SocketException e) {
            logger.log(LogLevel.DEBUG, "Server socket was closed, probably because the server was stopped.", e);
        } catch (Exception ex) {
            logger.log(LogLevel.ERROR, "Error accepting a client socket.", ex);
        }
    }

    private class ClientHandler implements Runnable {

        private final Socket clientSocket;
        private final OutputStream out;
        private final InputStream in;
        private final PayloadCoder payloadCoder;
        private final FrameWriter frameWriter;
        private WebSocketHandler handler;
        private volatile boolean isClosed; // potentially set from handler thread

        ClientHandler(Socket clientSocket) throws IOException {
            this.clientSocket = clientSocket;
            out = clientSocket.getOutputStream();
            in = clientSocket.getInputStream();

            payloadCoder = new PayloadCoder();
            frameWriter = new FrameWriter(out, payloadCoder, options.maxFrameSize);
        }

        private void invokeHandler(Consumer<WebSocketHandler> fun) {
            if (handler == null) return;
            try {
                fun.accept(handler);
            } catch (Exception ex) {
                logger.log(LogLevel.ERROR, "Handler invocation error.", ex);
            }
        }

        @Override
        public void run() {
            try {
                communicate();
            } catch (WebSocketClosure ex) {
                lazyLog(LogLevel.DEBUG, () -> String.format("Closing with code %d (%s)%s", ex.code, ex.reason,
                        ex.debugDetails != null ? (" because: " + ex.debugDetails) : ""));
                doIgnoringExceptions(() -> frameWriter.writeClose(ex.code, ex.reason));
                // If the connection was closed by the client, we expect onClosedByClient to have been invoked and
                // we must *not* invoke onClosedByServer since that would be a lie...
                if (!ex.closedByClient)
                    invokeHandler(h -> h.onClosedByServer(ex.code, ex.reason));
            } catch (MethodNotAllowedException ex) {
                lazyLog(LogLevel.WARN, () -> String.format("WebSocket client from %s used a non-allowed method: %s",
                            clientSocket.getRemoteSocketAddress(), ex.method));
                sendMethodNotAllowedResponse();
            } catch (IllegalArgumentException ex) {
                lazyLog(LogLevel.WARN, () -> String.format("WebSocket client from %s sent a malformed request: %s",
                        clientSocket.getRemoteSocketAddress(), ex.getMessage()));
                sendBadRequestResponse();
            } catch (FileNotFoundException ex) {
                lazyLog(LogLevel.WARN, () -> String.format("WebSocket client from %s requested an unknown endpoint.",
                        clientSocket.getRemoteSocketAddress()));
                sendNotFoundResponse();
            } catch (SocketException ex) {
                if (!isClosed) {
                    logger.log(LogLevel.ERROR, "Client socket error.", ex);
                    invokeHandler(h -> h.onFailure(ex));
                }
            } catch (Exception ex) {
                logger.log(LogLevel.ERROR, "Client communication error.", ex);
                invokeHandler(h -> h.onFailure(ex));
            }
            abort();
        }

        private void abort() {
            if (isClosed) return;
            doIgnoringExceptions(clientSocket::close);
            isClosed = true;
        }

        private void communicate() throws IOException, NoSuchAlgorithmException {
            maybeLogSSLDetails();

            Headers headers = Headers.read(in, isSSL());
            String endpoint = headers.endpoint;

            Supplier<WebSocketHandler> handlerFactory = handlerFactories.get(endpoint);
            if (handlerFactory == null || (handler = handlerFactory.get()) == null) {
                fallbackHandler.handle(createConnection(headers));
                return;
            }

            if (!"GET".equals(headers.method)) throw new MethodNotAllowedException(headers.method);
            if (!headers.isProperUpgrade()) throw new IllegalArgumentException("Handshake has malformed upgrade.");
            if (headers.version() != SupportedVersion) throw new IllegalArgumentException("Bad version, must be: " + SupportedVersion);

            lazyLog(LogLevel.INFO, () -> String.format("New WebSocket client from %s at endpoint '%s'.",
                        clientSocket.getRemoteSocketAddress(), endpoint));

            invokeHandler(h -> h.onOpened(new WebSocketClientImpl(frameWriter, this::abort, headers)));

            String key = headers.key();
            if (key == null) throw new IllegalArgumentException("Missing Sec-WebSocket-Key in handshake.");

            String responseKey = createResponseKey(key);

            lazyLog(LogLevel.TRACE, () -> String.format("Opening handshake key is '%s', sending response key '%s'.", key, responseKey));

            sendHandshakeResponse(responseKey);

            List<Frame> frameBatch = new ArrayList<>();
            while (true) {
                frameBatch.add(Frame.read(in));
                handleBatch(frameBatch);
            }
        }

        private Connection createConnection(Headers headers) {
            return new Connection() {
                @Override public String method() { return headers.method; }
                @Override public URI uri() { return headers.uri; }
                @Override public InputStream inputStream() { return in; }
                @Override public OutputStream outputStream() { return out; }
                @Override public Iterable<String> headerNames() { return headers.headers.keySet(); }
                @Override public Optional<String> header(String name) {
                    if (name == null) throw new IllegalArgumentException("Header name must be non-null");
                    String value = headers.headers.get(name);
                    return Optional.ofNullable(value);
                }
                @Override
                public void sendResponse(int statusCode, String reason, Map<String, String> headers) {
                    if (reason == null) reason = "";
                    if (headers == null) headers = Collections.emptyMap();
                    ClientHandler.this.sendResponse(statusCode, reason, headers);
                }
            };
        }

        private boolean isSSL() {
            return clientSocket instanceof SSLSocket;
        }

        private void maybeLogSSLDetails() {
            if (isSSL()) {
                SSLSocket sslSocket = (SSLSocket) clientSocket;
                SSLSession sslSession = sslSocket.getSession();
                lazyLog(LogLevel.DEBUG, () -> String.format("SSL session uses protocol %s and cipher suite %s.",
                        sslSession.getProtocol(), sslSession.getCipherSuite()));
            }
        }

        private void handleBatch(List<Frame> frameBatch) throws IOException {
            Frame firstFrame = frameBatch.get(0);

            if (firstFrame.opCode == 0) throw WebSocketClosure.protocolError("Continuation frame with nothing to continue.");

            Frame lastOne = frameBatch.get(frameBatch.size() - 1);
            lazyLog(LogLevel.TRACE, lastOne::toString);
            if (!lastOne.isFin) return;
            if (firstFrame != lastOne) {
                if (lastOne.isControl()) {
                    // Interleaved control frame
                    frameBatch.remove(frameBatch.size() - 1);
                    handleResultFrame(lastOne);
                    return;
                } else if (lastOne.opCode > 0) {
                    throw WebSocketClosure.protocolError("Continuation frame must have opcode 0.");
                }
            }

            Frame result = frameBatch.size() > 1 ? Frame.merge(frameBatch) : lastOne;

            frameBatch.clear();

            handleResultFrame(result);
        }

        private void handleResultFrame(Frame result) throws IOException {
            switch (result.opCode) {
                case 1:
                    CharSequence data = payloadCoder.decode(result.payloadData);
                    invokeHandler(h -> h.onTextMessage(data));
                    break;
                case 2:
                    invokeHandler(h -> h.onBinaryData(result.payloadData));
                    break;
                case 8:
                    CloseData cd = result.toCloseData(payloadCoder);

                    if (cd.hasInvalidCode()) throw WebSocketClosure.protocolError("Invalid close frame code: " + cd.code);

                    // 1000 is normal close
                    int i = cd.code != null ? cd.code : 1000;

                    invokeHandler(h -> h.onClosedByClient(i, cd.reason));

                    throw WebSocketClosure.fromClient(i);
                case 9:
                    // Ping, send pong!
                    logger.log(LogLevel.TRACE, "Got ping frame, sending pong.", null);
                    frameWriter.writePong(result.payloadData);
                    break;
                case 10:
                    // Pong is ignored
                    logger.log(LogLevel.TRACE, "Ignoring unsolicited pong frame.", null);
                    break;
                default:
                    throw WebSocketClosure.protocolError("Invalid opcode: " + result.opCode);
            }
        }

        private void outputLine(PrintWriter writer, String data) {
            writer.print(data);
            writer.print("\r\n");
        }

        private void sendHandshakeResponse(String responseKey) {
            Map<String, String> headers = new HashMap<String, String>() {{
                put("Upgrade", "websocket");
                put("Connection", "upgrade");
                put("Sec-WebSocket-Accept", responseKey);
            }};
            sendEmptyResponseBeforeClose(101, "Switching Protocols", headers);
        }

        private void sendBadRequestResponse() {
            // Advertise supported version regardless of what was bad. A bit lazy, but simple.
            Map<String, String> headers = new HashMap<String, String>() {{
                put("Sec-WebSocket-Version", Integer.toString(SupportedVersion));
            }};
            sendEmptyResponseBeforeClose(400, "Bad Request", headers);
        }
        private void sendMethodNotAllowedResponse() {
            Map<String, String> headers = new HashMap<String, String>() {{
                put("Allow", "GET");
            }};
            sendEmptyResponseBeforeClose(405, "Method Not Allowed", headers);
        }
        private void sendNotFoundResponse() {
            sendEmptyResponseBeforeClose(404, "Not Found", Collections.emptyMap());
        }

        private void sendEmptyResponseBeforeClose(int statusCode, String reason, Map<String, String> headers) {
            Map<String, String> allHeaders = new HashMap<>(headers);
            // Headers added when we don't do a connection upgrade to WebSocket!
            if (statusCode >= 200) {
                // https://tools.ietf.org/html/rfc7230#section-6.1
                allHeaders.put("Connection", "close");

                // https://tools.ietf.org/html/rfc7230#section-3.3.2
                allHeaders.put("Content-Length", "0");
            }

            sendResponse(statusCode, reason, allHeaders);
        }
        private void sendResponse(int statusCode, String reason, Map<String, String> headers) {
            PrintWriter writer = new PrintWriter(out, false);
            outputLine(writer, "HTTP/1.1 " + statusCode + " " + reason);
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                outputLine(writer, entry.getKey() + ": " + entry.getValue());
            }

            // https://tools.ietf.org/html/rfc7231#section-7.4.2
            outputLine(writer, String.format("Server: %s %s", ServerName, ServerVersion));

            outputLine(writer, "");
            writer.flush();
            // Note: Do NOT close the writer, as the stream must remain open
        }
    }

    static class Frame {

        final int opCode;
        final byte[] payloadData;
        final boolean isFin;

        public String toString() {
            return String.format("Frame[opcode=%d, control=%b, payload length=%d, fragmented=%b]",
                    opCode, isControl(), payloadData.length, !isFin);
        }

        boolean isControl() {
            return (opCode & 8) == 8;
        }

        private Frame(int opCode, byte[] payloadData, boolean isFin) {
            this.opCode = opCode;
            this.payloadData = payloadData;
            this.isFin = isFin;
        }

        private static int toUnsigned(byte b) {
            int result = b;
            if (result < 0) result += 256;
            return result;
        }

        private static byte[] readBytes(InputStream in, int len, byte[] target) throws IOException {
            assert target == null || target.length >= len : "readBytes target is too small";
            byte[] buf = target != null ? target : new byte[len];
            int totalRead = 0;
            int offs = 0;
            while (totalRead < len) {
                int readLen = in.read(buf, offs, len - offs);
                if (readLen < 0) break;
                totalRead += readLen;
                offs += readLen;
            }
            if (totalRead != len) throw new IOException("Expected to read " + len + " bytes but read " + totalRead);
            return buf;
        }

        private static long toLong(byte[] data, int offset, int len) {
            long result = 0;
            for (int i = offset, j = offset + len; i < j; i++) {
                result = (result << 8) + toUnsigned(data[i]);
            }
            return result;
        }

        static Frame read(InputStream in) throws IOException {
            // We will read at most 8 bytes at any time, except the payload data.
            byte[] buf = new byte[8];

            // Read first 2 bytes
            readBytes(in, 2, buf);
            byte firstByte = buf[0];
            byte secondByte = buf[1];
            boolean isFin = (firstByte & 128) == 128;
            boolean hasZeroReserved = (firstByte & 112) == 0;
            if (!hasZeroReserved) throw WebSocketClosure.protocolError("Non-zero reserved bits in 1st byte: " + (firstByte & 112));
            int opCode = (firstByte & 15);
            boolean isControlFrame = (opCode & 8) == 8;
            boolean isMasked = (secondByte & 128) == 128;
            int len = (secondByte & 127);
            if (isControlFrame) {
                if (len > 125) throw WebSocketClosure.protocolError("Control frame length exceeding 125 bytes.");
                if (!isFin) throw WebSocketClosure.protocolError("Fragmented control frame.");
            }
            if (len == 126) {
                // 2 bytes of extended len
                long tmp = toLong(readBytes(in, 2, buf), 0, 2);
                len = (int) tmp;
            } else if (len == 127) {
                // 8 bytes of extended len
                long tmp = toLong(readBytes(in, 8, buf), 0, 8);
                if (tmp > Integer.MAX_VALUE) throw WebSocketClosure.protocolError("Frame length greater than 0x7fffffff not supported.");
                len = (int) tmp;
            }
            byte[] maskingKey = isMasked ? readBytes(in, 4, buf) : null;
            byte[] payloadData = unmaskIfNeededInPlace(readBytes(in, len, null), maskingKey);
            return new Frame(opCode, payloadData, isFin);
        }

        CloseData toCloseData(PayloadCoder payloadCoder) throws WebSocketClosure {
            if (opCode != 8) throw new IllegalStateException("Not a close frame: " + opCode);
            if (payloadData.length == 0) return new CloseData(null, null);
            if (payloadData.length == 1) throw WebSocketClosure.protocolError("Invalid close frame payload length (1).");
            int code = (int) toLong(payloadData, 0, 2);
            CharSequence reason = payloadData.length > 2 ? payloadCoder.decode(payloadData, 2, payloadData.length - 2) : null;
            return new CloseData(code, reason != null ? reason.toString() : null);
        }

        static Frame merge(List<Frame> frameBatch) {                // Combine payloads!
            int totalLength = frameBatch.stream().mapToInt(f -> f.payloadData.length).sum();
            byte[] allTheData = new byte[totalLength];
            int offs = 0;
            for (Frame frame : frameBatch) {
                System.arraycopy(frame.payloadData, 0, allTheData, offs, frame.payloadData.length);
                offs += frame.payloadData.length;
            }
            return new Frame(frameBatch.get(0).opCode, allTheData, true);
        }
    }

    private static class CloseData {
        private final Integer code;
        private final String reason;

        CloseData(Integer code, String reason) {
            this.code = code;
            this.reason = reason;
        }

        boolean hasInvalidCode() {
            if (code == null) return false; // no code isn't invalid
            if (code < 1000 || code >= 5000) return true;
            if (code >= 3000) return false; // 3000-3999 and 4000-4999 are valid
            return code == 1004 || code == 1005 || code == 1006 || code > 1011;
        }
    }

    static class Headers {
        private final Map<String, String> headers;
        final String endpoint;
        final String method;
        final String query;
        final String fragment;
        final URI uri;

        private Headers(Map<String, String> headers, URI uri, String method) {
            this.headers = headers;
            this.method = method;
            this.uri = uri;
            this.endpoint = uri.getPath();
            this.query = uri.getQuery();
            this.fragment = uri.getFragment();
        }

        boolean isProperUpgrade() {
            return "websocket".equalsIgnoreCase(headers.get("Upgrade")) && "Upgrade".equalsIgnoreCase(headers.get("Connection"));
        }
        int version() {
            String versionStr = headers.get("Sec-WebSocket-Version");
            try {
                return Integer.parseInt(versionStr);
            } catch (Exception ignore) {
                return 0;
            }
        }

        String key() { return headers.get("Sec-WebSocket-Key"); }
        String userAgent() { return headers.get("User-Agent"); }
        String host() { return headers.get("Host"); }

        private static String readHeaderLine(InputStream in) throws IOException {
            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
            int b;
            while ((b = in.read()) != 13) {
                if (b < 0) break; // EOS, return what we have
                bytes.write(b);
            }
            if (b != -1) {
                // Read one more, but it has to be LF
                if (in.read() != 10) throw new IOException("Expected LF after CR in HTTP header");
            }
            return new String(bytes.toByteArray(), StandardCharsets.US_ASCII);
        }

        static Headers read(InputStream in, boolean isSSL) throws IOException {
            String inputLine, method = "";
            String path = null;
            URI endpoint = null;
            Map<String, String> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
            boolean isFirstLine = true;
            while (!"".equals((inputLine = readHeaderLine(in)))) {
                if (isFirstLine) {
                    String[] parts = inputLine.split(" ", 3);
                    if (parts.length != 3) throw new IllegalArgumentException("Malformed 1st header line: " + inputLine);
                    method = parts[0];
                    if (!"HTTP/1.1".equals(parts[2])) throw new IllegalArgumentException("Only HTTP/1.1 is supported");
                    path = parts[1];
                    isFirstLine = false;
                }

                String[] keyValue = inputLine.split(":", 2);
                if (keyValue.length != 2) continue;

                headers.put(keyValue[0], keyValue[1].trim());
            }
            if (isFirstLine) throw new IllegalArgumentException("No HTTP headers received");

            // Figure out the entire endpoint
            try {
                String scheme = isSSL ? "https" : "http";
                String host = headers.get("host");
                if (host == null) host = "server";
                endpoint = new URI(scheme + "://" + host + path);
            } catch (URISyntaxException e) {
                throw new IllegalArgumentException("Invalid endpoint: " + path);
            }

            // Note: Do NOT close the reader, because the stream must remain open!
            return new Headers(headers, endpoint, method);
        }
    }

    static class PayloadCoder {
        private final Charset charset = StandardCharsets.UTF_8;
        private final CharsetDecoder decoder = charset.newDecoder();
        private final CharsetEncoder encoder = charset.newEncoder();

        CharSequence decode(byte[] bytes) throws WebSocketClosure {
            return decode(bytes, 0, bytes.length);
        }

        /**
         * Decodes the given byte data as UTF-8 and returns the result as a string.
         *
         * @param bytes the byte array
         * @param offset offset into the array where to start decoding
         * @param len length of data to decode
         * @return the decoded string
         * @throws WebSocketClosure (1007) thrown if the data are not valid UTF-8
         */
        CharSequence decode(byte[] bytes, int offset, int len) throws WebSocketClosure {
            decoder.reset();
            try {
                return decoder.decode(ByteBuffer.wrap(bytes, offset, len));
            } catch (Exception ex) {
                throw WebSocketClosure.invalidFramePayloadData();
            }
        }

        ByteBuffer encode(CharSequence s) throws CharacterCodingException {
            encoder.reset();
            ByteBuffer buf = encoder.encode(CharBuffer.wrap(s));
            assert buf.hasArray() : "Expected ByteBuffer to have an array";
            return buf;
        }
    }

    static class WebSocketClosure extends IOException {
        final int code;
        final String reason;
        final String debugDetails;
        final boolean closedByClient;

        private WebSocketClosure(int code, String reason, String debugDetails, boolean closedByClient) {
            this.code = code;
            this.reason = reason;
            this.debugDetails = debugDetails;
            this.closedByClient = closedByClient;
        }

        static WebSocketClosure fromClient(int code) {
            return new WebSocketClosure(code, "", "Closed by client", true);
        }
        static WebSocketClosure protocolError(String debugDetails) {
            return new WebSocketClosure(1002, "Protocol error", debugDetails, false);
        }
        static WebSocketClosure invalidFramePayloadData() {
            return new WebSocketClosure(1007, "Invalid frame payload data", null, false);
        }

        @Override
        public synchronized Throwable fillInStackTrace() {
            // Stack trace is not relevant
            return this;
        }
    }

    static class FrameWriter {
        private final OutputStream out;
        private final PayloadCoder payloadCoder;
        private final int maxFrameSize;

        // Reusable array for writing length bytes
        private final byte[] lengthBytes = new byte[8];

        FrameWriter(OutputStream out, PayloadCoder payloadCoder, int maxFrameSize) {
            this.out = out;
            this.payloadCoder = payloadCoder;
            this.maxFrameSize = maxFrameSize;
        }

        void writeClose(int code, String reason) throws IOException {
            ByteBuffer buf = payloadCoder.encode(reason);
            int bufLen = buf.limit();
            byte[] combined = new byte[2 + bufLen];
            numberToBytes(code, 2, combined);
            buf.get(combined, 2, bufLen);
            writeFrame(8, combined);
        }

        void writeText(CharSequence text) throws IOException {
            ByteBuffer buf = payloadCoder.encode(text);
            writePossiblyFragmentedFrames(1, buf);
        }

        void writeBinary(byte[] data) throws IOException {
            writePossiblyFragmentedFrames(2, ByteBuffer.wrap(data));
        }

        void writePing(byte[] data) throws IOException {
            writeFrame(9, data);
        }

        void writePong(byte[] data) throws IOException {
            writeFrame(10, data);
        }

        private void writePossiblyFragmentedFrames(int opCode, ByteBuffer buf) throws IOException {
            // https://tools.ietf.org/html/rfc6455#section-5.6 implies that a single frame may contain an UTF-8
            // sequence that by itself is invalid, as long as the entire message text is valid UTF-8.
            int bufLen = buf.limit();
            byte[] data = buf.array();
            if (maxFrameSize == 0 || bufLen <= maxFrameSize) {
                writeFrame(opCode, data, bufLen, 0, bufLen);
            } else {
                int offset = 0;
                while (offset < bufLen) {
                    int len = Math.min(bufLen - offset, maxFrameSize);
                    writeFrame(opCode, data, bufLen, offset, len);
                    offset += len;
                }
            }
        }

        private void writeFrame(int opCode, byte[] data) throws IOException {
            int dataLen = data != null ? data.length : 0;
            writeFrame(opCode, data, dataLen, 0, dataLen);
        }

        /**
         * Writes a frame to the output stream. Since FrameWriter is handed out to potentially different threads,
         * this method is synchronized.
         *
         * @param opCode the opcode of the frame
         * @param data array that contains frame data
         * @param totalLen total data length (differs from {@code len} when data are split across multiple frames
         * @param offset offset in the {@code data} array where the frame data starts
         * @param len length of frame data
         * @throws IOException thrown if writing to the socket fails
         */
        synchronized private void writeFrame(int opCode, byte[] data, int totalLen, int offset, int len) throws IOException {
            boolean isFirstFrame = offset == 0;
            boolean isFinalFrame = offset + len == totalLen;

            int firstByte = isFirstFrame ? opCode : 0;
            if (isFinalFrame) firstByte |= 128; // FIN
            int secondByte;
            int extraLengthBytes = 0;
            if (len < 126) {
                secondByte = len;
            } else if (len < 65536) {
                secondByte = 126;
                extraLengthBytes = 2;
            } else {
                secondByte = 127;
                extraLengthBytes = 8;
            }
            out.write(firstByte);
            out.write(secondByte);
            if (extraLengthBytes > 0) {
                out.write(numberToBytes(len, extraLengthBytes, lengthBytes), 0, extraLengthBytes);
            }
            if (data != null) out.write(data, offset, len);
            out.flush();
        }
    }

    private static class WebSocketClientImpl implements WebSocketClient {

        private final FrameWriter writer;
        private final Runnable closeCallback;
        private final Headers headers;

        WebSocketClientImpl(FrameWriter writer, Runnable closeCallback, Headers headers) {
            this.writer = writer;
            this.closeCallback = closeCallback;
            this.headers = headers;
        }

        public void ping() throws IOException {
            writer.writePing(null);
        }

        public void close() {
            doIgnoringExceptions(() -> {
                writer.writeClose(1001, "Going Away");
                closeCallback.run();
            });
        }

        public void sendTextMessage(CharSequence text) throws IOException {
            if (text == null) throw new IllegalArgumentException("Cannot send null text");
            writer.writeText(text);
        }

        public void sendBinaryData(byte[] data) throws IOException {
            if (data == null) throw new IllegalArgumentException("Cannot send null data");
            writer.writeBinary(data);
        }

        public String userAgent() { return headers.userAgent(); }
        public String host() { return headers.host(); }
        public String query() { return headers.query; }
        public String fragment() { return headers.fragment; }
    }

    static byte[] numberToBytes(int number, int len, byte[] target) {
        assert target == null || target.length >= len : "numberToBytes target is too small";
        byte[] array = target != null ? target : new byte[len];
        // Start from the end (network byte order), assume array is filled with zeros.
        for (int i = len - 1; i >= 0; i--) {
            array[i] = (byte) (number & 0xff);
            number = number >> 8;
        }
        return array;
    }

    static String createResponseKey(String key) throws NoSuchAlgorithmException {
        MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
        byte[] rawBytes = (key + HANDSHAKE_GUID).getBytes();
        byte[] result = sha1.digest(rawBytes);
        return Base64.getEncoder().encodeToString(result);
    }

    private static void doIgnoringExceptions(RunnableThatThrows runnable) {
        try {
            runnable.run();
        } catch (Exception ex) {
            // ignore
        }
    }
    private interface RunnableThatThrows {
        void run() throws Exception;
    }

    static byte[] unmaskIfNeededInPlace(byte[] bytes, byte[] maskingKey) {
        if (maskingKey != null) {
            // Performance note: This code is up to 4 times faster than using only the last loop by itself.
            // Using an IntBuffer is not faster.
            byte m0 = maskingKey[0], m1 = maskingKey[1], m2 = maskingKey[2], m3 = maskingKey[3];
            int roundedLen = 4 * (bytes.length / 4);
            int i = 0;
            for (; i < roundedLen; i += 4) {
                bytes[i] = (byte) (bytes[i] ^ m0);
                bytes[i+1] = (byte) (bytes[i+1] ^ m1);
                bytes[i+2] = (byte) (bytes[i+2] ^ m2);
                bytes[i+3] = (byte) (bytes[i+3] ^ m3);
            }
            for (; i < bytes.length; i++) {
                int j = i % 4;
                bytes[i] = (byte) (bytes[i] ^ maskingKey[j]);
            }
        }
        return bytes;
    }

    static class MethodNotAllowedException extends IllegalArgumentException {
        final String method;
        public MethodNotAllowedException(String method) {
            this.method = method;
        }
    }

    /**
     * Server options, configured using a fluent interface. Start with {@code Options.withPort(int)} since port is
     * required.
     */
    public static class Options {
        Integer backlog;
        int port;
        Logger logger;
        InetAddress address;
        int maxFrameSize;
        SSLContext sslContext;

        private boolean shouldUseSSL() { return sslContext != null; }

        private Options(int port) {
            this.port = port;
        }

        /**
         * Creates new options with the given port.
         *
         * @param port the port to use when listening for WebSocket clients
         * @return this options instance
         */
        public static Options withPort(int port) {
            return new Options(port);
        }

        /**
         * Specifies the backlog size, i.e. the size of the client connection queue. If the queue is full, a client
         * connection is rejected.
         *
         * @param backlog the backlog size, which must be greater than 0
         * @return this options instance
         */
        public Options andBacklog(int backlog) {
            if (backlog <= 0) throw new IllegalArgumentException("Backlog must be > 0");
            this.backlog = backlog;
            return this;
        }

        /**
         * Specifies a logger.
         *
         * @param logger the logger instance
         * @return this options instance
         */
        public Options andLogger(Logger logger) {
            this.logger = logger;
            return this;
        }

        /**
         * Specifies the address to use when creating the server socket.
         *
         * @param address the address to bind to
         * @return this options instance
         */
        public Options andAddress(InetAddress address) {
            this.address = address;
            return this;
        }

        /**
         * Specifies the maximum frame size. The maximum frame size must be at least 126, as it doesn't make much
         * sense to create frame fragments smaller than that.
         *
         * @param size maximum frame size
         * @return this options instance
         */
        public Options andMaxFrameSize(int size) {
            if (size <= 125) throw new IllegalArgumentException("Max frame size must be at least 126.");
            this.maxFrameSize = size;
            return this;
        }

        /**
         * Configures the server for SSL.
         *
         * @param sslContext the SSL context that creates an SSL socket
         * @return this options instance
         */
        public Options andSSL(SSLContext sslContext) {
            if (sslContext == null) throw new IllegalArgumentException("SSL context cannot be null.");
            this.sslContext = sslContext;
            return this;
        }
    }

    /**
     * Log level for logging.
     */
    public enum LogLevel {
        TRACE(0),
        DEBUG(10),
        INFO(20),
        WARN(50),
        ERROR(100);

        /**
         * Numeric level corresponding to this log level. ERROR has the highest level and TRACE has the lowest.
         */
        public final int level;

        LogLevel(int level) {
            this.level = level;
        }
    }

    /**
     * A simple interface for logging.
     */
    public interface Logger {
        /**
         * Logs a message at a certain level. Note that this method is not called if {@link #isEnabledAt(LogLevel)}
         * returns {@code false} for the given level.
         *
         * @param level the log level
         * @param message the message to log
         * @param error an optional error
         */
        void log(LogLevel level, String message, Throwable error);

        /**
         * Determines if logging is enabled for the given level.
         *
         * @param level a log level
         * @return {@code true} if logging is enabled at the level, {@code false} otherwise
         */
        boolean isEnabledAt(LogLevel level);
    }

    /**
     * Represents a WebSocket client and exposes methods that makes it possible to interact with the client, as well
     * as methods for getting information about the client and how it requested the handled resource.
     *
     * Methods on this interface can be invoked from any thread.
     */
    public interface WebSocketClient {
        /**
         * Sends a ping to the client. This can be used to send keep-alive messages to the client.
         *
         * @throws IOException on I/O failure while sending the ping
         */
        void ping() throws IOException;

        /**
         * Performs a clean close of the connection to the client.
         */
        void close();

        /**
         * Sends a text message to the client.
         *
         * @param text the text to send
         * @throws IOException on I/O failure while sending
         */
        void sendTextMessage(CharSequence text) throws IOException;

        /**
         * Sends binary data to the client.
         *
         * @param data the data to send
         * @throws IOException on I/O failure while sending
         */
        void sendBinaryData(byte[] data) throws IOException;

        /**
         * Returns the value of the User-Agent header passed by the client when requesting a Websocket connection. If no
         * User-Agent header was present, returns {@code null}.
         *
         * @return the Host header value, or {@code null}
         */
        String userAgent();

        /**
         * Returns the value of the Host header passed by the client when requesting a Websocket connection. If no
         * Host header was present, returns {@code null}.
         *
         * @return the Host header value, or {@code null}
         */
        String host();

        /**
         * Returns the query (part after '?', not including the fragment) used by the client when requesting a WebSocket
         * connection. If no query was specified, returns {@code null}. If an empty query was specified, returns the
         * empty string. The '?' character is never included.
         *
         * @return a query string, or {@code null}
         * @see Uniform Resource Identifier (URI): Generic Syntax
         */
        String query();

        /**
         * Returns the fragment (part after '#') used by the client when requesting a WebSocket connection. If no
         * fragment was specified, returns {@code null}. If an empty fragment was specified, returns the empty string.
         * The '#' character is never included.
         *
         * @return a fragment string, or {@code null}
         * @see Uniform Resource Identifier (URI): Generic Syntax
         */
        String fragment();
    }

    /**
     * A connection to a non-WebSocket endpoint.
     */
    public interface Connection {
        /**
         * The method (e.g. GET or POST) that the client used to request the endpoint.
         */
        String method();

        /**
         * The URI of the endpoint, including any Host header sent by the client.
         */
        URI uri();

        /**
         * The input stream through which a fallback handler can read data sent by the client.
         */
        InputStream inputStream();

        /**
         * The output stream through which a fallback handler can send data to the client.
         */
        OutputStream outputStream();

        /**
         * All header names sent by the client.
         */
        Iterable<String> headerNames();

        /**
         * The value (if present) of a header sent by the client.
         *
         * @param name case-insensitive, non-{@code null} header name
         * @return an {@code Optional} with the header value if the specified header was sent by the client,
         * otherwise an empty {@code Optional}
         */
        Optional<String> header(String name);

        /**
         * Sends an HTTP response to the client. The server will add a 'Server' header, but otherwise the fallback
         * handler needs to set all headers correctly (e.g. Content-Length).
         *
         * @param statusCode the status code
         * @param reason the status message/reason (e.g. "OK" in "200 OK"); {@code null} is treated as the empty string
         * @param headers headers to send to the client, can be {@code null} to send no headers (except Server)
         */
        void sendResponse(int statusCode, String reason, Map<String, String> headers);
    }

    /**
     * A fallback handler deals with a connection to an unknown endpoint. This makes it possible to let non-WebSocket
     * endpoints be regular HTTP endpoints, for example.
     */
    public interface FallbackHandler {
        /**
         * Handles the connection to an endpoint for which a WebSocket handler hasn't been registered.
         *
         * @param connection an object that provides access to connection details
         * @throws IOException if an I/O error occurs
         */
        void handle(Connection connection) throws IOException;
    }

    static class DefaultFallbackHandler implements FallbackHandler {
        @Override
        public void handle(Connection connection) throws IOException {
            throw new FileNotFoundException("Unknown endpoint: " + connection.uri().getPath());
        }
    }

    /**
     * A handler for a WebSocket client connection. A new handler instance will be created for each connected client.
     * Handlers are invoked on the handler executor passed to the {@code Server} constructor.
     */
    public interface WebSocketHandler {
        /**
         * Invoked right after construction.
         *
         * @param client instance for interacting with the client
         */
        void onOpened(WebSocketClient client);

        /**
         * Invoked when the client closes the connection in an orderly fashion.
         *
         * @param code the close code the client used, if any, otherwise 1000 (Normal Closure).
         * @param reason the close reason the client used, if any. May be {@code null}.
         */
        void onClosedByClient(int code, String reason);

        /**
         * Invoked when the server closes the connection in an orderly fashion, but must likely because of an error.
         *
         * @param code the close code sent to the client
         * @param reason the close reason sent to the client
         */
        void onClosedByServer(int code, String reason);

        /**
         * Invoked when the connection is closed abruptly because of an error.
         *
         * @param t the error that occurred
         */
        void onFailure(Throwable t);

        /**
         * Invoked when the client sends a text message.
         *
         * @param text the message
         */
        void onTextMessage(CharSequence text);

        /**
         * Invoked when the client sends binary data.
         *
         * @param data the data
         */
        void onBinaryData(byte[] data);
    }
}


text:
This Week in Programming: Has Facebook Forgotten about the Developers?
this-week-in-programming,
3 May 2019 3:00pm, by Mike Melanson
Do you smell that? That's right, it's the sweet smell of free t-shirts, stickers, buttons, and that oddly-flavored coffee that you only drink at a conference, because, well, it's free and plentiful. We are full swing into conference season here in the developer world and we're kicking it off this week with Facebook's F8 Developer Conference, which is where we'll focus a bit of our attention this week to start.
For those of you on the infrastructure end of things, this past week played host to both the newly-named Open Infrastructure Summit, as well as DockerCon, so make sure to check the recent posts of The New Stack to catch up on all the news there as well, but not to worry, if none of these conferences are your cup of tea — next week will likely scratch an itch. In some freak coincidence of "did nobody talk this over?" Red Hat, Microsoft and Google will all hold their conferences at pretty much exactly the same time. Red Hat goes to Boston for its annual Red Hat Summit, Microsoft holds down the fort in Seattle with Microsoft Build, and Google takes Google I/O down to Mountain View. (Oh, and don't forget about PyCon that somehow overlaps all of them, where Netflix told us all about the myriad ways it uses Python to keep us all binging that content.)
Phew. I'm exhausted just thinking about trying to keep tabs.
On day one of F8, the company talked about many things — privacy, a faster Messenger experience, Occulus Rift for the workplace — but just two things stand out. First, the company noted it would be making some changes in its Marketing API 3.3 in regards to rate limits for Pages API, Instagram, Messenger, and Ads Insights, all of which will go into effect starting July 29, 2019. I know, sexy stuff right there. Next, it announced the launch of the Facebook Developer Community Forum, which is pretty much exactly what it sounds like. I'll let TechCrunch's Frederic Lardinois handle the overall sentiment around day one:
So far, Facebook's developer conference has been about many things, but not developers. #F82019
— Frederic Lardinois (@fredericl) April 30, 2019
So, moving on to day two then! The name of the game for the second day of Facebook's developer conference was "open source" and AI/ML, as the bulk of actual announcements came around updates to PyTorch, the company's "open source deep learning platform that provides a seamless path from research prototyping to production deployment" as well as a list of newly "open-sourced tools and frameworks that simplify machine learning experimentation and optimization, speed up test execution times, and help solve memory-related performance issues."
Following its stable release of 1.0 last December, PyTorch 1.1 adds some new developer tools, such as TensorBoard, "a web application suite for inspecting and understanding training runs and graphs" that provides "first-class and native support for visualization and model debugging." In addition, the new version improves its just-in-time (JIT) compiler with "expanded capabilities in TorchScript, such as support for dictionaries, user classes, and attributes," and adds new APIs for Boolean tensors and better support for custom recurrent neural networks. The AI/ML platform also saw the addition of some collaboration tools with Google AI Platform Notebooks and Google Colab
As for new open source tools, the list includes BoTorch, a library for for Bayesian optimization (BO) research built on PyTorch, idb, an iOS development bridge to "build complex workflows so that automation on iOS can be distributed amongst a fleet of machines," Memscout, an analysis tool that can be used to quickly diagnose memory-related performance issues, and Mvfst, which offers the abilities to "stream multiplexing as a transport feature, 0-RTT connection establishment, better loss recovery, security built in from the ground up, and flexible congestion control."
Beyond that, Facebook offered some navel-gazing analysis of how it's using natural language processing to combat the hate speech and bullying that have plagued the site, working towards building inclusive AI and trying to be conscientious and ethical in its design changes. Unfortunately, as Lardinois once more points out, it did little to say how developers could do this themselves:
Facebook has talked a lot about the work it does in AI, to avoid bias, find hate speech on its platform etc. today. That's all very laudable. It is not using its keynotes to really talk about how developers can bring this to their own products, though. #f8 #f82019
— Frederic Lardinois (@fredericl) May 1, 2019
Even if F8 wasn't the feature-packed marathon of sweet developer announcements, that's okay, because, as we mentioned earlier, next week may make your head spin. Stay tuned.
This Week in Programming
Atlassian Introduces Bitbucket Cloud & Jira for VS Code: We know how much you folks love your Visual Studio Code, so we thought you might want to hear about Atlassian for VS Code, which combines three places you spend the most of your time — chat, IDE and repository. The VS Code extension pulls Jira issues into the IDE, automatically updating the status in Jira, and combines with Bitbucket for continuous feedback and delivery. With the extension, you can create and review pull requests, and initiate builds, tests and deployments with Bitbucket Pipelines. The extension is available in the VS Code Marketplace and you can find more information in the documentation.
VS Code Remote Development: A bit more Visual Studio Code news also comes this week directly from Microsoft, with the announcement of three new extensions for all of you running the Insiders build that will "enable seamless development in Containers, remotely on physical or virtual machines, and with the Windows Subsystem for Linux (WSL)." In other words, Microsoft is announcing "three new extensions for working with remote workspaces running in WSL, Docker containers, or in physical and virtual machines over SSH."
Apache Goes All-In on GitHub: The Apache Software Foundation, which counts itself as "the world's largest open source foundation, with over 200 million lines of code managed by an all-volunteer community of 730 members and 7,000 code contributors" has joined the GitHub open source community by migrating all of that code to GitHub. The move started back in 2016 and completed in February 2019. If you're interested in more of the details, make sure to give JAXEnter's interview with Bryan Clark, Director Of Product for Open Source at GitHub, a read for more details and insight.
The Nominees Are In: Google's Season of Docs has announced the participating organizations, a list of 50 organizations including the likes of Drupal, Arduino, SciPy and NumPy, FreeBSD, Wikimedia and more. And now, it will be time to choose the technical writers, who can apply starting May 29 and are eligible to a stipend for their participation. Here's to tackling that bane of every developer's existence — documentation.
I remember the days when I built my own gaming PCs. Eventually I sold out and bought a Xbox because I just wanted to play games, not build gaming rigs.
Serverless is like that.
— Kelsey Hightower (@kelseyhightower) April 30, 2019
A Look Back at Joe Armstrong and Erlang: We'll end off this week with another article by a favorite New Stack author of mine, David Cassel, who writes about Joe Armstrong's Legacy of Fault-Tolerant Computing, in memory of the Erlang creator who passed last month. Cassel notes that the language "grew out of work more than 33 years ago at the Swedish multinational telecom company Ericsson" to eventually become some ubiquitous that, "last June a presentation at the Code BEAM conference noted that every year Cisco ships about two million devices with Erlang, and that 90% of all internet traffic goes through Erlang controlled nodes." Cassel goes on to explore what gives this language its special place in the hearts of developers, taking a walk through the language's history, which he says is hiding in plain sight in all 295 pages of Armstrong's 2003 Ph.D. thesis which is titled "Making reliable distributed systems in the presence of software errors."
Culture / Development
This Week in Programming: GitHub Opens Back Up to Iran
9 Jan 2021 6:00am, by Mike Melanson
Containers / Development
This Week in Programming: Docker Previews Desktop for Mac M1
19 Dec 2020 6:00am, by Mike Melanson
Bridgecrew's 2020 Year in Review
5 Effective Ways Developers Can Support IT
What's new in Istio 1.8: Tetrate AMA Takeaways
Amazon Location – Add Maps and Location Awareness to Your Applications
We built LogDNA Templates so you don't have to
Snyk user community…3,2,1…LAUNCH!
We Replaced an SSD with Storage Class Memory. Here is What We Learned.
Join us at our new blog home

redpajama_set_name: RedPajamaCommonCrawl


composition: reference common parts as external entities.
Batch job xml inheritance is not included in JSR 352 Batch Spec 1.0. JBeret implements JSL inheritance based on the draft JSL Inheritance v1. Refer to that document for inheritance rules and restrictions. Note that this is an experimental feature and may undergo significant changes in future releases.
Here are some examples illustrating how to use JSL inheritance with JBeret.
Parent elements (step, flow, etc) are marked with attribute abstract = "true" to exclude them from direct execution. Child elements contains parent attribute, which points to the parent element.
Child elements (step, job, etc) contain a jsl-name attribute, which specifies the job xml name (without .xml extension) containing the parent element.
The target file of the entity (job-segment.xml in the above example) should be accessible and loadable by JBeret batch runtime, and typically reside in the same location as the referencing job xml (job-with-xml-entities.xml in the above example).


Senior Advertising and PR will need to be very proactive in developing the overall fragrance and cosmetic exposures in the media both traditional and digital/SNS to increase the fragrance and cosmetic customer demand.
* Make smooth collaboration internally with brand management team.
Cosmetic and Fragrance Company with Multiple brands with high Customer awareness. Very strong in Asia and US. Several Direct stores and shop-in-shops in Japan.


Super hosts, Lady Captain Yvonne, President Ken and members of Silecroft Golf Club for the 5-Club Final.
40 Ladies took part on a breezy summer day.
Winner was Val Kirkwood from Furness Golf Club with 77 nett, Second was Naomi Brennan from Seascale Golf Club with 78 nett and Third was Mary Dodd from Brampton Golf Club with 79 nett.
Many thanks to Silecroft Golf Club for hosting the compettiion.
Check out the Cumbria Sail!"


For those of you involved with this season's U13-18 Division, you are already aware that the teams were broken up for the most part by age. 2 teams are comprised exclusively of U13-15 players, a 3rd team is predominantly U13-15 players, and the 4th team is comprised of U15-U17 players. Furthermore, although these teams currently play against other neighboring towns (Manalapan, OId Bridge, etc.), the opposing teams have likewise been sorted according to age as much as possible.
It is our desire to make a more formal division of age groups in future seasons. However, to help us meet that goal, we need to continue our recent increases in player registration for those age groups. We need today's players to recruit their friends to join the Club - with increased numbers come increased opportunity for us to group players more appropriately by age. Thank you for your help.


text:
Bernard Anício Caldeira Duarte (født 8. september 1992), bedre kendt som Bernard, er en professionel fodboldspiller fra Brasilien. Han spiller for Everton, som kant.

Referencer

Eksterne henvisninger

Fodboldspillere fra Brasilien
Fodboldspillere fra Atletico Mineiro
Fodboldspillere fra Democrata Futebol Clube
Fodboldspillere fra FC Shakhtar Donetsk
Personer fra Belo Horizonte

redpajama_set_name: RedPajamaWikipedia


My name is Daniel de Luca, and I'm a Game Development student at the HvA.
On this website you can view different projects of mine, which are all made in Unity3D.
After this semester I will do my final internship and write a thesis.
FishyFishy is a simple game which mainly focuses on the learning part.
You get an English word, and underneath 3 Japanese words. The Japanese user has to press the correct Japanese corresponding word. The player gains "Fishpoints" after every correct word, which the player can buy fish with for their virtual aquarium (which are more popular in Japan than in the west).
This game is created by two Japanese students and me.
You can see the prototype here.
Magnetic Duo is another local multiplayer game, but this time it's a puzzle game!
while the other player can push blocks, and turn them around.
With these two simple mechanics, it's possible to make many levels to enjoy at your own pace.


exquisite bedroom set. Listed below are a few of top rated exquisite bedroom set pics on internet. We identified it from reliable resource. Its posted by admin in the best field. We think this exquisite bedroom set photo could possibly be the most trending topic if we distribute it in google plus or facebook.
We attempt to introduced in this posting since this can be one of great resource for any exquisite bedroom set options. Dont you come here to know some new unique exquisite bedroom set idea? We really hope you can easily recognize it as one of your reference and many thanks for your free time for exploring our blog. Please share this picture for your precious mates, families, society via your social websites such as facebook, google plus, twitter, pinterest, or other social bookmarking sites.
Aarons Rent To Own Bedroom Sets Rent Own King Size Bedroom Sets .
House Endearing White Bedroom Dresser 38 Modern Ideas Dressers And .
B188 63n Ashley Furniture Exquisite White Twin Sleigh Bed .
B188 26 Ashley Furniture Exquisite White Bedroom Bedroom Mirror .
Ashley Exquisite Twin Over Twin Trundle Bed Set .
Exquisite Poster Bedroom Set Signature Design By Ashley FurniturePick .
Signature Design By Ashley Exquisite Youth Poster Bedroom Set .
Exquisite Poster Bedroom Set From Ashley ASL B188 71 82N Coleman .
Exquisite Bedroom Set Jennifer Furniture .
Exquisite Youth Sleigh Bedroom Set .
Ashley Exquisite Youth Canopy Bedroom Set YouTube .
Ashley Exquisite Youth Bedroom Set YouTube .
Exquisite Full Size Sleigh Bed Ashley Furniture .
Amazon Com Exquisite Youth Twin Size Poster Bed Room Set In White .
Signature Design By Ashley Exquisite Ornate Arched Bedroom Mirror .
Ashley Signature Design Exquisite B188 Girls Bedroom Furniture For .
FurnitureETC Furniture More Exquisite Trundle Poster Bedroom Set .
Buy Exquisite Bedroom Desk And Hutch By Signature Design From Www .
Exquisite Full Poster Bed Ashley Furniture HomeStore .
Exquisite Full Size Poster Bed Beds Ashley Furniture .
30 Lovely Exquisite Bedroom Set Luxury Best Bedroom Design Ideas .
Exquisite Bed Ashley Furniture Modern Home Furniture Check More At .
Ashley Furniture Exquisite Double Dresser B188 21 Kids Double .
Amazon Com Exquisite Youth Full Size Sleigh Bed Room Set In White .
Exquisite Headboard Bedroom Set Signature Design By Ashley Furniture .
Bedroom Exquisite Sleigh Set Signature Design Youth .
Bisini Luxury Furniture Bed Exquisite Bedroom Furniture King Size .
Exquisite Youth Bedroom Set Scifipie Me .
Signature Design By Ashley Exquisite B188 46 5 Drawer Chest Del .
Granite Top Bedroom Furniture Sets Granite Top Bedroom Set Exquisite .
Elegant Wooden Bedroom Furniture Exquisite Wood Carved Bedroom Set .
Luxury Bed With Noble Quality And Exquisite Carving Process .
Ashley Furniture Exquisite Bedroom Set With Regard To Warm Bedroom .
Exquisite Bedroom Set Photos And Video WylielauderHouse Com .
Contemporary Wood Bedroom Furniture And Exquisite Wood Modern Master .
Exquisite Bedroom Set Bedroom Design Ideas .
Exquisite Poster Bedroom Set Apartmany Anton .
Bedroom Set Pieces Names Furniture Names Exquisite Names Of Bedroom .
Bedroom Gorgeous Lea Romance Panel Bedroom Set With Exquisite Wood .
Ashley Exquisite Bedroom Set Photos And Video WylielauderHouse Com .
Exquisite Timber Beds Furniture Set Royal Style Wooden Bedroom Set .
Women Bedroom Furniture Exquisite Poster Bedroom Set Exquisite .
Charming Exquisite Bedroom Set 24 Callysbrewing .
Ashley Furniture Homestore Exquisite Poster Bedroom Set Intended For .
Bedroom Mdf Bedroom Furniture Charming On Intended Suppliers And 12 .
Ashley Furniture Exquisite Bedroom Set Redhome Info .
Glamorous White Distressed Bedroomrniture Antique Exquisite Creative .
Cheap King Bedroom Sets With Exquisite Cheap King Bedroom Sets In .
Bedroom Celine 6 Piece Mirrored And Upholstered Tufted Queen Size .
Exquisite Bedroom Set Home Design Ideas Ikea Duckdns Org .
Exquisite Early 20th Century Art Nouveau Bedroom Set .
Interior Exquisite White Queen Bedroom Set 29 B196 31 36 46 57 92 .
Bathroom Awesome Exquisite Bedroom Set Design Ideas Modern Fresh .
Ashley Furniture Twin Bed Sets 5 Exquisite Twin Sleigh Bed By .
Kids Desks Ashley Furniture HomeStore .
Exquisite Distressed White Bedroom Furniture 19 DIY Futbol51 Com .
Happy Shabby Chic Bedroom Sets Exquisite Sheek Bedrooms 18 Special .
Bedroom Beautiful Ashley Bedroom Sets Ashley Furniture Bedroom .
Bedroom Timberline Bedroom Set From Ashley B258 Coleman Furniture .
Mirrored Tufted Bed Bedroom Exquisite Mirror With Ornamental Metal .
Glorious Wooden Bedroom Furniture Exquisite Hand Painting Princess .
Bedroom Willa Arlo Interiors Alasdair Mirrored Tufted Platform 3 .
Cool Cute Bedroom Furniture Charming Boys Full Size Of .
Exquisite Twin Sleigh Bed Ashley Furniture .
Exquisite Ideas Designer Bedroom Furniture Sets Luxury Bedroom .
Exquisite Full Size Poster Bed By Ashley Furniture White Poster Bed .
Delightful Exquisite Bedroom Sets With Storage Monroe King Storage .
Www Conns Furniture Payment Phone Exquisite Bedroom Set Best Ideas .
Bedroom Set Up Plain Master Bedroom Setup Intended Exquisite On .
Scandinavian Bedroom Sets Scan Design Bedroom Furniture Bedroom Set .
Luxurious Bedroom Furniture Luxury Bedroom Sets Interior Design .
Sofia Vergara Bedroom Collection Furniture Collection Sofia Vergara .
Queen Sleigh Bed Ashley Anarasia Assembly Instructions Bedroom Set .
Scandinavian Bedroom Furniture Large Size Of Bedroom Furniture Ideas .
Raymour And Flanigan Bedroom Sets With Exquisite Raymour And .
Canales Furniture Creative Exquisite King Bedroom Sets King Bedroom .
Furniture Exquisite Full Size White Canopy Bed 39 Girls Bedroom .


Despite its exciting premise of Jules Verne-inspired nautical adventuring, sea monsters and mechanical leviathans, Diluvion sank out of sonar range shortly after launching early last year – yesterday, it resurfaced under an expanded name. While a striking looking game, it got depth-charged by negative reviews, with complaints about wonky UI and some underdeveloped systems. Developers Arachnid Games have been patching holes ever since. Boasting major improvements, it's currently 75% discounted. Below, a fresh trailer for the new 'Resubmerged' version.
From the little bit I had to play, it's three quarters 3D claustrophobic 'light' submarine sim, one quarter I struggle to define. As a salvager, you make most of your money finding wrecked structures or ships, boarding them and poking around to find loot. This is handled ingeniously by zooming in to a hand-drawn 2D cutaway view of the vessel you're searching, and you manually click your way through crates and doorways to explore and plunder. You'll also occasionally meet enemies in these wrecks, and your crew need to engage in turn-based RPG style combat to proceed.
Crew management and dialogue work this way too, dragging and dropping crew-members to their ship stations, with backup crew handling repairs and boarding. In friendlier environments, you can trade salvage for gear and additional crew, slowly cluttering up your submarine as far as your (upgradable) life support will allow. If there's one thing I have to grumble about in my limited time playing so far, it's the writing – it just feels a little dry and hollow, which stands out against the brightly coloured haze of its weird ocean world. I'm hoping to play more soon.
As I missed out on Diluvion first time round, I've little point of reference as to what they've added to it. Among the bigger changes listed are a major overhaul to UI, salvaging and the ship upgrade system. There's new quests, smarter enemies, and a new save system – previously checkpoint-based, but now you can update your captain's log whenever you see fit. It's good to see Arachnid didn't give up on this one – it feels too special to just leave to the barnacles.
Diluvion: Resubmerged is available on GOG for £3.74, and the Fleet Edition (including soundtrack, artbook and a bonus submarine) costs £4.74/€6.24/$6.24 on Steam.
Tagged with arachnid games, Good Shepherd Entertainment, Diluvion, Diluvion: Resubmerged.


text:
Little Owls
Gardens & Woodland
Moors And Mountains
Misc Mammals
Mull Workshops
Highlands Workshops
Mull Garden Bird List
Mull Visitor Guide
Seeing your first white-tailed eagle is unforgettable. Mine was during a trip to Skye, from a small boat bobbing around just outside the shelter of Portree Harbour, in the pouring rain. The eagle was sat in a tree on the side of some steep cliffs, and was tempted down to our boat after the skipper threw a fish overboard. Massive wings unfolded and it drifted down towards us, circling briefly before swooping down at a pace that defied the size of the bird, to snatch the fish from the surface, and powerfully flew back to those cliffs once more. The whole sequence was over in a matter of seconds, but I was smitten already.
Since then I have spent hours watching and photographing these majestic birds, and never grow tired of any sighting of them, be it a distant speck drifting over a mountain or one perching up on a rocky outcrop beside a loch, only a few dozen yards from my car.
Unlike golden eagles, that can in certain situations resemble buzzards, white-tailed eagles are unmistakeable. The breadth of their massive wings make them very easy to identify in flight, and provide ample reason for their nickname of "flying barn doors".
Fully mature adults have the characteristic white tail, and the feathers on their head can be paler too. Not quite the white colour of a bald eagle, but apparent in comparison to the rest of the bird.
The beak is also enormous - considerably larger than the golden eagle's and must be perfect for tearing up the carrion and fish that make up the majority of their diet.
It is difficult to gauge how huge the eagles are though. And how strong they are. One experience sticks in my mind for this, and again was on Skye. It was the last of our boat trips, and the eagles weren't coming down to the fish being thrown out for them. Knowing we were on our last trip, and appreciating that we'd been on several over a couple of days, the skipper collected the small fish that had been thrown, and disappeared into the cabin to get something larger.
Appearing with a ling, which was as long as the skipper was tall, he then launched this more appealing meal into the water, and waited. This was obviously worth the effort for the eagle, and down it came at last. The skipper had had to hold the fish with both hands, and it'd taken quite some effort to hurl it over into the sea. The eagle snatched the fish, with just one foot, its long sharp talons gripping it securely, and as it had with much smaller fish, it flew off back to the nest area again. It was this sight, the size of the eagle's foot carrying something that had been so enormous on the boat, that rammed it home just how massive these eagles are.
Even as youngsters, they are huge. I recently photographed a fledgling on the Isle Of Mull, that was a mere four months old, yet it was as large as the adult birds and capable of flying low and skillfully along the shore, or soaring so high into the sky that it vanished from sight.
When leaving the nest, the young eagles are mostly brown in colour, with dark brown heads, tails and primary feathers. Their beaks are also dark tipped, though no smaller than the adults!
Like many birds of prey, white-tailed eagles are lazy and prefer to wait for food to present itself to take advantage of, rather than chase it down and kill it for itself. Carrion forms a large proportion of their diet. Soaring over the hills and scanning the shore, coupled with their incredible eyesight helps them spot opportunities from afar.
That said, they will take fish from the water, and while slightly artificial, this can be witnessed at close quarters from the boat trips, such as Mull Charters. It should be noted that this "feeding" is done in a controlled manner, to ensure that the eagles do not become dependant on the boat trips for their food. Something apparent on trips where the eagles fail to come out to the boat, as they already have food available, perhaps from a carcass or prey caught earlier.
To see the eagles hunting in the wild is breathtaking. I have witnessed this on a number of occasions on Mull, and it is something truly special to see.
When hunting alone, the eagles will make use of the weather. I have been out on days when the clouds are lying only a couple of hundred feet above the ground, and spotted the eagles hanging in the breeze, just touching the clouds, using them to hide their presence. From this lofty, shrouded position, they can swoop down in a matter of seconds to grab prey.
And the prey can be surprising too. I have seen them go for geese and grey herons, plus pheasants seem to be a popular snack. Mountain hares and rabbits are part of their diet, and of course fish too. I have even seen one chase a gannet across a loch one misty morning. The power and speed of the eagle in pursuit was startling, and the gannet had to fly at top speed to make its escape.
I remember watching in awe as they hunted as a pair. Sat in my car hoping for views of hen harriers, I was keeping a vigil on anything moving around the marsh area. Hence I noticed when a white-tailed eagle sailed over me, and headed towards the flocks of geese feeding on the grass beside the river. All hell broke loose, as the birds also saw this hunter approaching but the eagle didn't dive for anything. No, it was merely creating the chaos for its partner to make the most of. Enter stage left, low down, skimming the tops of the long grass and reeds, came the partner, like a missile to pin down a young grey heron caught up in the confusion.
After subduing the leggy prey, it was carried back to the nest nearby for a youngster to tear to pieces, no doubt.
One year I watched a pair of white-tailed eagles taking advantage of a boom in fish populations. Whitebait numbers were up and hence the waters around the Isle Of Mull were heaving with mackerel. Chasing the whitebait into the lochs, both species were drowning in the fresh water, and when the tide retreated, the fish were being washed up on the shore or left in pools on the rocks.
They're not fools, these eagles. They found themselves a good viewpoint in a tall conifer, and watched the gulls below. With every lapping wave on the shore came another dead fish, and the gulls would drag fish worth scavenging ashore to eat. Anything of a decent size would attract the attention of the larger gulls, and in turn, caught the eagle's eyes. And that would be enough for the eagle to swoop down, to steal the fish from the rather annoyed gulls.
This theft of food is common and otters are also watched by the eagles, and can have their spoils stolen if they're not careful with it.
White-tailed eagle picking up dead fish on retreating tide
As mentioned above, the isles of Mull and Skye are hotspots for seeing white-tailed eagles, as is most of the West Coast of Scotland. There is also now a growing population on the East Coast of Scotland (around Fife), after reintroduction projects proved to be successful there too. Individuals are occasionally seen south of the border, usually juveniles along coasts. But they never seem to stay for long.
Spotting them can be made easier if there are flocks of birds around, such as geese or gulls. If they all suddenly go up in a mass panic, it's often because a white-tailed eagle is in the area.
They also like to sit beside the shore on rocks or even on the beach, waiting to see what the tide might leave for them. Despite their immense size, they can be easy to miss when sat on a beach, as they blend in so well with the surroundings.
In flight, well, just look for something akin to a barn door drifting across the sky...
White-tailed eagle taking a fish
Photographing White-Tailed Eagles
Without doubt the best way to photograph these magnificent eagles is from one of the boat trips that attract them in close. Provided the eagles take the bait, and come out, then you're guaranteed to at least see them at close quarters. Getting a photograph isn't quite as simple as it seems, as despite being huge, they're not slow.
It can be only a few seconds between the eagle circling over the boat, to it diving, taking and flying away with the fish.
Choice of lens, exposure and focusing modes can make a huge difference to what images you come away with. And to make things trickier, the weather, lighting and movement of the boat all play a part. I've been on a couple of trips where it has been a challenge to remain standing up, let alone track the eagle descending like a bullet to take the fish.
As I have been on so many of these trips now, I can offer advice on how to capture images, and two of these trips feature in the Mull Summer Photo Tours I co-run each year. They're definitely the highlight for me, as I guess may also be the case for some of the clients too.
Aside from the boat trips, great views can be had on dry land, if you choose to visit an eagle watchpoint. Here, a Guide will lead you to a safe (for the eagle) viewing point to look at perhaps the nest or any perched adults nearby.
From close encounters on land or at sea, distant views of them soaring on thermals or hunting low down, from adults expertly picking huge slippery fish from the water to fledglings battling to peck a morsel of meat from an old carcass, watching and admiring white-tailed eagles is something to be treasured, and is something I will never take for granted.
info@petewalkden.co.uk
Flickr – Latest Images


text:
Q: jQuery function not acting like I would expect I have the following jQuery code:
//The user clicked on a species to delete it. We need to use event delegation because items are added dynamically.
$('#speciesAdded').on('click', 'li', function (event) {

    // Let's make sure this is what the user wants to do?
    alertify.confirm("Do you wish to delete the sighting?", function (e) {
        if (e) {
            // User clicked Ok - No need to do anything

        } else {
            // User clicked cancel
            return;
        }
    });

    alert("Howdy!");

    ...
    ...
});

When this fires the JavaScript alert dialog appears at the same time as the alertify confirmation dialog. In other words, the code occurring after the alertify executes before the user even has a chance to confirm the action. I'm not sure what's going on here How can I prevent this?

A: I think you want to put your alert method call inside the confirm callback...
$('#speciesAdded').on('click', 'li', function (event) {

    // Let's make sure this is what the user wants to do?
    alertify.confirm("Do you wish to delete the sighting?", function (e) {
        if (e) {
            // User clicked Ok - No need to do anything
            // Do something on okay
            alert("Howdy!");
            ...
             ...
        } else {
            // User clicked cancel
            //
            return;
        }

    });

});

redpajama_set_name: RedPajamaStackExchange