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

donky.microsoft.aspnet.signalr.client.hubs.HubConnection Maven / Gradle / Ivy

There is a newer version: 2.7.0.3
Show newest version
/*
Copyright (c) Microsoft Open Technologies, Inc.
All Rights Reserved
See License.txt in the project root for license information.
*/

package donky.microsoft.aspnet.signalr.client.hubs;

import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

import donky.microsoft.aspnet.signalr.client.Action;
import donky.microsoft.aspnet.signalr.client.ConnectionState;
import donky.microsoft.aspnet.signalr.client.InvalidStateException;
import donky.microsoft.aspnet.signalr.client.LogLevel;
import donky.microsoft.aspnet.signalr.client.Logger;
import donky.microsoft.aspnet.signalr.client.Connection;

/**
 * Represents a SignalRConnection that implements the Hubs protocol
 */
public class HubConnection extends Connection {

    private Map> mCallbacks = Collections.synchronizedMap(new HashMap>());
    private Map mHubs = Collections.synchronizedMap(new HashMap());
    private Integer mCallbackId = 0;

    /**
     * Initializes the connection
     * 
     * @param url
     *            The connection URL
     * @param queryString
     *            The connection query string
     * @param useDefaultUrl
     *            indicates if the default SignalR URL should be used
     * @param logger
     *            The connection logger
     */
    public HubConnection(String url, String queryString, boolean useDefaultUrl, Logger logger) {
        super(getUrl(url, useDefaultUrl), queryString, logger);
    }

    /**
     * Initialized the connection
     * 
     * @param url
     *            The connection URL
     */
    public HubConnection(String url) {
        super(getUrl(url, true));
    }

    /**
     * Initializes the connection
     * 
     * @param url
     *            The connection URL
     * @param useDefaultUrl
     *            indicates if the default SignalR URL should be used
     */
    public HubConnection(String url, boolean useDefaultUrl) {
        super(getUrl(url, useDefaultUrl));
    }

    @Override
    public void onReceived(JsonElement message) {
        super.onReceived(message);

        log("Processing message", LogLevel.Information);
        if (getState() == ConnectionState.Connected) {
            if (message.isJsonObject() && message.getAsJsonObject().has("I")) {
                log("Getting HubResult from message", LogLevel.Verbose);
                HubResult result = mGson.fromJson(message, HubResult.class);
    
                String id = result.getId().toLowerCase(Locale.getDefault());
                log("Result Id: " + id, LogLevel.Verbose);
                log("Result Data: " + result.getResult(), LogLevel.Verbose);
    
                if (mCallbacks.containsKey(id)) {
                    log("Get and remove callback with id: " + id, LogLevel.Verbose);
                    Action callback = mCallbacks.remove(id);
    
                    try {
                        log("Execute callback for message", LogLevel.Verbose);
                        callback.run(result);
                    } catch (Exception e) {
                        onError(e, false);
                    }
                }
            } else {
                HubInvocation invocation = mGson.fromJson(message, HubInvocation.class);
                log("Getting HubInvocation from message", LogLevel.Verbose);
    
                String hubName = invocation.getHub().toLowerCase(Locale.getDefault());
                log("Message for: " + hubName, LogLevel.Verbose);
    
                if (mHubs.containsKey(hubName)) {
                    HubProxy hubProxy = mHubs.get(hubName);
                    if (invocation.getState() != null) {
                        for (String key : invocation.getState().keySet()) {
                            JsonElement value = invocation.getState().get(key);
                            log("Setting state for hub: " + key + " -> " + value, LogLevel.Verbose);
                            hubProxy.setState(key, value);
                        }
                    }
    
                    String eventName = invocation.getMethod().toLowerCase(Locale.getDefault());
                    log("Invoking event: " + eventName + " with arguments " + arrayToString(invocation.getArgs()), LogLevel.Verbose);
    
                    try {
                        hubProxy.invokeEvent(eventName, invocation.getArgs());
                    } catch (Exception e) {
                        onError(e, false);
                    }
                }
            }
        }
    }

    private static String arrayToString(JsonElement[] args) {
        StringBuilder sb = new StringBuilder();

        sb.append("[");

        for (int i = 0; i < args.length; i++) {
            if (i > 0) {
                sb.append(", ");
            }

            sb.append(args[i].toString());
        }

        sb.append("]");

        return sb.toString();
    }

    @Override
    public String getConnectionData() {
        JsonArray jsonArray = new JsonArray();

        for (String hubName : mHubs.keySet()) {
            JsonObject element = new JsonObject();
            element.addProperty("name", hubName);
            jsonArray.add(element);
        }

        String connectionData = jsonArray.toString();

        log("Getting connection data: " + connectionData, LogLevel.Verbose);
        return connectionData;
    }

    @Override
    protected void onClosed() {
        clearInvocationCallbacks("Connection closed");
        super.onClosed();
    }

    private void clearInvocationCallbacks(String error) {
        log("Clearing invocation callbacks: " + error, LogLevel.Verbose);
        HubResult result = new HubResult();
        result.setError(error);

        for (String key : mCallbacks.keySet()) {
            try {
                log("Invoking callback with empty result: " + key, LogLevel.Verbose);
                mCallbacks.get(key).run(result);
            } catch (Exception e) {
            }
        }

        mCallbacks.clear();
    }

    @Override
    protected void onReconnecting() {
        clearInvocationCallbacks("Reconnecting");
        super.onReconnecting();
    }

    /**
     * Creates a proxy for a hub
     * 
     * @param hubName
     *            The hub name
     * @return The proxy for the hub
     * @throws InvalidStateException
     *             If called when not disconnected, the method will throw an
     *             exception
     */
    public HubProxy createHubProxy(String hubName) {
        if (mState != ConnectionState.Disconnected) {
            throw new InvalidStateException(mState);
        }

        if (hubName == null) {
            throw new IllegalArgumentException("hubName cannot be null");
        }

        String hubNameLower = hubName.toLowerCase(Locale.getDefault());

        log("Creating hub proxy: " + hubNameLower, LogLevel.Information);

        HubProxy proxy = null;
        if (mHubs.containsKey(hubNameLower)) {
            proxy = mHubs.get(hubNameLower);
        } else {
            proxy = new HubProxy(this, hubName, getLogger());
            mHubs.put(hubNameLower, proxy);
        }

        return proxy;
    }

    /**
     * Registers a callback
     * 
     * @param callback
     *            The callback to register
     * @return The callback Id
     */
    String registerCallback(Action callback) {
        String id = mCallbackId.toString().toLowerCase(Locale.getDefault());
        log("Registering callback: " + id, LogLevel.Verbose);
        mCallbacks.put(id, callback);
        mCallbackId++;
        return id;
    }

    /**
     * Removes a callback
     * 
     * @param callbackId
     *            Id for the callback to remove
     */
    void removeCallback(String callbackId) {
        log("Removing callback: " + callbackId, LogLevel.Verbose);
        mCallbacks.remove(callbackId.toLowerCase(Locale.getDefault()));
    }

    /**
     * Generates a standarized URL
     * 
     * @param url
     *            The base URL
     * @param useDefaultUrl
     *            Indicates if the default SignalR suffix should be appended
     * @return The connection URL
     */
    private static String getUrl(String url, boolean useDefaultUrl) {
        if (!url.endsWith("/")) {
            url += "/";
        }

        if (useDefaultUrl) {
            return url + "signalr";
        }

        return url;
    }

    @Override
    protected String getSourceNameForLog() {
        return "HubConnection";
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy