Search in sources :

Example 46 with Endpoint

use of javax.websocket.Endpoint in project component-runtime by Talend.

the class WebsocketClient method read.

public <T> T read(final Class<T> response, final String method, final String uri, final String body, final String type) {
    final WebSocketContainer container = ContainerProvider.getWebSocketContainer();
    final CountDownLatch latch = new CountDownLatch(1);
    final AtomicReference<String> indexHolder = new AtomicReference<>();
    final ClientEndpointConfig clientEndpointConfig = ClientEndpointConfig.Builder.create().build();
    clientEndpointConfig.getUserProperties().put("org.apache.tomcat.websocket.IO_TIMEOUT_MS", "60000");
    final Session session;
    try {
        session = container.connectToServer(new Endpoint() {

            @Override
            public void onOpen(final Session session, final EndpointConfig endpointConfig) {
                final StringBuilder builder = new StringBuilder();
                session.addMessageHandler(ByteBuffer.class, new MessageHandler.Partial<ByteBuffer>() {

                    @Override
                    public synchronized void onMessage(final ByteBuffer part, final boolean last) {
                        try {
                            builder.append(new String(part.array()));
                        } finally {
                            if (builder.toString().endsWith("^@")) {
                                indexHolder.set(builder.toString());
                                doClose(session);
                            }
                        }
                    }
                });
            }

            @Override
            public void onClose(final Session session, final CloseReason closeReason) {
                latch.countDown();
            }

            @Override
            public void onError(final Session session, final Throwable throwable) {
                latch.countDown();
                if (session.isOpen()) {
                    doClose(session);
                }
                fail(throwable.getMessage());
            }

            private void doClose(final Session session) {
                try {
                    session.close(new CloseReason(CloseReason.CloseCodes.GOING_AWAY, "bye bye"));
                } catch (final IOException e) {
                    fail(e.getMessage());
                }
            }
        }, clientEndpointConfig, URI.create("ws://localhost:" + config.getHttpPort() + "/websocket/v1/bus"));
    } catch (final DeploymentException | IOException e) {
        fail(e.getMessage());
        throw new IllegalStateException(e);
    }
    try {
        final RemoteEndpoint.Async asyncRemote = session.getAsyncRemote();
        final String payload = "SEND\r\ndestination:" + uri + "\r\ndestinationMethod:" + method + "\r\nAccept: " + type + "\r\nContent-Type: " + "application/json\r\n\r\n" + body + "^@";
        asyncRemote.sendBinary(ByteBuffer.wrap(payload.getBytes(StandardCharsets.UTF_8)));
        latch.await(1, MINUTES);
    } catch (final InterruptedException e) {
        Thread.interrupted();
        fail(e.getMessage());
    }
    try {
        final String index = indexHolder.get();
        assertTrue(index.startsWith("MESSAGE\r\n"), index);
        assertTrue(index.contains("Content-Type: " + type + "\r\n"), index);
        final int startJson = index.indexOf('{');
        final int endJson = index.indexOf("^@");
        assertTrue(startJson > 0, index);
        assertTrue(endJson > startJson, index);
        if (String.class == response) {
            return response.cast(index.substring(startJson, endJson));
        }
        try (final Jsonb jsonb = JsonbProvider.provider().create().build()) {
            final T ci = jsonb.fromJson(index.substring(startJson, endJson), response);
            assertNotNull(ci);
            return ci;
        } catch (final Exception e) {
            fail(e.getMessage());
            throw new IllegalStateException(e);
        }
    } finally {
        if (session.isOpen()) {
            try {
                session.close(new CloseReason(CloseReason.CloseCodes.GOING_AWAY, "bye bye"));
            } catch (IOException e) {
                fail(e.getMessage());
            }
        }
    }
}
Also used : MessageHandler(javax.websocket.MessageHandler) Jsonb(javax.json.bind.Jsonb) Endpoint(javax.websocket.Endpoint) RemoteEndpoint(javax.websocket.RemoteEndpoint) CloseReason(javax.websocket.CloseReason) ClientEndpointConfig(javax.websocket.ClientEndpointConfig) WebSocketContainer(javax.websocket.WebSocketContainer) AtomicReference(java.util.concurrent.atomic.AtomicReference) RemoteEndpoint(javax.websocket.RemoteEndpoint) IOException(java.io.IOException) CountDownLatch(java.util.concurrent.CountDownLatch) ByteBuffer(java.nio.ByteBuffer) Endpoint(javax.websocket.Endpoint) RemoteEndpoint(javax.websocket.RemoteEndpoint) DeploymentException(javax.websocket.DeploymentException) IOException(java.io.IOException) DeploymentException(javax.websocket.DeploymentException) ClientEndpointConfig(javax.websocket.ClientEndpointConfig) EndpointConfig(javax.websocket.EndpointConfig) Session(javax.websocket.Session)

Example 47 with Endpoint

use of javax.websocket.Endpoint in project groovity by disney.

the class Ws method tag.

@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public Object tag(Map attributes, Closure body) throws Exception {
    Object url = resolve(attributes, URL);
    if (url == null) {
        throw new RuntimeException("ws() requires 'url' attribute");
    }
    ScriptHelper context = getScriptHelper(body);
    Map variables = context.getBinding().getVariables();
    URI uri;
    URIBuilder builder;
    ArrayList<Header> headers;
    Function handlerFunction;
    Optional<UserPass> userPass;
    Optional<HttpSignatureSigner> signer;
    final AtomicReference openMessage = new AtomicReference<>();
    try {
        builder = new URIBuilder(url.toString());
        bind(context, Uri.CURRENT_URI_BUILDER, builder);
        headers = new ArrayList<Header>();
        bind(context, com.disney.groovity.tags.Header.CURRENT_LIST_FOR_HEADERS, headers);
        Credentials.acceptCredentials(variables);
        Signature.acceptSigner(variables);
        Object oldOut = get(context, OUT);
        StringWriter sw = new StringWriter();
        Object rval = null;
        bind(context, OUT, sw);
        try {
            rval = body.call();
            if (rval instanceof Writable) {
                ((Writable) rval).writeTo(sw);
            }
        } finally {
            bind(context, OUT, oldOut);
            userPass = Credentials.resolveCredentials(variables);
            signer = Signature.resolveSigner(variables);
        }
        String val = sw.toString().trim();
        if (val.length() > 0) {
            openMessage.set(val);
        } else if (rval != null) {
            openMessage.set(rval);
        }
        uri = builder.build();
        handlerFunction = (Function) get(body, Handler.HANDLER_BINDING);
    } catch (URISyntaxException e1) {
        throw new RuntimeException("Invalid URI " + url, e1);
    } finally {
        unbind(context, Uri.CURRENT_URI_BUILDER);
        unbind(context, com.disney.groovity.tags.Header.CURRENT_LIST_FOR_HEADERS);
        unbind(context, Handler.HANDLER_BINDING);
    }
    final Closure closer = resolve(attributes, CLOSE, Closure.class);
    final Closure errorHandler = resolve(attributes, ERROR, Closure.class);
    final Class messageFormat = resolve(attributes, MESSAGE, Class.class);
    final Integer timeout = resolve(attributes, TIMEOUT, Integer.class);
    final AtomicReference<WebSocket> socket = new AtomicReference<>();
    ClientEndpointConfig.Builder configBuilder = ClientEndpointConfig.Builder.create();
    Session session;
    try {
        session = getContainer().connectToServer(new Endpoint() {

            @Override
            public void onOpen(Session session, EndpointConfig config) {
                try {
                    openCount.incrementAndGet();
                    if (timeout != null) {
                        session.setMaxIdleTimeout(timeout * 1000);
                    }
                    WebSocket ws = new WebSocket(session);
                    socket.set(ws);
                    ws.setName(uri.toString());
                    if (handlerFunction != null) {
                        ws.setMessageHandler(arg -> {
                            synchronized (handlerFunction) {
                                handlerFunction.apply(arg);
                            }
                        }, messageFormat);
                    }
                    if (openMessage.get() != null) {
                        ws.call(openMessage.get());
                    }
                } catch (Exception e) {
                    log.log(Level.SEVERE, "Error opening web socket session " + uri, e);
                }
            }

            @Override
            public void onClose(Session session, CloseReason reason) {
                try {
                    closeCount.incrementAndGet();
                    openSessions.remove(session);
                    if (closer != null) {
                        if (closer.getMaximumNumberOfParameters() > 0) {
                            closer.call(reason);
                        } else {
                            closer.call();
                        }
                    }
                } catch (Exception e) {
                    log.log(Level.SEVERE, "Error closing web socket session " + uri, e);
                }
            }

            @Override
            public void onError(Session session, Throwable th) {
                try {
                    errorCount.incrementAndGet();
                    if (errorHandler == null) {
                        throw th;
                    }
                    errorHandler.call(th);
                } catch (Throwable e) {
                    Level logLevel = Level.WARNING;
                    if (th != e) {
                        log.log(logLevel, "Error handling error for web socket session " + uri, e);
                    } else if (th instanceof IOException) {
                        logLevel = Level.FINE;
                    }
                    log.log(logLevel, "WebSocket client error: " + uri, th);
                }
            }
        }, configBuilder.configurator(new ClientEndpointConfig.Configurator() {

            public void beforeRequest(Map<String, List<String>> reqHeaders) {
                // copy programmatic headers
                for (Header header : headers) {
                    List<String> hl = reqHeaders.get(header.getName());
                    if (hl == null) {
                        hl = new ArrayList<>();
                        reqHeaders.put(header.getName(), hl);
                    }
                    hl.add(header.getValue());
                }
                Map<String, Map<String, String>> allChallenges = null;
                if (userPass.isPresent() || signer.isPresent()) {
                    allChallenges = getChallenges(uri, reqHeaders);
                }
                if (userPass.isPresent()) {
                    UserPass user = userPass.get();
                    if (allChallenges != null) {
                        List<String> auths = reqHeaders.get(AUTHORIZATION_HEADER);
                        if (auths == null) {
                            auths = new ArrayList<>();
                            reqHeaders.put(AUTHORIZATION_HEADER, auths);
                        }
                        if (allChallenges.containsKey("basic")) {
                            StringBuilder authBuilder = new StringBuilder(user.getUser());
                            authBuilder.append(":");
                            char[] pass = user.getPass();
                            for (char c : pass) {
                                authBuilder.append(c);
                            }
                            try {
                                auths.add("Basic " + printBase64Binary(authBuilder.toString().getBytes("UTF-8")));
                            } catch (UnsupportedEncodingException e) {
                                log.severe(e.getMessage());
                            }
                        }
                        if (allChallenges.containsKey("digest")) {
                            final String digestUri = uri.getPath() + ((uri.getRawQuery() != null) ? "?" + uri.getRawQuery() : "");
                            Map<String, String> digestChallenge = allChallenges.get("digest");
                            if (log.isLoggable(Level.FINE)) {
                                log.fine("Generating digest auth for " + digestChallenge.toString());
                            }
                            DigestAuthorization digestAuth = new DigestAuthorization();
                            digestAuth.setUsername(user.getUser());
                            digestAuth.setQop("auth");
                            digestAuth.setCnonce(String.valueOf(ThreadLocalRandom.current().nextLong(10000000, 999999999999l)));
                            digestAuth.setNonceCount("000001");
                            digestAuth.setUri(digestUri);
                            for (Entry<String, String> entry : digestChallenge.entrySet()) {
                                String k = entry.getKey();
                                String v = entry.getValue();
                                if ("nonce".equalsIgnoreCase(k)) {
                                    digestAuth.setNonce(v);
                                } else if ("realm".equalsIgnoreCase(k)) {
                                    digestAuth.setRealm(v);
                                } else if ("opaque".equalsIgnoreCase(k)) {
                                    digestAuth.setOpaque(v);
                                }
                            }
                            String signingString;
                            try {
                                signingString = digestAuth.generateSigningString(user.getUser(), new String(user.getPass()), new AuthorizationRequest() {

                                    @Override
                                    public String getURI() {
                                        return digestUri;
                                    }

                                    @Override
                                    public String getMethod() {
                                        return "GET";
                                    }

                                    @Override
                                    public List<String> getHeaders(String name) {
                                        return reqHeaders.get(name);
                                    }
                                });
                                MessageDigest md5 = MessageDigest.getInstance("MD5");
                                digestAuth.setDigest(md5.digest(signingString.toString().getBytes()));
                                if (log.isLoggable(Level.FINE)) {
                                    log.fine("Generated digest auth " + digestAuth.toString());
                                }
                                auths.add(digestAuth.toString());
                            } catch (NoSuchAlgorithmException e) {
                                log.severe("Missing MD5 " + e.getMessage());
                            }
                        }
                    }
                }
                if (signer.isPresent()) {
                    if (allChallenges.containsKey("signature")) {
                        HttpSignatureSigner sig = signer.get();
                        HttpGet signReq = createRequest(uri, reqHeaders);
                        List<Header> beforeHeaders = Arrays.asList(signReq.getAllHeaders());
                        try {
                            sig.process(signReq, null);
                        } catch (HttpException | IOException e) {
                            log.log(Level.SEVERE, "Error processing http signature", e);
                        }
                        Header[] afterHeaders = signReq.getAllHeaders();
                        for (Header h : afterHeaders) {
                            if (!beforeHeaders.contains(h)) {
                                List<String> hl = reqHeaders.get(h.getName());
                                if (hl == null) {
                                    hl = new ArrayList<>();
                                    reqHeaders.put(h.getName(), hl);
                                }
                                hl.add(h.getValue());
                                if (log.isLoggable(Level.FINE)) {
                                    log.fine("Copied HTTP signature header " + h);
                                }
                            }
                        }
                    }
                }
            }
        }).build(), uri);
    } catch (Exception e) {
        errorCount.incrementAndGet();
        throw e;
    }
    openSessions.add(session);
    String var = resolve(attributes, VAR, String.class);
    if (var != null) {
        context.getBinding().setVariable(var, socket.get());
    }
    return socket.get();
}
Also used : AuthorizationRequest(com.disney.http.auth.AuthorizationRequest) Writable(groovy.lang.Writable) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) Endpoint(javax.websocket.Endpoint) CloseReason(javax.websocket.CloseReason) MessageDigest(java.security.MessageDigest) UnsupportedEncodingException(java.io.UnsupportedEncodingException) URIBuilder(org.apache.http.client.utils.URIBuilder) Header(org.apache.http.Header) Level(java.util.logging.Level) ScriptHelper(com.disney.groovity.util.ScriptHelper) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) LinkedHashMap(java.util.LinkedHashMap) Closure(groovy.lang.Closure) HttpGet(org.apache.http.client.methods.HttpGet) URISyntaxException(java.net.URISyntaxException) URI(java.net.URI) Function(java.util.function.Function) StringWriter(java.io.StringWriter) HttpSignatureSigner(com.disney.http.auth.client.signer.HttpSignatureSigner) HttpException(org.apache.http.HttpException) ClientEndpointConfig(javax.websocket.ClientEndpointConfig) DigestAuthorization(com.disney.http.auth.DigestAuthorization) UserPass(com.disney.groovity.tags.Credentials.UserPass) AtomicReference(java.util.concurrent.atomic.AtomicReference) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) HttpException(org.apache.http.HttpException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) IOException(java.io.IOException) ClientEndpointConfig(javax.websocket.ClientEndpointConfig) EndpointConfig(javax.websocket.EndpointConfig) Session(javax.websocket.Session)

Aggregations

Endpoint (javax.websocket.Endpoint)47 Session (javax.websocket.Session)30 URI (java.net.URI)25 EndpointConfig (javax.websocket.EndpointConfig)25 ServerEndpointConfig (javax.websocket.server.ServerEndpointConfig)20 AtomicReference (java.util.concurrent.atomic.AtomicReference)19 ServerWebSocketContainer (io.undertow.websockets.jsr.ServerWebSocketContainer)14 UndertowSession (io.undertow.websockets.jsr.UndertowSession)14 AnnotatedClientEndpoint (io.undertow.websockets.jsr.test.annotated.AnnotatedClientEndpoint)14 FrameChecker (io.undertow.websockets.utils.FrameChecker)14 WebSocketTestClient (io.undertow.websockets.utils.WebSocketTestClient)14 IOException (java.io.IOException)14 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)14 FutureResult (org.xnio.FutureResult)14 ClientEndpointConfig (javax.websocket.ClientEndpointConfig)13 MessageHandler (javax.websocket.MessageHandler)12 ByteBuffer (java.nio.ByteBuffer)11 ServerEndpoint (javax.websocket.server.ServerEndpoint)11 CountDownLatch (java.util.concurrent.CountDownLatch)10 ClientEndpoint (javax.websocket.ClientEndpoint)10