com.msopentech.thali.utilities.webviewbridge.BridgeManager.java Source code

Java tutorial

Introduction

Here is the source code for com.msopentech.thali.utilities.webviewbridge.BridgeManager.java

Source

/*
Copyright (c) Microsoft Open Technologies, Inc.
All Rights Reserved
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
    
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
    
See the Apache 2 License for the specific language governing permissions and limitations under the License.
*/

package com.msopentech.thali.utilities.webviewbridge;

import org.apache.commons.lang3.StringEscapeUtils;

import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Provides the infrastructure for the Webview Javascript Bridge that is common to both JavaFX and Android's WebViews.
 * This object is thread safe.
 */
public abstract class BridgeManager implements Bridge {
    protected String callbackManager = "window.thali_callback_manager";
    private String managerNameInJavascript = "ThaliBridgeManager0";
    public static final String pathToBridgeManagerJs = "/BridgeManager.js";

    protected ConcurrentHashMap<String, BridgeHandler> registeredHandlers = new ConcurrentHashMap<String, BridgeHandler>();

    /**
     * A useful utility for small streams. The stream will be closed by this method.
     *
     * Taken from http://stackoverflow.com/questions/309424/read-convert-an-inputstream-to-a-string
     * @param inputStream
     * @return Stream as a string
     */
    public static String turnUTF8InputStreamToString(InputStream inputStream) {
        try {
            Scanner scanner = new Scanner(inputStream, "UTF-8").useDelimiter("\\A");
            return scanner.hasNext() ? scanner.next() : "";
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                }
            }
        }
    }

    /**
     * Executes the submitted Javascript string in the associated WebView. Note, the string is expected to be a
     * .js file.
     * @param javascript
     */
    public abstract void executeJavascript(final String javascript);

    /**
     * However this method is implemented it MUST be thread safe.
     * @param handlerName
     *
     */
    public void callBack(String handlerName, String jsonString) {
        String functionCall = callbackManager + "[\"" + handlerName + "\"]('"
                + StringEscapeUtils.escapeEcmaScript(jsonString) + "')";
        this.executeJavascript(functionCall);
    }

    public void register(BridgeHandler bridgeHandler) {
        if (registeredHandlers.putIfAbsent(bridgeHandler.getName(), bridgeHandler) != null) {
            throw new RuntimeException("Already have a handler registered with the given name");
        }
    }

    public void registerIfNameNotTaken(BridgeHandler bridgeHandler) {
        registeredHandlers.putIfAbsent(bridgeHandler.getName(), bridgeHandler);
    }

    /**
     * The method that will be called by the Bridge framework from Javascript. E.g. someone calls to the bridge in
     * Javascript and the bridge then marshals the call and calls across the bridge to this method.
     * @param handlerName
     * @param jsonString
     * @param successHandlerName
     * @param failureHandlerName
     */
    public void invokeHandler(String handlerName, String jsonString, String successHandlerName,
            String failureHandlerName) {
        BridgeCallBack bridgeCallBack = new BridgeCallBack(this, successHandlerName, failureHandlerName);

        BridgeHandler bridgeHandler = registeredHandlers.get(handlerName);

        if (bridgeHandler == null) {
            // We throw the error back to javascript so it can 'test' to see if certain interfaces have been
            // registered or not.
            bridgeCallBack
                    .failureHandler("{\"failure\":\"No registered handler with the name" + handlerName + "\"}");
        }

        bridgeHandler.call(jsonString, bridgeCallBack);
    }

    /**
     * This is the variable name that will be bound to in Javascript to expose the bridge manager.
     * @return
     */
    public String getManagerNameInJavascript() {
        return this.managerNameInJavascript;
    }
}