All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.tyrus.client.ClientManager Maven / Gradle / Ivy

There is a newer version: 2.2.0
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 2011-2013 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * http://glassfish.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
package org.glassfish.tyrus.client;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

import javax.websocket.ClientEndpoint;
import javax.websocket.ClientEndpointConfig;
import javax.websocket.DeploymentException;
import javax.websocket.Endpoint;
import javax.websocket.Extension;
import javax.websocket.HandshakeResponse;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;

import org.glassfish.tyrus.core.AnnotatedEndpoint;
import org.glassfish.tyrus.core.BaseContainer;
import org.glassfish.tyrus.core.ComponentProviderService;
import org.glassfish.tyrus.core.EndpointWrapper;
import org.glassfish.tyrus.core.ErrorCollector;
import org.glassfish.tyrus.core.ReflectionHelper;
import org.glassfish.tyrus.core.TyrusContainerProvider;
import org.glassfish.tyrus.spi.SPIHandshakeListener;
import org.glassfish.tyrus.spi.TyrusClientSocket;
import org.glassfish.tyrus.spi.TyrusContainer;

/**
 * ClientManager implementation.
 *
 * @author Stepan Kopriva (stepan.kopriva at oracle.com)
 * @author Pavel Bucek (pavel.bucek at oracle.com)
 */
public class ClientManager extends BaseContainer implements WebSocketContainer {

    /**
     * Default {@link TyrusContainer} class name.
     * 

* Uses Grizzly as transport implementation. */ private static final String ENGINE_PROVIDER_CLASSNAME = "org.glassfish.tyrus.container.grizzly.GrizzlyEngine"; private static final Logger LOGGER = Logger.getLogger(ClientManager.class.getName()); private final TyrusContainer engine; private final ComponentProviderService componentProvider; private final ErrorCollector collector; private final Map properties = new HashMap(); private long defaultAsyncSendTimeout; private long defaultMaxSessionIdleTimeout; private int maxBinaryMessageBufferSize = Integer.MAX_VALUE; private int maxTextMessageBufferSize = Integer.MAX_VALUE; /** * Create new {@link ClientManager} instance. *

* Uses {@link ClientManager#ENGINE_PROVIDER_CLASSNAME} as container implementation, thus relevant module needs to * be on classpath. Setting different container is possible via {@link ClientManager#createClient(String)}. * * @see ClientManager#createClient(String) */ public static ClientManager createClient() { return createClient(ENGINE_PROVIDER_CLASSNAME); } /** * Create new ClientManager instance. * * @return new ClientManager instance. */ public static ClientManager createClient(String engineProviderClassname) { return new ClientManager(engineProviderClassname); } /** * Create new {@link ClientManager} instance. *

* Uses {@link ClientManager#ENGINE_PROVIDER_CLASSNAME} as container implementation, thus relevant module needs to * be on classpath. Setting different container is possible via {@link ClientManager#createClient(String)}}. * * @see ClientManager#createClient(String) */ public ClientManager() { this(ENGINE_PROVIDER_CLASSNAME); } private ClientManager(String engineProviderClassname) { collector = new ErrorCollector(); componentProvider = ComponentProviderService.create(); Class engineProviderClazz = null; try { engineProviderClazz = ReflectionHelper.classForNameWithException(engineProviderClassname); } catch (ClassNotFoundException e) { collector.addException(e); } LOGGER.config(String.format("Provider class loaded: %s", engineProviderClassname)); this.engine = (TyrusContainer) ReflectionHelper.getInstance(engineProviderClazz, collector); TyrusContainerProvider.getContainerProvider().setContainer(this); if (!collector.isEmpty()) { throw new RuntimeException(collector.composeComprehensiveException()); } } @Override public Session connectToServer(Class annotatedEndpointClass, URI path) throws DeploymentException { if (annotatedEndpointClass.getAnnotation(ClientEndpoint.class) == null) { throw new DeploymentException(String.format("Class argument in connectToServer(Class, URI) is to be annotated endpoint class." + "Class %s does not have @ClientEndpoint", annotatedEndpointClass.getName())); } return connectToServer(annotatedEndpointClass, null, path.toString()); } @Override public Session connectToServer(Class endpointClass, ClientEndpointConfig cec, URI path) throws DeploymentException { return connectToServer(endpointClass, cec, path.toString()); } @Override public Session connectToServer(Endpoint endpointInstance, ClientEndpointConfig cec, URI path) throws DeploymentException, IOException { return connectToServer(endpointInstance, cec, path.toString()); } public Session connectToServer(Object obj, URI path) throws DeploymentException { return connectToServer(obj, null, path.toString()); } public Session connectToServer(Object obj, ClientEndpointConfig cec, URI path) throws DeploymentException { return connectToServer(obj, cec, path.toString()); } /** * Connects client endpoint o to the specified url. * * @param o the endpoint. * @param configuration of the endpoint. * @param url to which the client will connect. * @return {@link Session}. * @throws DeploymentException */ Session connectToServer(Object o, ClientEndpointConfig configuration, String url) throws DeploymentException { // TODO use maxSessionIdleTimeout, maxBinaryMessageBufferSize and maxTextMessageBufferSize ClientEndpointConfig config = null; Endpoint endpoint; TyrusClientSocket clientSocket = null; try { URI uri = new URI(url); String scheme = uri.getScheme(); if (scheme == null || !(scheme.equals("ws") || scheme.equals("wss"))) { throw new DeploymentException("Incorrect scheme in WebSocket endpoint URI=" + url); } } catch (URISyntaxException e) { throw new DeploymentException("Incorrect WebSocket endpoint URI=" + url, e); } final CountDownLatch responseLatch = new CountDownLatch(1); try { if (o instanceof Endpoint) { endpoint = (Endpoint) o; config = configuration == null ? ClientEndpointConfig.Builder.create().build() : configuration; } else if (o instanceof Class) { if (Endpoint.class.isAssignableFrom((Class) o)) { //noinspection unchecked endpoint = ReflectionHelper.getInstance(((Class) o), collector); config = configuration == null ? ClientEndpointConfig.Builder.create().build() : configuration; } else if ((((Class) o).getAnnotation(ClientEndpoint.class) != null)) { endpoint = AnnotatedEndpoint.fromClass((Class) o, componentProvider, false, collector); config = (ClientEndpointConfig) ((AnnotatedEndpoint) endpoint).getEndpointConfig(); } else { collector.addException(new DeploymentException(String.format("Class %s in not Endpoint descendant and does not have @ClientEndpoint", ((Class) o).getName()))); endpoint = null; config = null; } } else { endpoint = AnnotatedEndpoint.fromInstance(o, componentProvider, false, collector); config = (ClientEndpointConfig) ((AnnotatedEndpoint) endpoint).getEndpointConfig(); } final ClientEndpointConfig finalConfig = config; if (endpoint != null) { EndpointWrapper clientEndpoint = new EndpointWrapper(endpoint, config, componentProvider, this, url, collector, null); SPIHandshakeListener listener = new SPIHandshakeListener() { @Override public void onResponseHeaders(final Map originalHeaders) { final Map> headers = new TreeMap>(new Comparator() { @Override public int compare(String o1, String o2) { return o1.toLowerCase().compareTo(o2.toLowerCase()); } }); for (Map.Entry entry : originalHeaders.entrySet()) { headers.put(entry.getKey(), Arrays.asList(entry.getValue())); } finalConfig.getConfigurator().afterResponse(new HandshakeResponse() { @Override public Map> getHeaders() { return headers; } }); responseLatch.countDown(); } @Override public void onError(Throwable exception) { finalConfig.getUserProperties().put("org.glassfish.tyrus.client.exception", exception); responseLatch.countDown(); } }; clientSocket = engine.openClientSocket(url, config, clientEndpoint, listener, properties); } } catch (Exception e) { collector.addException(new DeploymentException("Connection failed.", e)); } if (!collector.isEmpty()) { throw collector.composeComprehensiveException(); } if (clientSocket != null) { try { // TODO - configurable timeout? responseLatch.await(10, TimeUnit.SECONDS); if (responseLatch.getCount() == 0) { final Object exception = config.getUserProperties().get("org.glassfish.tyrus.client.exception"); if (exception != null) { throw new DeploymentException("Handshake error.", (Throwable) exception); } final Session session = clientSocket.getSession(); if(session.isOpen()) { session.setMaxBinaryMessageBufferSize(maxBinaryMessageBufferSize); session.setMaxTextMessageBufferSize(maxTextMessageBufferSize); session.setMaxIdleTimeout(defaultMaxSessionIdleTimeout); } return session; } } catch (InterruptedException e) { throw new DeploymentException("Handshaker response not received.", e); } throw new DeploymentException("Handshake response not received."); } return null; } @Override public int getDefaultMaxBinaryMessageBufferSize() { return maxBinaryMessageBufferSize; } @Override public void setDefaultMaxBinaryMessageBufferSize(int i) { maxBinaryMessageBufferSize = i; } @Override public int getDefaultMaxTextMessageBufferSize() { return maxTextMessageBufferSize; } @Override public void setDefaultMaxTextMessageBufferSize(int i) { maxTextMessageBufferSize = i; } @Override public Set getInstalledExtensions() { return Collections.emptySet(); } @Override public long getDefaultAsyncSendTimeout() { return defaultAsyncSendTimeout; } @Override public void setAsyncSendTimeout(long timeoutmillis) { this.defaultAsyncSendTimeout = timeoutmillis; } @Override public long getDefaultMaxSessionIdleTimeout() { return defaultMaxSessionIdleTimeout; } @Override public void setDefaultMaxSessionIdleTimeout(long defaultMaxSessionIdleTimeout) { this.defaultMaxSessionIdleTimeout = defaultMaxSessionIdleTimeout; } public Map getProperties() { return properties; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy