com.googlecode.mgwt.useragent.rebind.UserAgentPropertyGenerator.java Source code

Java tutorial

Introduction

Here is the source code for com.googlecode.mgwt.useragent.rebind.UserAgentPropertyGenerator.java

Source

/*
 * Copyright 2014 Daniel Kurka
 *
 * 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.googlecode.mgwt.useragent.rebind;

import java.util.HashSet;
import java.util.Set;
import java.util.SortedSet;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.linker.ConfigurationProperty;
import com.google.gwt.core.ext.linker.PropertyProviderGenerator;
import com.google.gwt.user.rebind.SourceWriter;
import com.google.gwt.user.rebind.StringSourceWriter;
import com.google.gwt.useragent.rebind.UserAgentGenerator;

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

    /**
     * The list of {@code user.agent} values listed here should be kept in sync with
     * {@code UserAgent.gwt.xml}.
     * <p>Note that the order of enums matter as the script selection is based on running
     * these predicates in order and matching the first one that returns {@code true}.
     * <p> Also note that, {@code docMode < 11} in predicates for older IEs exists to
     * ensures we never choose them for IE11 (we know that they will not work for IE11).
     */
    private enum UserAgent {
        ie10("return (ua.indexOf('iemobile/11') != -1) || (ua.indexOf('trident/7') != -1) || "
                + "(ua.indexOf('msie 10.') != -1) || (ua.indexOf('iemobile/10') != -1);"), ie9(
                        "return (ua.indexOf('msie') != -1 && (docMode >= 9 && docMode < 11));"), ie8(
                                "return (ua.indexOf('msie') != -1 && (docMode >= 8 && docMode < 11));"), safari(
                                        "return (ua.indexOf('webkit') != -1);"), gecko1_8(
                                                "return (ua.indexOf('gecko') != -1 || docMode >= 11);");

        private final String predicateBlock;

        private UserAgent(String predicateBlock) {
            this.predicateBlock = predicateBlock;
        }

        private static Set<String> getKnownAgents() {
            HashSet<String> userAgents = new HashSet<String>();
            for (UserAgent userAgent : values()) {
                userAgents.add(userAgent.name());
            }
            return userAgents;
        }
    }

    /**
     * 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.
     */
    static void writeUserAgentPropertyJavaScript(SourceWriter body, SortedSet<String> possibleValues,
            String fallback) {

        // write preamble
        body.println("var ua = navigator.userAgent.toLowerCase();");
        body.println("var docMode = $doc.documentMode;");

        for (UserAgent userAgent : UserAgent.values()) {
            // write only selected user agents
            if (possibleValues.contains(userAgent.name())) {
                body.println("if ((function() { ");
                body.indentln(userAgent.predicateBlock);
                body.println("})()) return '%s';", userAgent.name());
            }
        }

        // default return
        if (fallback == null) {
            fallback = "unknown";
        }
        body.println("return '" + fallback + "';");
    }

    @Override
    public String generate(TreeLogger logger, SortedSet<String> possibleValues, String fallback,
            SortedSet<ConfigurationProperty> configProperties) {
        assertUserAgents(logger, possibleValues);

        StringSourceWriter body = new StringSourceWriter();
        body.println("{");
        body.indent();
        writeUserAgentPropertyJavaScript(body, possibleValues, fallback);
        body.outdent();
        body.println("}");

        return body.toString();
    }

    private static void assertUserAgents(TreeLogger logger, SortedSet<String> possibleValues) {
        HashSet<String> unknownValues = new HashSet<String>(possibleValues);
        unknownValues.removeAll(UserAgent.getKnownAgents());
        if (!unknownValues.isEmpty()) {
            logger.log(TreeLogger.WARN,
                    "Unrecognized user.agent" + " values " + unknownValues
                            + ", possibly due to UserAgent.gwt.xml and "
                            + UserAgentPropertyGenerator.class.getName() + " being out of sync.");
        }
    }
}