com.google.gwt.user.rebind.UserAgentPropertyGenerator.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.user.rebind.UserAgentPropertyGenerator.java

Source

/*
 * Copyright 2011 Google Inc.
 * 
 * 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
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.gwt.user.rebind;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.linker.ConfigurationProperty;
import com.google.gwt.core.ext.linker.PropertyProviderGenerator;

import java.util.Arrays;
import java.util.List;
import java.util.SortedSet;

/**
 * Generator which writes out the JavaScript for determining the value of the
 * <code>user.agent</code> selection property.
 */
public class UserAgentPropertyGenerator implements PropertyProviderGenerator {

    /**
     * List of valid user agent selection property values, which helps ensure that
     * UserAgent.gwt.xml stays in sync with the
     * {@link #writeUserAgentPropertyJavaScript(SourceWriter)} method body of this
     * class.
     */
    private static final List<String> VALID_VALUES = Arrays
            .asList(new String[] { "ie6", "ie8", "gecko1_8", "safari", "opera", "ie9" });

    /**
     * List of predicates to identify user agent.
     * The order of evaluation is from top to bottom, i.e., the first matching
     * predicate will have the associated ua token returned.
     * ua is defined in an outer scope and is therefore visible in
     * the predicate javascript fragment.
     */
    private static UserAgentPropertyGeneratorPredicate[] predicates = new UserAgentPropertyGeneratorPredicate[] {

            // opera
            new UserAgentPropertyGeneratorPredicate("opera").getPredicateBlock()
                    .println("return (ua.indexOf('opera') != -1);").returns("'opera'"),

            // webkit family (chrome, safari and chromeframe).
            new UserAgentPropertyGeneratorPredicate("safari").getPredicateBlock().println("return (")
                    .println("(ua.indexOf('webkit') != -1)").println("||").println("(function() {")
                    .println("if (ua.indexOf('chromeframe') != -1) {").println("return true;").println("}")
                    .println("if (typeof window['ActiveXObject'] != 'undefined') {").println("try {")
                    .println("var obj = new ActiveXObject('ChromeTab.ChromeFrame');").println("if (obj) {")
                    .println("obj.registerBhoIfNeeded();").println("return true;").println("}")
                    .println("} catch(e) { }").println("}").println("return false;").println("})()").println(")")
                    .returns("'safari'"),

            // IE9
            new UserAgentPropertyGeneratorPredicate("ie9").getPredicateBlock()
                    .println("return (ua.indexOf('msie') != -1 && ($doc.documentMode >= 9));").returns("'ie9'"),

            // IE8
            new UserAgentPropertyGeneratorPredicate("ie8").getPredicateBlock()
                    .println("return (ua.indexOf('msie') != -1 && ($doc.documentMode >= 8));").returns("'ie8'"),

            // IE6
            new UserAgentPropertyGeneratorPredicate("ie6").getPredicateBlock()
                    .println("var result = /msie ([0-9]+)\\.([0-9]+)/.exec(ua);")
                    .println("if (result && result.length == 3)").indent()
                    .println("return (makeVersion(result) >= 6000);").outdent().returns("'ie6'"),

            // gecko family
            new UserAgentPropertyGeneratorPredicate("gecko1_8").getPredicateBlock()
                    .println("return (ua.indexOf('gecko') != -1);").returns("'gecko1_8'"), };

    /**
     * Writes out the JavaScript function body for determining the value of the
     * <code>user.agent</code> selection property. This method is used to create
     * the selection script and by {@link UserAgentGenerator} to assert at runtime
     * that the correct user agent permutation is executing. The list of
     * <code>user.agent</code> values listed here should be kept in sync with
     * {@link #VALID_VALUES} and <code>UserAgent.gwt.xml</code>.
     */
    static void writeUserAgentPropertyJavaScript(SourceWriter body, SortedSet<String> possibleValues) {

        // write preamble
        body.println("var ua = navigator.userAgent.toLowerCase();");
        body.println("var makeVersion = function(result) {");
        body.indent();
        body.println("return (parseInt(result[1]) * 1000) + parseInt(result[2]);");
        body.outdent();
        body.println("};");

        // write only selected user agents 
        for (int i = 0; i < predicates.length; i++) {
            if (possibleValues.contains(predicates[i].getUserAgent())) {
                body.println("if ((function() { ");
                body.indent();
                body.print(predicates[i].toString());
                body.outdent();
                body.println("})()) return " + predicates[i].getReturnValue() + ";");
            }
        }

        // default return
        body.println("return 'unknown';");
    }

    public String generate(TreeLogger logger, SortedSet<String> possibleValues, String fallback,
            SortedSet<ConfigurationProperty> configProperties) {
        for (String value : possibleValues) {
            if (!VALID_VALUES.contains(value)) {
                logger.log(TreeLogger.WARN,
                        "Unrecognized " + UserAgentGenerator.PROPERTY_USER_AGENT + " property value '" + value
                                + "', possibly due to UserAgent.gwt.xml and "
                                + UserAgentPropertyGenerator.class.getName() + " being out of sync."
                                + " Use <set-configuration-property name=\""
                                + UserAgentGenerator.PROPERTY_USER_AGENT_RUNTIME_WARNING
                                + "\" value=\"false\"/> to suppress this warning message.");
            }
        }
        // make sure that the # of ua in VALID_VALUES
        // is the same of predicates. maybe should iterate
        // to make sure each one has a match.
        assert predicates.length == VALID_VALUES.size();
        StringSourceWriter body = new StringSourceWriter();
        body.println("{");
        body.indent();
        writeUserAgentPropertyJavaScript(body, possibleValues);
        body.outdent();
        body.println("}");

        return body.toString();
    }
}