You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@velocity.apache.org by cb...@apache.org on 2016/10/20 20:35:23 UTC
svn commit: r1765879 [1/4] - in /velocity/tools/trunk: ./
velocity-tools-browser/ velocity-tools-browser/src/
velocity-tools-browser/src/main/ velocity-tools-browser/src/main/java/
velocity-tools-browser/src/main/java/org/ velocity-tools-browser/src/ma...
Author: cbrisson
Date: Thu Oct 20 20:35:23 2016
New Revision: 1765879
URL: http://svn.apache.org/viewvc?rev=1765879&view=rev
Log:
[tools] upgrading of BrowserTool tool, and make it a subjar, to isolate dependency towards Apache DeviceMap
Added:
velocity/tools/trunk/velocity-tools-browser/
velocity/tools/trunk/velocity-tools-browser/pom.xml
velocity/tools/trunk/velocity-tools-browser/src/
velocity/tools/trunk/velocity-tools-browser/src/main/
velocity/tools/trunk/velocity-tools-browser/src/main/java/
velocity/tools/trunk/velocity-tools-browser/src/main/java/org/
velocity/tools/trunk/velocity-tools-browser/src/main/java/org/apache/
velocity/tools/trunk/velocity-tools-browser/src/main/java/org/apache/velocity/
velocity/tools/trunk/velocity-tools-browser/src/main/java/org/apache/velocity/tools/
velocity/tools/trunk/velocity-tools-browser/src/main/java/org/apache/velocity/tools/view/
velocity/tools/trunk/velocity-tools-browser/src/main/java/org/apache/velocity/tools/view/BrowserTool.java
velocity/tools/trunk/velocity-tools-browser/src/main/java/org/apache/velocity/tools/view/BrowserToolDeprecatedMethods.java
velocity/tools/trunk/velocity-tools-browser/src/main/java/org/apache/velocity/tools/view/UAParser.java
velocity/tools/trunk/velocity-tools-browser/src/main/resources/
velocity/tools/trunk/velocity-tools-browser/src/main/resources/org/
velocity/tools/trunk/velocity-tools-browser/src/main/resources/org/apache/
velocity/tools/trunk/velocity-tools-browser/src/main/resources/org/apache/velocity/
velocity/tools/trunk/velocity-tools-browser/src/main/resources/org/apache/velocity/tools/
velocity/tools/trunk/velocity-tools-browser/src/main/resources/org/apache/velocity/tools/browser/
velocity/tools/trunk/velocity-tools-browser/src/main/resources/org/apache/velocity/tools/browser/tools.xml
velocity/tools/trunk/velocity-tools-browser/src/main/resources/org/apache/velocity/tools/view/
velocity/tools/trunk/velocity-tools-browser/src/main/resources/org/apache/velocity/tools/view/ua-keywords.txt
velocity/tools/trunk/velocity-tools-browser/src/test/
velocity/tools/trunk/velocity-tools-browser/src/test/java/
velocity/tools/trunk/velocity-tools-browser/src/test/java/org/
velocity/tools/trunk/velocity-tools-browser/src/test/java/org/apache/
velocity/tools/trunk/velocity-tools-browser/src/test/java/org/apache/velocity/
velocity/tools/trunk/velocity-tools-browser/src/test/java/org/apache/velocity/tools/
velocity/tools/trunk/velocity-tools-browser/src/test/java/org/apache/velocity/tools/view/
velocity/tools/trunk/velocity-tools-browser/src/test/java/org/apache/velocity/tools/view/BrowserToolTests.java
velocity/tools/trunk/velocity-tools-browser/src/test/resources/
velocity/tools/trunk/velocity-tools-browser/src/test/resources/browsers.txt
velocity/tools/trunk/velocity-tools-browser/src/test/resources/operating_systems.txt
velocity/tools/trunk/velocity-tools-browser/src/test/resources/robots.txt
Removed:
velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/BrowserTool.java
Modified:
velocity/tools/trunk/pom.xml
velocity/tools/trunk/velocity-tools-examples/velocity-tools-examples-showcase/pom.xml
velocity/tools/trunk/velocity-tools-generic/pom.xml
velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/config/ConfigurationUtils.java
velocity/tools/trunk/velocity-tools-view/src/main/resources/org/apache/velocity/tools/view/tools.xml
Modified: velocity/tools/trunk/pom.xml
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/pom.xml?rev=1765879&r1=1765878&r2=1765879&view=diff
==============================================================================
--- velocity/tools/trunk/pom.xml (original)
+++ velocity/tools/trunk/pom.xml Thu Oct 20 20:35:23 2016
@@ -46,7 +46,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.version>4.12</junit.version>
- <slf4j.version>1.7.21</slf4j.version>
+ <slf4j.version>1.7.21</slf4j.version>
<surefire.plugin.version>2.19.1</surefire.plugin.version>
<servlet.api.version>3.0.1</servlet.api.version>
</properties>
@@ -119,6 +119,7 @@
<module>velocity-tools-generic</module>
<module>velocity-tools-xml</module>
<module>velocity-tools-view</module>
+ <module>velocity-tools-browser</module>
<module>velocity-tools-view-jsp</module>
<module>velocity-tools-struts</module>
<module>velocity-tools-uberjar</module>
Added: velocity/tools/trunk/velocity-tools-browser/pom.xml
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-browser/pom.xml?rev=1765879&view=auto
==============================================================================
--- velocity/tools/trunk/velocity-tools-browser/pom.xml (added)
+++ velocity/tools/trunk/velocity-tools-browser/pom.xml Thu Oct 20 20:35:23 2016
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>velocity-tools-parent</artifactId>
+ <groupId>org.apache.velocity</groupId>
+ <version>3.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.apache.velocity</groupId>
+ <artifactId>velocity-tools-browser</artifactId>
+ <name>Apache Velocity Tools - Browser tools</name>
+ <description>Tools for client browser user agent parsing.</description>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.velocity</groupId>
+ <artifactId>velocity-tools-view</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>${servlet.api.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.devicemap</groupId>
+ <artifactId>devicemap-client</artifactId>
+ <version>1.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.devicemap</groupId>
+ <artifactId>devicemap-data</artifactId>
+ <version>1.0.3</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ <scope>test</scope>
+ </dependency>
+ <!-- to reuse some test classes from velocity-tools-generic -->
+ <dependency>
+ <groupId>org.apache.velocity</groupId>
+ <artifactId>velocity-tools-generic</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <defaultGoal>install</defaultGoal>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>${surefire.plugin.version}</version>
+ <configuration>
+ <skip>${maven.test.skip}</skip>
+ <systemProperties>
+ <property>
+ <name>test</name>
+ <value>${test}</value>
+ </property>
+ <property>
+ <name>test.output.dir</name>
+ <value>${project.build.testOutputDirectory}</value>
+ </property>
+ <property>
+ <name>test.result.dir</name>
+ <value>${project.build.directory}/results</value>
+ </property>
+ <property>
+ <name>org.slf4j.simpleLogger.defaultLogLevel</name>
+ <value>warn</value>
+ </property>
+ </systemProperties>
+ </configuration>
+ <executions>
+ <execution>
+ <id>integration-test</id>
+ <phase>integration-test</phase>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <skip>false</skip>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
Added: velocity/tools/trunk/velocity-tools-browser/src/main/java/org/apache/velocity/tools/view/BrowserTool.java
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-browser/src/main/java/org/apache/velocity/tools/view/BrowserTool.java?rev=1765879&view=auto
==============================================================================
--- velocity/tools/trunk/velocity-tools-browser/src/main/java/org/apache/velocity/tools/view/BrowserTool.java (added)
+++ velocity/tools/trunk/velocity-tools-browser/src/main/java/org/apache/velocity/tools/view/BrowserTool.java Thu Oct 20 20:35:23 2016
@@ -0,0 +1,596 @@
+package org.apache.velocity.tools.view;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.*;
+
+import org.apache.devicemap.DeviceMapClient;
+import org.apache.devicemap.DeviceMapFactory;
+import org.apache.devicemap.data.Device;
+import org.apache.devicemap.loader.LoaderOption;
+import org.apache.velocity.exception.VelocityException;
+import org.apache.velocity.tools.ConversionUtils;
+import static org.apache.velocity.tools.view.UAParser.*;
+
+import org.slf4j.Logger;
+
+import org.apache.velocity.tools.Scope;
+import org.apache.velocity.tools.config.DefaultKey;
+import org.apache.velocity.tools.config.InvalidScope;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * <p>userAgent.getBrowser()-sniffing tool (session or request scope requested, session scope advised).</p>
+ * <p></p>
+ * <p><b>Usage:</b></p>
+ * <p>BrowserTool defines properties that are used to test the client userAgent.getBrowser(), operating system, device, language...</p>
+ * <p>All properties are boolean, excpet those in italic which are strings (and major/minor versions which are integers)</p>
+ * <p>The following properties are available:</p>
+ * <ul>
+ * <li><b>Device: </b><i>device</i> robot mobile tablet desktop</li>
+ * <li><b>Features:</b>css3 dom3</li>
+ * <li><b>Browser:</b><i>userAgent.getBrowser().name userAgent.getBrowser().majorVersion userAgent.getBrowser().minorVersion</i></li>
+ * <li><b>Rendering engine: </b><i>renderingEngine.name renderingEngine.minorVersion renderingEngine.majorVersion</i></li>
+ * <li><b>Operating system: </b><i>operatingsystem.name operatingsystem.majorVersion operatingsystem.minorVersion</i></li>
+ * <li><b>Specific userAgent.getBrowser() tests:</b>netscape firefox safari MSIE opera links mozilla konqueror chrome</li>
+ * <li><b>Specific rendering engine tests:</b>gecko webKit KHTML trident blink edgeHTML presto</li>
+ * <li><b>Specific OS tests:</b>windows OSX linux unix BSD android iOS symbian</li>
+ * <li><b>Languages</b>: <i>preferredLanguageTag</i> (a string like 'en', 'da', 'en-US', ...), <i>preferredLocale</i> (a java Locale)</li>
+ * </ul>
+ *
+ * <p>Language properties are filtered by the languagesFilter tool param, if present, which is here to specify which languages are acceptable on the server side.
+ * If no matching language is found, or if there is no
+ * matching language, the tools defaut locale (or the first value of languagesFilter) is returned.
+ * Their value is guarantied to belong to the set provided in languagesFilter, if any.</p>
+ *
+ * <p>Thanks to Lee Semel (lee@semel.net), the author of the HTTP::BrowserDetect Perl module.</p>
+ * <p>See also:
+ * <ul>
+ * <li>http://www.zytrax.com/tech/web/userAgent.getBrowser()_ids.htm</li>
+ * <li>http://en.wikipedia.org/wiki/User_agent</li>
+ * <li>http://www.user-agents.org/</li>
+ * <li>https://github.com/OpenDDR</li>
+ * <li>https://devicemap.apache.org/</li>
+ * <li>http://www.useragentstring.com/pages/useragentstring.php?name=All</li>
+ * <li>https://en.wikipedia.org/wiki/Comparison_of_layout_engines_(Cascading_Style_Sheets)</li>
+ * <li>https://en.wikipedia.org/wiki/Comparison_of_layout_engines_(Document_Object_Model)</li>
+ * <li>http://www.webapps-online.com/online-tools/user-agent-strings</li>
+ * <li>https://whichuserAgent.getBrowser().net/data/</li>
+ * </ul>
+ * </p>
+ *
+ * @author <a href="mailto:claude@renegat.net">Claude Brisson</a>
+ * @since VelocityTools 2.0
+ * @version $Revision$ $Date$
+ */
+@DefaultKey("userAgent.getBrowser()")
+@InvalidScope(Scope.APPLICATION)
+public class BrowserTool extends BrowserToolDeprecatedMethods implements java.io.Serializable
+{
+ private static final long serialVersionUID = 1734529350532353339L;
+
+ protected Logger LOG = null;
+
+ /* User-Agent */
+ private String userAgentString = null;
+ private String lowercaseUserAgentString = null;
+ private UserAgent userAgent = null;
+
+ /* Accept-Language header variables */
+ private String acceptLanguage = null;
+ private SortedMap<Float,List<String>> languageRangesByQuality = null;
+ private String starLanguageRange = null;
+ // pametrizable filter of retained laguages
+ private List<String> languagesFilter = null;
+ private String preferredLanguage = null;
+
+ private static Pattern quality = Pattern.compile("^q\\s*=\\s*(\\d(?:0(?:.\\d{0,3})?|1(?:.0{0,3}))?)$");
+
+ /* parsing helpers */
+ private static UAParser uaParser = null;
+ /**
+ * Retrieves the User-Agent header from the request (if any).
+ * @see #setUserAgentString
+ */
+ public void setRequest(HttpServletRequest request)
+ {
+ if (request != null)
+ {
+ setUserAgentString(request.getHeader("User-Agent"));
+ setAcceptLanguage(request.getHeader("Accept-Language"));
+ }
+ else
+ {
+ setUserAgentString(null);
+ setAcceptLanguage(null);
+ }
+ }
+
+ /**
+ * Set log.
+ */
+ public void setLog(Logger log)
+ {
+ if (log == null)
+ {
+ throw new NullPointerException("BrowserTool: log should not be set to null");
+ }
+ this.LOG = log;
+ uaParser = new UAParser(LOG);
+ }
+
+
+ /**
+ * Sets the User-Agent string to be parsed for info. If null, the string
+ * will be empty and everything will return false or null. Otherwise,
+ * it will set the whole string to lower case before storing to simplify
+ * parsing.
+ */
+ public void setUserAgentString(String ua)
+ {
+ /* reset internal state */
+ userAgentString = null;
+ userAgent = null;
+ acceptLanguage = preferredLanguage = null;
+ languageRangesByQuality = null;
+ starLanguageRange = null;
+
+ if (ua == null)
+ {
+ lowercaseUserAgentString = "";
+ }
+ else
+ {
+ userAgentString = ua;
+ lowercaseUserAgentString = ua.toLowerCase();
+ if (uaParser == null)
+ {
+ /* can't run without a logger, can we? */
+ throw new VelocityException("BrowserTool: no logger was defined");
+ }
+ userAgent = uaParser.parseUserAgent(ua);
+ }
+ }
+
+ public void setAcceptLanguage(String al)
+ {
+ if(al == null)
+ {
+ acceptLanguage = "";
+ }
+ else
+ {
+ acceptLanguage = al.toLowerCase();
+ }
+ }
+
+ public void setLanguagesFilter(String filter)
+ {
+ if(filter == null || filter.length() == 0)
+ {
+ languagesFilter = null;
+ }
+ else
+ {
+ languagesFilter = Arrays.asList(filter.split(","));
+ }
+ // clear preferred language cache
+ preferredLanguage = null;
+ }
+
+ public String getLanguagesFilter()
+ {
+ return languagesFilter.toString();
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.getClass().getSimpleName()+"[ua="+ userAgentString +"]";
+ }
+
+
+ /* Generic getter for unknown tests
+ */
+ public boolean get(String key)
+ {
+ return test(key);
+ }
+
+ public String getUserAgentString()
+ {
+ return userAgentString;
+ }
+
+ public String getAcceptLanguage()
+ {
+ return acceptLanguage;
+ }
+
+ /* device type */
+
+ /**
+ * @Since VelocityTools 3.0
+ */
+ public String getDeviceType()
+ {
+ return userAgent == null ? null : userAgent.getDeviceType().toString().toLowerCase();
+ }
+
+ public boolean isRobot()
+ {
+ return userAgent != null && userAgent.getDeviceType() == DeviceType.ROBOT;
+ }
+
+ /**
+ * @Since VelocityTools 3.0
+ */
+ public boolean isTablet()
+ {
+ return userAgent == null && userAgent.getDeviceType() == DeviceType.TABLET;
+ }
+
+ /**
+ * @Since VelocityTools 3.0
+ */
+ public boolean isMobile()
+ {
+ return userAgent == null && userAgent.getDeviceType() == DeviceType.MOBILE;
+ }
+
+ /**
+ * @Since VelocityTools 3.0
+ */
+ public boolean isDesktop()
+ {
+ return userAgent == null && userAgent.getDeviceType() == DeviceType.DESKTOP;
+ }
+
+ /**
+ * @Since VelocityTools 3.0
+ */
+ public UAEntity getBrowser()
+ {
+ return userAgent == null ? null : userAgent.getBrowser();
+ }
+
+ /**
+ * @Since VelocityTools 3.0
+ */
+ public UAEntity getRenderingEngine()
+ {
+ return userAgent == null ? null : userAgent.getRenderingEngine();
+ }
+
+ /**
+ * @Since VelocityTools 3.0
+ */
+ public UAEntity getOperatingSystem()
+ {
+ return userAgent == null ? null : userAgent.getOperatingSystem();
+ }
+
+ /* Specific rendering engines */
+
+ public boolean isGecko()
+ {
+ return getRenderingEngine() != null && "Gecko".equals(getRenderingEngine().getName());
+ }
+
+ public boolean isWebKit()
+ {
+ return getRenderingEngine() != null && "AppleWebKit".equals(getRenderingEngine().getName());
+ }
+
+ public boolean isKHTML()
+ {
+ return getRenderingEngine() != null && "KHTML".equals(getRenderingEngine().getName());
+ }
+
+ public boolean isTrident()
+ {
+ return getRenderingEngine() != null && "Trident".equals(getRenderingEngine().getName());
+ }
+
+ public boolean isBlink()
+ {
+ return getRenderingEngine() != null && "Blink".equals(getRenderingEngine().getName());
+ }
+
+ public boolean isEdgeHTML()
+ {
+ return getRenderingEngine() != null && "EdgeHTML".equals(getRenderingEngine().getName());
+ }
+
+ public boolean isPresto()
+ {
+ return getRenderingEngine() != null && "Presto".equals(getRenderingEngine().getName());
+ }
+
+ /* Specific userAgent.getBrowser()s */
+
+ public boolean isChrome()
+ {
+ return getBrowser() != null && ("Chrome".equals(getBrowser().getName()) || "Chromium".equals(getBrowser().getName()));
+ }
+
+ public boolean isMSIE()
+ {
+ return getBrowser() != null && "MSIE".equals(getBrowser().getName());
+ }
+
+ public boolean isFirefox()
+ {
+ return getBrowser() != null && ("Firefox".equals(getBrowser().getName()) || "Iceweasel".equals(getBrowser().getName()));
+ }
+
+ public boolean isOpera()
+ {
+ return getBrowser() != null && ("Opera".equals(getBrowser().getName()) || "Opera Mobile".equals(getBrowser().getName()));
+ }
+
+ public boolean isSafari()
+ {
+ return getBrowser() != null && "Safari".equals(getBrowser().getName());
+ }
+
+ public boolean isNetscape()
+ {
+ return getBrowser() != null && "Netscape".equals(getBrowser().getName());
+ }
+
+ public boolean isKonqueror()
+ {
+ return getBrowser() != null && "Konqueror".equals(getBrowser().getName());
+ }
+
+ public boolean isLinks()
+ {
+ return getBrowser() != null && "Links".equals(getBrowser().getName());
+ }
+
+ public boolean isMozilla()
+ {
+ return getBrowser() != null && "Mozilla".equals(getBrowser().getName());
+ }
+
+ /* Operating System */
+
+ public boolean isWindows()
+ {
+ return getOperatingSystem() != null && getOperatingSystem().getName().startsWith("Windows");
+ }
+
+ public boolean isOSX()
+ {
+ return getOperatingSystem() != null && (getOperatingSystem().getName().equals("OS X") || getOperatingSystem().getName().equals("iOS"));
+ }
+
+ private static Set<String> linuxDistros = null;
+ static
+ {
+ linuxDistros = new HashSet<String>();
+ linuxDistros.add("Ubuntu");
+ linuxDistros.add("Debian");
+ linuxDistros.add("Red Hat");
+ linuxDistros.add("Fedora");
+ linuxDistros.add("Slackware");
+ linuxDistros.add("SUSE");
+ linuxDistros.add("ArchLinux");
+ linuxDistros.add("Gentoo");
+ linuxDistros.add("openSUSE");
+ linuxDistros.add("Manjaro");
+ linuxDistros.add("Mandriva");
+ linuxDistros.add("PCLinuxOS");
+ linuxDistros.add("CentOS");
+ linuxDistros.add("Tizen");
+ linuxDistros.add("Mint");
+ linuxDistros.add("StartOS");
+ }
+
+ public boolean isLinux()
+ {
+ return getOperatingSystem() != null && (getOperatingSystem().getName().startsWith("Linux") || linuxDistros.contains(getOperatingSystem().getName()));
+ }
+
+ public boolean isBSD()
+ {
+ return getOperatingSystem() != null && getOperatingSystem().getName().endsWith("BSD");
+ }
+
+ public boolean isUnix()
+ {
+ if (getOperatingSystem() != null)
+ {
+ String osname = getOperatingSystem().getName().toLowerCase();
+ return osname.indexOf("unix") != -1 || osname.equals("bsd") || osname.equals("sunos");
+ }
+ return false;
+ }
+
+ public boolean isAndroid()
+ {
+ return getOperatingSystem() != null && getOperatingSystem().getName().startsWith("Android");
+ }
+
+ public boolean isIOS()
+ {
+ if (getOperatingSystem() != null)
+ {
+ String osName = getOperatingSystem().getName();
+ return osName.startsWith("iOS") || osName.startsWith("iPhone") || osName.startsWith("iPad");
+ }
+ return false;
+ }
+
+ public boolean isSymbian()
+ {
+ return getOperatingSystem() != null && getOperatingSystem().getName().startsWith("Symb");
+ }
+
+ public boolean isBlackberry()
+ {
+ return getOperatingSystem() != null &&
+ (getOperatingSystem().getName().startsWith("BlackBerry") ||
+ getOperatingSystem().getName().equals("PlayBook"));
+ }
+
+ /* Features */
+
+ /* Since support of those features is often partial, the sniffer returns true
+ when a consequent subset is supported. */
+
+ public boolean getCss3()
+ {
+ return isTrident() && getRenderingEngine().getMajorVersion() >= 9 ||
+ isEdgeHTML() ||
+ isGecko() && (getRenderingEngine().getMajorVersion() >=2 || getRenderingEngine().getMinorVersion() >= 9) ||
+ isWebKit() && getRenderingEngine().getMajorVersion() >= 85 ||
+ isKHTML() && (getRenderingEngine().getMajorVersion() >= 4 || getRenderingEngine().getMajorVersion() == 3 && getRenderingEngine().getMinorVersion() >= 4) ||
+ isPresto() && getRenderingEngine().getMajorVersion() >= 2;
+ }
+
+ public boolean getDom3()
+ {
+ return isEdgeHTML() ||
+ isTrident() && getRenderingEngine().getMajorVersion() >= 9 ||
+ isGecko() && (getRenderingEngine().getMajorVersion() >=2 || getRenderingEngine().getMinorVersion() >= 7) ||
+ isWebKit() && getRenderingEngine().getMajorVersion() >= 601;
+ }
+
+ /* Languages */
+
+ public String getPreferredLanguage()
+ {
+ if(preferredLanguage != null) return preferredLanguage;
+
+ parseAcceptLanguage();
+ if(languageRangesByQuality.size() == 0)
+ {
+ preferredLanguage = starLanguageRange; // may be null
+ }
+ else
+ {
+ List<List<String>> lists = new ArrayList<List<String>>(languageRangesByQuality.values());
+ Collections.reverse(lists);
+ for(List<String> lst : lists) // sorted by quality (treemap)
+ {
+ for(String l : lst)
+ {
+ preferredLanguage = filterLanguageTag(l);
+ if(preferredLanguage != null) break;
+ }
+ if(preferredLanguage != null) break;
+ }
+ }
+ // fallback
+ if(preferredLanguage == null)
+ {
+ preferredLanguage = filterLanguageTag(languagesFilter == null ? getLocale().getDisplayName() : languagesFilter.get(0));
+ }
+ // preferredLanguage should now never be null
+ assert(preferredLanguage != null);
+ return preferredLanguage;
+ }
+
+ public Locale getPreferredLocale()
+ {
+ return ConversionUtils.toLocale(getPreferredLanguage());
+ }
+
+ /* Helpers */
+
+ protected boolean test(String key)
+ {
+ return lowercaseUserAgentString.indexOf(key) != -1;
+ }
+
+ private void parseAcceptLanguage()
+ {
+ if(languageRangesByQuality != null)
+ {
+ // already done
+ return;
+ }
+
+ languageRangesByQuality = new TreeMap<Float,List<String>>();
+ StringTokenizer languageTokenizer = new StringTokenizer(acceptLanguage, ",");
+ while (languageTokenizer.hasMoreTokens())
+ {
+ String language = languageTokenizer.nextToken().trim();
+ int qValueIndex = language.indexOf(';');
+ if(qValueIndex == -1)
+ {
+ language = language.replace('-','_');
+ List<String> l = languageRangesByQuality.get(1.0f);
+ if(l == null)
+ {
+ l = new ArrayList<String>();
+ languageRangesByQuality.put(1.0f,l);
+ }
+ l.add(language);
+ }
+ else
+ {
+ String code = language.substring(0,qValueIndex).trim().replace('-','_');
+ String qval = language.substring(qValueIndex + 1).trim();
+ if("*".equals(qval))
+ {
+ starLanguageRange = code;
+ }
+ else
+ {
+ Matcher m = quality.matcher(qval);
+ if(m.matches())
+ {
+ Float q = Float.valueOf(m.group(1));
+ List<String> al = languageRangesByQuality.get(q);
+ if(al == null)
+ {
+ al = new ArrayList<String>();
+ languageRangesByQuality.put(q,al);
+ }
+ al.add(code);
+ }
+ else
+ {
+ LOG.error("BrowserTool: could not parse language quality value: {}", language);
+ }
+ }
+ }
+ }
+ }
+
+ private String filterLanguageTag(String languageTag)
+ {
+ languageTag = languageTag.replace('-','_');
+ if(languagesFilter == null) return languageTag;
+ if(languagesFilter.contains(languageTag)) return languageTag;
+ if(languageTag.contains("_"))
+ {
+ String[] parts = languageTag.split("_");
+ if(languagesFilter.contains(parts[0])) return parts[0];
+ }
+ return null;
+ }
+}
Added: velocity/tools/trunk/velocity-tools-browser/src/main/java/org/apache/velocity/tools/view/BrowserToolDeprecatedMethods.java
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-browser/src/main/java/org/apache/velocity/tools/view/BrowserToolDeprecatedMethods.java?rev=1765879&view=auto
==============================================================================
--- velocity/tools/trunk/velocity-tools-browser/src/main/java/org/apache/velocity/tools/view/BrowserToolDeprecatedMethods.java (added)
+++ velocity/tools/trunk/velocity-tools-browser/src/main/java/org/apache/velocity/tools/view/BrowserToolDeprecatedMethods.java Thu Oct 20 20:35:23 2016
@@ -0,0 +1,697 @@
+package org.apache.velocity.tools.view;
+
+import org.apache.velocity.tools.generic.FormatConfig;
+import static org.apache.velocity.tools.view.UAParser.UAEntity;
+
+
+@Deprecated
+public abstract class BrowserToolDeprecatedMethods extends FormatConfig
+{
+ public abstract UAEntity getBrowser();
+ public abstract UAEntity getRenderingEngine();
+ public abstract UAEntity getOperatingSystem();
+ public abstract boolean isMSIE();
+ public abstract boolean isNetscape();
+ public abstract boolean isOpera();
+ public abstract boolean isOSX();
+ public abstract boolean isGecko();
+ public abstract boolean isKonqueror();
+ public abstract boolean isSafari();
+ public abstract boolean isChrome();
+ public abstract boolean isLinks();
+ public abstract boolean isWindows();
+ public abstract boolean isMozilla();
+ public abstract boolean isFirefox();
+ public abstract boolean isLinux();
+ protected abstract boolean test(String str);
+
+ /**
+ * @deprecated use {@link #getBrowser()} version getters
+ */
+ @Deprecated
+ public String getVersion()
+ {
+ return getBrowser().getMajorVersion() + "." + getBrowser().getMinorVersion();
+ }
+
+ /**
+ * @deprecated use {@link #getBrowser()}.getMajorVersion()
+ */
+ @Deprecated
+ public int getMajorVersion()
+ {
+ return getBrowser().getMajorVersion();
+ }
+
+ /**
+ * @deprecated use {@link #getBrowser()}.getMinorVersion()
+ */
+ @Deprecated
+ public int getMinorVersion()
+ {
+ return getBrowser().getMinorVersion();
+ }
+
+ /**
+ * @deprecated use {@link #getRenderingEngine()} and version getters
+ */
+ @Deprecated
+ public String getGeckoVersion()
+ {
+ UAEntity renderingEngine = getRenderingEngine();
+ return
+ renderingEngine != null && "Gecko".equals(renderingEngine.getName()) ?
+ renderingEngine.getMajorVersion() + "." + renderingEngine.getMinorVersion() :
+ null;
+ }
+
+ /**
+ * @deprecated use {@link #getRenderingEngine()} and version getters
+ */
+ public int getGeckoMajorVersion()
+ {
+ UAEntity renderingEngine = getRenderingEngine();
+ return
+ renderingEngine != null && "Gecko".equals(renderingEngine.getName()) ?
+ renderingEngine.getMajorVersion() :
+ 0;
+ }
+
+ /**
+ * @deprecated use {@link #getRenderingEngine()} version getters
+ */
+ public int getGeckoMinorVersion()
+ {
+ UAEntity renderingEngine = getRenderingEngine();
+ return
+ renderingEngine != null && "Gecko".equals(renderingEngine.getName()) ?
+ renderingEngine.getMajorVersion() :
+ 0;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getNav2()
+ {
+ return isNetscape() && getBrowser().getMajorVersion() == 2;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getNav3()
+ {
+ return isNetscape() && getMajorVersion() == 3;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getNav4()
+ {
+ return isNetscape() && getMajorVersion() == 4;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getNav4up()
+ {
+ return isNetscape() && getMajorVersion() >= 4;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getNav45()
+ {
+ return isNetscape() && getMajorVersion() == 4 &&
+ getMinorVersion() == 5;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getNav45up()
+ {
+ return isNetscape() && getMajorVersion() >= 5 ||
+ getNav4() && getMinorVersion() >= 5;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getNavgold()
+ {
+ return test("gold");
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getNav6()
+ {
+ return isNetscape() && getMajorVersion() == 5; /* sic */
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getNav6up()
+ {
+ return isNetscape() && getMajorVersion() >= 5;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getIe()
+ {
+ return isMSIE();
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getIe3()
+ {
+ return isMSIE() && getBrowser().getMajorVersion() < 4;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getIe4()
+ {
+ return isMSIE() && getBrowser().getMajorVersion() == 4;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getIe4up()
+ {
+ return isMSIE() && getBrowser().getMajorVersion() >= 4;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getIe5()
+ {
+ return isMSIE() && getBrowser().getMajorVersion() == 5;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getIe5up()
+ {
+ return isMSIE() && getBrowser().getMajorVersion() >= 5;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getIe55()
+ {
+ return isMSIE() && getBrowser().getMajorVersion() == 5 && getBrowser().getMinorVersion() >= 5;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getIe55up()
+ {
+ return (getIe5() && getBrowser().getMinorVersion() >= 5) ||
+ (isMSIE() && getBrowser().getMajorVersion() >= 6);
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getIe6()
+ {
+ return isMSIE() && getBrowser().getMajorVersion() == 6;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getIe6up()
+ {
+ return isMSIE() && getBrowser().getMajorVersion() >= 6;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getIe7()
+ {
+ return isMSIE() && getBrowser().getMajorVersion() == 7;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getIe7up()
+ {
+ return isMSIE() && getBrowser().getMajorVersion() >= 7;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getIe8()
+ {
+ return isMSIE() && getBrowser().getMajorVersion() == 8;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getIe8up()
+ {
+ return isMSIE() && getBrowser().getMajorVersion() >= 8;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getOpera3()
+ {
+ return isOpera() && getBrowser().getMajorVersion() == 3;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getOpera4()
+ {
+ return isOpera() && getBrowser().getMajorVersion() == 4;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getOpera5()
+ {
+ return isOpera() && getBrowser().getMajorVersion() == 5;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getOpera6()
+ {
+ return isOpera() && getBrowser().getMajorVersion() == 6;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getOpera7()
+ {
+ return isOpera() && getBrowser().getMajorVersion() == 7;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getOpera8()
+ {
+ return isOpera() && getBrowser().getMajorVersion() == 8;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getOpera9()
+ {
+ return test("opera/9");
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getWin16()
+ {
+ return test("win16") || test("16bit") || test("windows 3") ||
+ test("windows 16-bit");
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getWin3x()
+ {
+ return test("win16") || test("windows 3") || test("windows 16-bit");
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getWin31()
+ {
+ return test("win16") || test("windows 3.1") || test("windows 16-bit");
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getWin95()
+ {
+ return test("win95") || test("windows 95");
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getWin98()
+ {
+ return test("win98") || test("windows 98");
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getWinnt()
+ {
+ return test("winnt") || test("windows nt") || test("nt4") || test("nt3");
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getWin2k()
+ {
+ return test("nt 5.0") || test("nt5");
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getWinxp()
+ {
+ return test("nt 5.1");
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getVista()
+ {
+ return test("nt 6.0");
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getDotnet()
+ {
+ return test(".net clr");
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getWinme()
+ {
+ return test("win 9x 4.90");
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean getWin32()
+ {
+ return getWin95() || getWin98() || getWinnt() || getWin2k() ||
+ getWinxp() || getWinme() || test("win32");
+ }
+
+ /**
+ * @deprecated use isOSX()
+ */
+ @Deprecated
+ public boolean isMac()
+ {
+ return isOSX();
+ }
+
+ @Deprecated
+ public boolean isMac68k()
+ {
+ return isMac() && (test("68k") || test("68000"));
+ }
+
+ @Deprecated
+ public boolean isMacppc()
+ {
+ return isMac() && (test("ppc") || test("powerpc"));
+ }
+
+ @Deprecated
+ public boolean isAmiga()
+ {
+ return test("amiga");
+ }
+
+ @Deprecated
+ public boolean isEmacs()
+ {
+ return test("emacs");
+ }
+
+ @Deprecated
+ public boolean isOs2()
+ {
+ return test("os/2");
+ }
+
+ @Deprecated
+ public boolean isSun()
+ {
+ return test("sun");
+ }
+
+ @Deprecated
+ public boolean isSun4()
+ {
+ return test("sunos 4");
+ }
+
+ @Deprecated
+ public boolean isSun5()
+ {
+ return test("sunos 5");
+ }
+
+ @Deprecated
+ public boolean isSuni86()
+ {
+ return isSun() && test("i86");
+ }
+
+ @Deprecated
+ public boolean isIrix()
+ {
+ return test("irix");
+ }
+
+ @Deprecated
+ public boolean isIrix5()
+ {
+ return test("irix5");
+ }
+
+ @Deprecated
+ public boolean isIrix6()
+ {
+ return test("irix6");
+ }
+
+ @Deprecated
+ public boolean isHpux()
+ {
+ return test("hp-ux");
+ }
+
+ @Deprecated
+ public boolean isHpux9()
+ {
+ return isHpux() && test("09.");
+ }
+
+ @Deprecated
+ public boolean isHpux10()
+ {
+ return isHpux() && test("10.");
+ }
+
+ @Deprecated
+ public boolean isAix()
+ {
+ return test("aix");
+ }
+
+ @Deprecated
+ public boolean isAix1()
+ {
+ return test("aix 1");
+ }
+
+ @Deprecated
+ public boolean isAix2()
+ {
+ return test("aix 2");
+ }
+
+ @Deprecated
+ public boolean isAix3()
+ {
+ return test("aix 3");
+ }
+
+ @Deprecated
+ public boolean isAix4()
+ {
+ return test("aix 4");
+ }
+
+ @Deprecated
+ public boolean isSco()
+ {
+ return test("sco") || test("unix_sv");
+ }
+
+ @Deprecated
+ public boolean isUnixware()
+ {
+ return test("unix_system_v");
+ }
+
+ @Deprecated
+ public boolean isMpras()
+ {
+ return test("ncr");
+ }
+
+ @Deprecated
+ public boolean isReliant()
+ {
+ return test("reliantunix");
+ }
+
+ @Deprecated
+ public boolean isDec()
+ {
+ return test("dec") || test("osf1") || test("delalpha") ||
+ test("alphaserver") || test("ultrix") || test("alphastation");
+ }
+
+ @Deprecated
+ public boolean isSinix()
+ {
+ return test("sinix");
+ }
+
+ @Deprecated
+ public boolean isFreebsd()
+ {
+ return test("freebsd");
+ }
+
+ @Deprecated
+ public boolean isBsd()
+ {
+ return test("bsd");
+ }
+
+ @Deprecated
+ public boolean isX11()
+ {
+ return test("x11");
+ }
+
+ @Deprecated
+ public boolean isVMS()
+ {
+ return test("vax") || test("openvms");
+ }
+
+ @Deprecated
+ public boolean getCss()
+ {
+ return (isMSIE() && getBrowser().getMajorVersion() >= 4) ||
+ (isNetscape() && getBrowser().getMajorVersion() >= 4) ||
+ isGecko() ||
+ isKonqueror() ||
+ (isOpera() && getBrowser().getMajorVersion() >= 3) ||
+ isSafari() ||
+ isChrome() ||
+ isLinks();
+ }
+
+ @Deprecated
+ public boolean getCss1()
+ {
+ return getCss();
+ }
+
+ @Deprecated
+ public boolean getCss2()
+ {
+ int maj = getBrowser() != null ? getBrowser().getMajorVersion() : 0;
+ return
+ (isOSX() && maj >= 5) ||
+ (isWindows() && getOperatingSystem().getMajorVersion() >= 6) ||
+ isGecko() || // && version >= ?
+ (isOpera() && maj >= 4) ||
+ (isSafari() && maj >= 2) ||
+ (isKonqueror() && maj >= 2) ||
+ isChrome();
+ }
+
+ @Deprecated
+ public boolean getDom0()
+ {
+ int maj = getBrowser() != null ? getBrowser().getMajorVersion() : 0;
+ return (isMSIE() && maj >= 3) ||
+ (isNetscape() && maj >= 2) ||
+ (isOpera() && maj >= 3) ||
+ isGecko() ||
+ isSafari() ||
+ isChrome() ||
+ isKonqueror();
+ }
+
+ @Deprecated
+ public boolean getDom1()
+ {
+ int maj = getBrowser() != null ? getBrowser().getMajorVersion() : 0;
+ return (isMSIE() && getBrowser().getMajorVersion() >= 5) ||
+ isGecko() ||
+ (isSafari() && maj >= 2) ||
+ (isOpera() && maj >= 4) ||
+ (isKonqueror() && maj >= 2)
+ || isChrome();
+ }
+
+ @Deprecated
+ public boolean getDom2()
+ {
+ int maj = getBrowser() != null ? getBrowser().getMajorVersion() : 0;
+ return (isMSIE() && maj >= 6) ||
+ (isMozilla() && maj >= 5.0) ||
+ (isOpera() && maj >= 7) ||
+ isFirefox() ||
+ isChrome();
+ }
+
+ @Deprecated
+ public boolean getJavascript()
+ {
+ return getDom0(); // good approximation
+ }
+}
Added: velocity/tools/trunk/velocity-tools-browser/src/main/java/org/apache/velocity/tools/view/UAParser.java
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-browser/src/main/java/org/apache/velocity/tools/view/UAParser.java?rev=1765879&view=auto
==============================================================================
--- velocity/tools/trunk/velocity-tools-browser/src/main/java/org/apache/velocity/tools/view/UAParser.java (added)
+++ velocity/tools/trunk/velocity-tools-browser/src/main/java/org/apache/velocity/tools/view/UAParser.java Thu Oct 20 20:35:23 2016
@@ -0,0 +1,590 @@
+package org.apache.velocity.tools.view;
+
+import org.apache.devicemap.DeviceMapClient;
+import org.apache.devicemap.DeviceMapFactory;
+import org.apache.devicemap.data.Device;
+import org.apache.devicemap.loader.LoaderOption;
+import org.apache.velocity.exception.VelocityException;
+import org.apache.velocity.tools.ClassUtils;
+import org.slf4j.Logger;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class UAParser
+{
+ public UAParser(Logger log)
+ {
+ this.LOG = log;
+ }
+
+ protected org.slf4j.Logger LOG = null;
+
+ public static class UAEntity
+ {
+ private String name = null;
+ private int majorVersion = -1;
+ private int minorVersion = -1;
+
+ public UAEntity(String n, String maj, String min)
+ {
+ name = n;
+ try
+ {
+ majorVersion = maj == null ? -1 : Integer.valueOf(maj);
+ minorVersion = maj == null ? -1 : Integer.valueOf(min);
+ }
+ catch (NumberFormatException nfe)
+ {
+ majorVersion = minorVersion = -1;
+ }
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public int getMajorVersion()
+ {
+ return majorVersion;
+ }
+
+ public int getMinorVersion()
+ {
+ return minorVersion;
+ }
+ }
+
+ /* device */
+ public enum DeviceType
+ {
+ DESKTOP,
+ MOBILE,
+ TABLET,
+ ROBOT,
+ UNKNOWN
+ };
+
+ private static DeviceMapClient deviceMapClient = null;
+
+ static
+ {
+ try
+ {
+ deviceMapClient = DeviceMapFactory.getClient(LoaderOption.JAR);
+ }
+ catch (Exception e)
+ {
+ /* no logging context yet, but a warning will be displayed at tool initialization */
+ }
+ }
+
+ /**
+ * devicemap classification
+ */
+ private Device doDeviceMapParsing(String userAgentString)
+ {
+ Device device = null;
+ if (deviceMapClient != null)
+ {
+ try
+ {
+ /* classify the userAgent */
+ device = deviceMapClient.classifyDevice(userAgentString.toLowerCase());
+ }
+ catch (Exception e)
+ {
+ LOG.error("BrowerTool: exception while querying DeviceMap:", e);
+ }
+ }
+ return device;
+ }
+
+ private static Map<String,String> browserTranslationMap = null;
+ private static Map<String,String> osTranslationMap = null;
+ static
+ {
+ browserTranslationMap = new HashMap<String,String>();
+ browserTranslationMap.put("navigator","Netscape");
+ browserTranslationMap.put("nokia5250", "Nokia Browser");
+
+ osTranslationMap = new HashMap<String,String>();
+ osTranslationMap.put("android", "Android");
+ osTranslationMap.put("bada", "Bada");
+ osTranslationMap.put("bb10", "BlackBerry");
+ osTranslationMap.put("blackberry", "BlackBerry");
+ osTranslationMap.put("cros", "Chrome OS");
+ osTranslationMap.put("fxos", "Firefox OS");
+ osTranslationMap.put("hpwos", "WebOS");
+ osTranslationMap.put("ipad", "iOS");
+ osTranslationMap.put("iphone", "iOS");
+ osTranslationMap.put("ipod", "iOS");
+ osTranslationMap.put("kfthwi", "Kindle");
+ osTranslationMap.put("kftt", "Kindle");
+ osTranslationMap.put("mac os x", "OS X");
+ osTranslationMap.put("macos x", "OS X");
+ osTranslationMap.put("remi", "Fedora");
+ osTranslationMap.put("rhel", "Red Hat");
+ osTranslationMap.put("series40", "Symbian");
+ osTranslationMap.put("series60", "Symbian");
+ osTranslationMap.put("series80", "Symbian");
+ osTranslationMap.put("series90", "Symbian");
+ osTranslationMap.put("series 40", "Symbian");
+ osTranslationMap.put("series 60", "Symbian");
+ osTranslationMap.put("series 80", "Symbian");
+ osTranslationMap.put("series 90", "Symbian");
+ osTranslationMap.put("symbianos", "Symbian");
+ osTranslationMap.put("symbos", "Symbian");
+ osTranslationMap.put("tigeros", "OS X");
+ osTranslationMap.put("tizen", "Tizen");
+ osTranslationMap.put("tt", "Android");
+ osTranslationMap.put("unix", "Unix");
+ osTranslationMap.put("unix bsd", "BSD");
+ osTranslationMap.put("unixware", "Unix");
+ osTranslationMap.put("webos", "WebOS");
+ osTranslationMap.put("windows nt", "Windows");
+ }
+
+ public static class UserAgent
+ {
+ private DeviceType deviceType = null;
+ private UAEntity operatingSystem = null;
+ private UAEntity browser = null;
+ private UAEntity renderingEngine = null;
+ private boolean isRobot = false;
+
+ public DeviceType getDeviceType() { return deviceType; }
+ public UAEntity getOperatingSystem() { return operatingSystem; }
+ public UAEntity getBrowser() { return browser; }
+ public UAEntity getRenderingEngine() { return renderingEngine; }
+
+ protected void setOperatingSystem(String entity, String major, String minor)
+ {
+ if (entity.equals("Series") && major != null)
+ {
+ entity += major;
+ major = minor = null;
+ }
+ String alternate = osTranslationMap.get(entity.toLowerCase());
+ if (alternate != null) entity = alternate;
+ if (entity.startsWith("BlackBerry")) { entity = "BlackBerry"; }
+ operatingSystem = new UAEntity(entity, major, minor);
+ }
+
+ protected void setBrowser(String entity, String major, String minor)
+ {
+ if (deviceType == DeviceType.ROBOT) return;
+ String alternate = browserTranslationMap.get(entity.toLowerCase());
+ if (alternate != null) { entity = alternate; }
+ if ("Navigator".equals(entity)) { entity = "Netscape"; }
+ browser = new UAEntity(entity, major, minor);
+ if ("Edge".equals(entity) && renderingEngine == null) { renderingEngine = new UAEntity("EdgeHTML", major, minor); }
+ }
+
+ protected void setRenderingEngine(String entity, String major, String minor)
+ {
+ if (deviceType == DeviceType.ROBOT) return;
+ renderingEngine = new UAEntity(entity, major, minor);
+ }
+
+ protected void setDeviceType(DeviceType deviceType)
+ {
+ this.deviceType = deviceType;
+ if (deviceType == DeviceType.ROBOT)
+ {
+ browser = renderingEngine = null;
+ }
+ }
+ }
+
+ private enum EntityType
+ {
+ BROWSER,
+ BROWSER_OS,
+ ENGINE,
+ FORCE_BROWSER,
+ FORCE_OS,
+ IGNORE,
+ MAYBE_BROWSER,
+ MAYBE_OS,
+ MAYBE_ROBOT,
+ MERGE,
+ MERGE_OR_BROWSER,
+ MERGE_OR_OS,
+ OS,
+ ROBOT
+ };
+
+ private static final String UA_KEYWORDS = "/org/apache/velocity/tools/view/ua-keywords.txt";
+
+ private static Map<String, EntityType> entityMap = new HashMap<String, EntityType>();
+
+ static
+ {
+ try
+ {
+ Properties properties = new Properties();
+ InputStream stream = ClassUtils.getResourceAsStream(UA_KEYWORDS, BrowserTool.class);
+ if (stream == null) { throw new IOException("could not find org.apache.velocity.tools.view.ua-keywords.txt resource"); }
+ BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
+ String line = null;
+ int num = 1;
+ while ((line = reader.readLine()) != null)
+ {
+ line = line.trim();
+ if (line.length() == 0 || line.startsWith("#")) { ++num; continue; }
+ int eq = line.indexOf('=');
+ if (eq == -1) { throw new IOException("invalid line format in ua-keywords.txt at line " + num); }
+ String key = line.substring(0, eq);
+ EntityType value = EntityType.valueOf(line.substring(eq + 1).toUpperCase());
+ entityMap.put(key, value);
+ ++num;
+ }
+ }
+ catch(Exception e)
+ {
+ throw new VelocityException("BrowserTool: static initialization failed", e);
+ }
+ }
+
+ private static final String nonMergeSep = "(;/)";
+
+ private static Pattern versionPattern = Pattern.compile(
+ /* entity name */
+ "([a-z]+(?:(?=[;()@]|$)|(?:[0-9]+(?!\\.)[a-z]*)|(?:[!_+.\\-][a-z]+)+|(?=[/ ,\\-:0-9+!_=])))" +
+ /* potential version */
+ "(?:(?:[/ ,\\-:+_=])?(?:v?(\\d+)(?:\\.(\\d+))?[a-z+]*)?)",
+ Pattern.CASE_INSENSITIVE);
+
+ private static boolean isRobotToken(String token)
+ {
+ token = token.toLowerCase();
+ return token.endsWith("bot") || token.endsWith("crawler") || token.endsWith("spider") || token.endsWith("agent") || token.endsWith("validator");
+ }
+
+ /* the big hairy parsing method */
+ public UserAgent parseUserAgent(String userAgentString)
+ {
+ UserAgent ua = null;
+ try
+ {
+ ua = new UserAgent();
+
+ Device device = doDeviceMapParsing(userAgentString);
+ if (Boolean.valueOf(device.getAttribute("is_robot")))
+ {
+ ua.setDeviceType(DeviceType.ROBOT);
+ }
+ else if (Boolean.valueOf(device.getAttribute("is_tablet")))
+ {
+ ua.setDeviceType(DeviceType.TABLET);
+ }
+ else if (Boolean.valueOf(device.getAttribute("is_wireless_device")))
+ {
+ ua.setDeviceType(DeviceType.MOBILE);
+ }
+ else if (Boolean.valueOf(device.getAttribute("is_desktop")))
+ {
+ ua.setDeviceType(DeviceType.DESKTOP);
+ }
+ else
+ {
+ ua.setDeviceType(DeviceType.UNKNOWN);
+ }
+
+ if ("Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; KFTT Build/IML74K) AppleWebKit/535.19 (KHTML, like Gecko) Silk/2.1 Mobile Safari/535.19 Silk-Accelerated=true".equals(userAgentString))
+ {
+ LOG.debug("breakpoint");
+ }
+
+ Matcher matcher = versionPattern.matcher(userAgentString);
+ String merge = null;
+ EntityType mergeTarget = null;
+ boolean maybeBrowser = true;
+ boolean maybeOS = true;
+ boolean maybeRobot = false;
+ boolean forcedBrowser = false;
+ boolean forcedOS = false;
+ while (matcher.find())
+ {
+ String entity = matcher.group(1);
+ String major = matcher.group(2);
+ String minor = matcher.group(3);
+ char next = userAgentString.length() == matcher.end(1) ? ';' : userAgentString.charAt(matcher.end(1));
+ if (entity != null)
+ {
+ if (merge != null)
+ {
+ String merged = merge + " " + entity;
+ if (mergeTarget == null)
+ {
+ entity = merged;
+ }
+ else
+ {
+ EntityType mergedType = entityMap.get(merged.toLowerCase());
+ if (mergedType != null && (
+ mergeTarget == mergedType ||
+ mergeTarget == EntityType.BROWSER && (mergedType == EntityType.MAYBE_BROWSER || mergedType == EntityType.FORCE_BROWSER) ||
+ mergeTarget == EntityType.OS && (mergedType == EntityType.MAYBE_OS || mergedType == EntityType.FORCE_OS)
+ ))
+ {
+ entity = merged;
+ }
+ else
+ {
+ /* It means the merge failed, so revert it */
+ switch (mergeTarget)
+ {
+ case BROWSER:
+ ua.setBrowser(merge, null, null);
+ break;
+ case OS:
+ ua.setOperatingSystem(merge, null, null);
+ break;
+ default:
+ throw new VelocityException("BrowserTool: unhandled case!");
+ }
+ }
+ }
+ merge = null;
+ mergeTarget = null;
+ }
+ EntityType entityType = entityMap.get(entity.toLowerCase());
+ if (entityType != null)
+ {
+ switch (entityType)
+ {
+ case BROWSER:
+ {
+ if (ua.getBrowser() == null || !forcedBrowser)
+ {
+ ua.setBrowser(entity, major, minor);
+ maybeBrowser = false;
+ }
+ break;
+ }
+ case BROWSER_OS:
+ {
+ ua.setBrowser(entity, major, minor);
+ maybeBrowser = false;
+ ua.setOperatingSystem(entity, major, minor);
+ maybeOS = false;
+ break;
+ }
+ case ENGINE:
+ {
+ if (!"KHTML".equals(entity) || major != null || ua.getRenderingEngine() == null)
+ {
+ ua.setRenderingEngine(entity, major, minor);
+ }
+ break;
+ }
+ case FORCE_BROWSER:
+ {
+ if (!forcedBrowser)
+ {
+ ua.setBrowser(entity, major, minor);
+ maybeBrowser = false;
+ forcedBrowser = true;
+ }
+ break;
+ }
+ case FORCE_OS:
+ {
+ if (!forcedOS)
+ {
+ ua.setOperatingSystem(entity, major, minor);
+ maybeOS = false;
+ forcedOS = true;
+ }
+ break;
+ }
+ case IGNORE:
+ {
+ break;
+ }
+ case MAYBE_BROWSER:
+ {
+ if (maybeBrowser)
+ {
+ if ("rv".equals(entity))
+ {
+ if (ua.getBrowser() != null && ua.getBrowser().getName().equals("Mozilla"))
+ {
+ entity = "Mozilla";
+ }
+ else
+ {
+ entity = null;
+ }
+ }
+ else if ("Version".equals(entity))
+ {
+ if (ua.getBrowser() != null && ua.getBrowser().getName().startsWith("Opera"))
+ {
+ entity = ua.getBrowser().getName();
+ }
+ else if (ua.getBrowser() != null && ua.getBrowser().getName().equals("Mozilla"))
+ {
+ entity = "Safari";
+ }
+ else
+ {
+ entity = null;
+ }
+ }
+ else if ("Safari".equals(entity) && ua.getBrowser() != null && "Safari".equals(ua.getBrowser().getName()))
+ {
+ entity = null;
+ }
+ if (entity != null)
+ {
+ ua.setBrowser(entity, major, minor);
+ }
+ }
+ break;
+ }
+ case MAYBE_OS:
+ {
+ if (maybeOS)
+ {
+ ua.setOperatingSystem(entity, major, minor);
+ }
+ break;
+ }
+ case MAYBE_ROBOT:
+ {
+ maybeRobot = true;
+ break;
+ }
+ case MERGE:
+ {
+ if (major == null)
+ {
+ if (nonMergeSep.indexOf(next) == -1)
+ {
+ merge = merge == null ? entity : merge + " " + entity;
+ }
+ else
+ {
+ if ("Mobile".equals(entity) && ua.getOperatingSystem() != null)
+ {
+ if (ua.getOperatingSystem().getName().equals("Ubuntu"))
+ {
+ ua.setOperatingSystem("Ubuntu Mobile", String.valueOf(ua.getOperatingSystem().getMajorVersion()), String.valueOf(ua.getOperatingSystem().getMinorVersion()));
+ }
+ else if (ua.getOperatingSystem().getName().equals("Linux"))
+ {
+ ua.setOperatingSystem("Android", null, null);
+ }
+ }
+ }
+ }
+ break;
+ }
+ case MERGE_OR_BROWSER:
+ {
+ if (!forcedBrowser)
+ {
+ if (major != null || nonMergeSep.indexOf(next) != -1)
+ {
+ ua.setBrowser(entity, major, minor);
+ }
+ else
+ {
+ merge = entity;
+ mergeTarget = EntityType.BROWSER;
+ }
+ }
+ break;
+ }
+ case MERGE_OR_OS:
+ {
+ if (!forcedOS)
+ {
+ if (major != null || nonMergeSep.indexOf(next) != -1)
+ {
+ ua.setOperatingSystem(entity, major, minor);
+ }
+ else
+ {
+ merge = entity;
+ mergeTarget = EntityType.OS;
+ }
+ }
+ break;
+ }
+ case OS:
+ {
+ if (ua.getOperatingSystem() == null || !forcedOS)
+ {
+ ua.setOperatingSystem(entity, major, minor);
+ maybeOS = false;
+ }
+ break;
+ }
+ case ROBOT:
+ {
+ ua.setDeviceType(DeviceType.ROBOT);
+ break;
+ }
+ default:
+ {
+ throw new VelocityException("BrowserTool: unhandled case: " + entityType);
+ }
+ }
+ } else
+ {
+ if (entity.startsWith("Linux") && !forcedOS)
+ {
+ ua.setOperatingSystem("Linux", null, null);
+ }
+ else if (isRobotToken(entity))
+ {
+ ua.setDeviceType(DeviceType.ROBOT);
+ }
+ }
+ }
+ }
+ if (ua.getOperatingSystem() != null && "Windows".equals(ua.getOperatingSystem().getName()) && (ua.getOperatingSystem().getMajorVersion() == 98 || ua.getOperatingSystem().getMajorVersion() == 2000))
+ {
+ if (ua.getOperatingSystem().getMajorVersion() == 98)
+ {
+ ua.setOperatingSystem("Windows 98", "4", "90");
+ }
+ else if (ua.getOperatingSystem().getMajorVersion() == 2000)
+ {
+ ua.setOperatingSystem("Windows 2000", "5", "0");
+ }
+ }
+ if (ua.getBrowser() == null)
+ {
+ if (maybeRobot)
+ {
+ ua.setDeviceType(DeviceType.ROBOT);
+ }
+ else if (ua.getOperatingSystem() != null && ua.getOperatingSystem().getName().equals("Symbian"))
+ {
+ ua.setBrowser("Nokia Browser", String.valueOf(ua.getOperatingSystem().getMajorVersion()), String.valueOf(ua.getOperatingSystem().getMinorVersion()));
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ LOG.error("BrowserTool: Could not parse browser for User-Agent: {}", userAgentString, e);
+ ua = null;
+ }
+ return ua;
+ }
+
+
+}
Added: velocity/tools/trunk/velocity-tools-browser/src/main/resources/org/apache/velocity/tools/browser/tools.xml
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-browser/src/main/resources/org/apache/velocity/tools/browser/tools.xml?rev=1765879&view=auto
==============================================================================
--- velocity/tools/trunk/velocity-tools-browser/src/main/resources/org/apache/velocity/tools/browser/tools.xml (added)
+++ velocity/tools/trunk/velocity-tools-browser/src/main/resources/org/apache/velocity/tools/browser/tools.xml Thu Oct 20 20:35:23 2016
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+-->
+
+<tools>
+ <data type="boolean" key="BROWSER_TOOL_AVAILABLE" value="true"/>
+ <toolbox scope="session" createSession="false">
+ <tool class="org.apache.velocity.tools.view.BrowserTool"/>
+ </toolbox>
+</tools>
Added: velocity/tools/trunk/velocity-tools-browser/src/main/resources/org/apache/velocity/tools/view/ua-keywords.txt
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-browser/src/main/resources/org/apache/velocity/tools/view/ua-keywords.txt?rev=1765879&view=auto
==============================================================================
--- velocity/tools/trunk/velocity-tools-browser/src/main/resources/org/apache/velocity/tools/view/ua-keywords.txt (added)
+++ velocity/tools/trunk/velocity-tools-browser/src/main/resources/org/apache/velocity/tools/view/ua-keywords.txt Thu Oct 20 20:35:23 2016
@@ -0,0 +1,397 @@
+# browsers
+abrowse=browser
+acoo=merge
+acoo browser=browser
+amaya=browser
+america=merge
+america online=merge
+america online browser=browser
+amigavoyager=browser
+aol=browser
+arora=browser
+avant=merge
+avant browser=browser
+avantbrowser=browser
+beonex=browser
+blazer=browser
+bolt=browser
+browserng=browser
+bunjalloo=browser
+camino=browser
+chrome=browser
+chromeplus=browser
+cometbird=browser
+conkeror=browser
+crazy=merge
+crazy browser=force_browser
+deepnet=merge
+deepnet explorer=browser
+dillo=browser
+dooble=browser
+doris=browser
+dorothy=browser
+edge=browser
+element=merge
+element browser=browser
+elinks=browser
+enigmafox=browser
+epiphany=browser
+escape=browser
+fennec=browser
+firebird=browser
+firefox=maybe_browser
+fireweb=merge
+fireweb navigator=browser
+flock=force_browser
+fluid=browser
+galaxy=browser
+galeon=browser
+gngr.info=browser
+gobrowser=browser
+granparadiso=browser
+greenbrowser=browser
+hana=browser
+ibrowse=browser
+icab=browser
+iceape=browser
+icecat=browser
+iceweasel=browser
+iemobile=browser
+inet=merge
+inet browser=browser
+irider=browser
+iris=browser
+iron=force_browser
+itunes=browser
+k-meleon=browser
+k-ninja=browser
+kapiko=browser
+kazehakase=browser
+kkman=browser
+kmlite=browser
+konqueror=browser
+like=merge
+like gecko=ignore
+links=browser
+lobo=browser
+lolifox=browser
+lunascape=browser
+lynx=browser
+maemo=merge
+maemo browser=browser
+maxthon=browser
+midori=browser
+minefield=browser
+minimo=browser
+mobile=merge
+mobile safari=maybe_browser
+mozilla=maybe_browser
+msie=maybe_browser
+namoroka=browser
+navigator=browser
+netnewswire=browser
+netpositive=browser
+netscape=browser
+netscape6=browser
+nokia5250=force_browser
+omniweb=browser
+opera=merge_or_browser
+opera mini=force_browser
+opera mobi=browser
+orca=browser
+oregano=browser
+palemoon=browser
+prism=browser
+puffin=browser
+qtweb=merge
+qtweb internet=merge
+qtweb internet browser=browser
+rekonq=browser
+retawq=browser
+rockmelt=force_browser
+rv=maybe_browser
+safari=maybe_browser
+samsungbrowser=browser
+seamonkey=browser
+semc-browser=browser
+shiretoko=browser
+silk=browser
+skyfire=browser
+sleipnir=browser
+slimbrowser=browser
+stainless=browser
+sundance=browser
+sunrise=browser
+sunrisebrowser=browser
+surf=browser
+sylera=force_browser
+teashark=browser
+teleca=browser
+thunderbird=browser
+tencenttraveler=browser
+tenfourfox=browser
+theworld=browser
+ucbrowser=browser
+uzbl=browser
+version=maybe_browser
+vimprobable=browser
+vimprobable2=browser
+vonkeror=browser
+w3m=browser
+webpositive=force_browser
+weltweitimnetzbrowser=browser
+windows-media-player=robot
+wyzo=browser
+
+# robots (+everyone ending with 'bot', 'crawler', 'spider', 'agent' or 'validator')
+amaya=robot
+appengine-google=robot
+accoona-ai-agent=robot
+arachmo=robot
+b-l-i-t-z-b-o-t=robot
+baiduspider+=robot
+binget=robot
+bloglines=robot
+boitho.com-dc=robot
+cerberian=robot
+charlotte=robot
+cocoal.icio.us=browser
+cosmos=robot
+csscheck=robot
+curl=robot
+cynthia=robot
+dataparksearch=robot
+emailsiphon=robot
+feedfetcher-google=robot
+findlinks=robot
+googlebot-image=robot
+greatnews=robot
+gregarius=robot
+holmes=robot
+htdig=robot
+html=merge
+htmlparser=robot
+ia_archiver=robot
+ichiro=robot
+igdespyder=robot
+java=maybe_robot
+larbin=robot
+lftp=robot
+libwww=robot
+libwww-perl=robot
+linkwalker=robot
+link=robot
+linkexaminer=robot
+lwp-trivial=robot
+magpierss=robot
+mediapartners-google=robot
+metauri=robot
+mnogosearch=robot
+morning=merge
+morning paper=robot
+mvaclient=robot
+netresearchserver=robot
+netseer=merge
+netseer crawler=robot
+newsgator=robot
+nfreader=robot
+ng-search=robot
+nitro=robot
+notifixious=robot
+nusearch=merge
+nutchcvs=robot
+nymesis=robot
+obot=robot
+oegp=robot
+offline=merge
+offline explorer=robot
+orbiter=robot
+p3p=robot
+peach=robot
+peew=robot
+php=robot
+pompos=robot
+postpost=robot
+pxyscand=robot
+pycurl=robot
+python-urllib=robot
+qseero=robot
+radian=robot
+sbider=robot
+scoutjet=robot
+scrubby=robot
+searchsight=robot
+semanticdiscovery=robot
+shopwiki=robot
+sitebar=robot
+snappy=robot
+snoopy=robot
+sosospider+=robot
+sqworm=robot
+stackrambler=robot
+susie=robot
+teoma=robot
+tineye=robot
+truwogps=robot
+updated=robot
+universalfeedparser=robot
+urd-magpie=robot
+control=robot
+vagabondo=robot
+vortex=robot
+voyager=robot
+vyu2=robot
+w3c-checklink=robot
+web=merge
+web downloader=robot
+webcapture=robot
+webcollage=robot
+webcopier=robot
+webis=robot
+websquash.com=robot
+webzip=robot
+wget=robot
+womlpefactory=robot
+yacy=robot
+yahoo=merge
+yahoo slurp=robot
+yahooseeker=robot
+yahooseeker-testing=robot
+yandeximages=robot
+yeti=robot
+yooglifetchagent=robot
+zao=robot
+zeller=robot
+zyborg=robot
+
+# rendering engines
+applewebkit=engine
+blink=engine
+khtml=engine
+martha=engine
+presto=engine
+prince=engine
+trident=engine
+
+# operating systems
+amigaos=os
+android=os
+bada=force_os
+bb10=force_os
+beos=os
+blackberry=force_os
+blackberry8100=force_os
+blackberry8300=force_os
+blackberry8520=force_os
+blackberry8700=force_os
+blackberry9100=force_os
+blackberry9300=force_os
+blackberry9320=force_os
+blackberry9360=force_os
+blackberry9380=force_os
+blackberry9500=force_os
+blackberry9700=force_os
+blackberry9780=force_os
+blackberry9790=force_os
+blackberry9860=force_os
+blackberry9900=force_os
+bsd=os
+centos=os
+cros=force_os
+cpu=merge
+cpu like=merge
+cpu like mac=merge
+cpu like mac os=merge
+cpu like mac os x=ignore
+cpu like os=merge
+cpu like os x=ignore
+cpu os=merge
+cpu os x=ignore
+darwin=os
+debian=os
+elementary=merge
+elementary os=force_os
+fedora=force_os
+remi=force_os
+freebsd=os
+fxos=force_os
+gentoo=force_os
+googletv=os
+haiku=os
+hp-ux=os
+hpwos=os
+ios=force_os
+ipad=maybe_os
+iphone=maybe_os
+ipod=maybe_os
+kfthwi=os
+kftt=os
+kindle=os
+like mac=merge
+like mac os=merge
+like mac os x=ignore
+like os=merge
+like os x=ignore
+linux=maybe_os
+mint=os
+tizen=os
+mac=merge
+mac os=merge
+mac os x=maybe_os
+macos=merge
+macos x=maybe_os
+mandriva=force_os
+meego=force_os
+netbsd=os
+newstockrom=os
+nintendo=merge
+nintendo ds=os
+nokiae=os
+openbsd=os
+os=merge
+os x=os
+palm=merge
+palm os=os
+palmos=os
+palmsource=os
+playbook=os
+playstation=browser_os
+psp=browser_os
+red=merge
+red hat=os
+rhel=os
+risc=merge
+risc os=os
+sailfish=force_os
+slackware=force_os
+sonyericssonk=os
+suse=os
+series=force_os
+series40=force_os
+series60=force_os
+series80=force_os
+series90=force_os
+startos=os
+sunos=os
+supergamer=os
+syllable=os
+symbian=os
+symbianos=force_os
+symbos=os
+tigeros=os
+tt=os
+ubuntu=os
+unicos=merge
+unicos lclinux=os
+unix=merge_or_os
+unix bsd=os
+unixware=os
+webos=os
+wii=merge
+wii libnup=browser_os
+windows=merge_or_os
+windows nt=os
+windows xp=os
+windows phone=os
+windows mobile=os
+xbox=os
Added: velocity/tools/trunk/velocity-tools-browser/src/test/java/org/apache/velocity/tools/view/BrowserToolTests.java
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-browser/src/test/java/org/apache/velocity/tools/view/BrowserToolTests.java?rev=1765879&view=auto
==============================================================================
--- velocity/tools/trunk/velocity-tools-browser/src/test/java/org/apache/velocity/tools/view/BrowserToolTests.java (added)
+++ velocity/tools/trunk/velocity-tools-browser/src/test/java/org/apache/velocity/tools/view/BrowserToolTests.java Thu Oct 20 20:35:23 2016
@@ -0,0 +1,155 @@
+package org.apache.velocity.tools.view;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.util.Map;
+import java.util.TreeMap;
+
+import static org.apache.velocity.tools.view.UAParser.UAEntity;
+
+import org.apache.velocity.tools.generic.MockLogger;
+import org.junit.Test;
+
+/**
+ * <p>Tests for BrowserTool</p>
+ *
+ * @author Claude Brisson
+ * @since VelocityTools 3.0
+ * @version $Id$
+ */
+public class BrowserToolTests {
+
+ private static final String TEST_OUTPUT_DIR = System.getProperty("test.output.dir");
+
+ protected Map<String, String> readUAs(String filename) throws Exception
+ {
+ Map result = new TreeMap<String, String>();
+ BufferedReader reader = new BufferedReader(new FileReader(TEST_OUTPUT_DIR + "/" + filename));
+ String line;
+ while ((line = reader.readLine()) != null)
+ {
+ if (line.length() == 0) continue;
+ int hash = line.indexOf("#");
+ if (hash == -1) continue;
+ result.put(line.substring(hash + 2), line.substring(0, hash - 1));
+ }
+ return result;
+ }
+
+ protected void checkBrowsers(BrowserTool tool, Map<String, String> uas)
+ {
+ int num = 0;
+ for (Map.Entry<String, String> entry : uas.entrySet())
+ {
+ ++num;
+ String expected = entry.getValue();
+ String ua = entry.getKey();
+ tool.setUserAgentString(ua);
+ UAEntity browser = tool.getBrowser();
+ StringBuilder builder = new StringBuilder();
+
+ assertNotNull("entry " + num + "/" + uas.size()+": browser was not detected: browser={"+expected+"}, ua={"+ua+"}", browser);
+ builder.append(browser.getName());
+ if (browser.getMajorVersion() != -1)
+ {
+ builder.append(' ');
+ builder.append(browser.getMajorVersion());
+ if (browser.getMinorVersion() != -1)
+ {
+ builder.append('.');
+ builder.append(browser.getMinorVersion());
+ }
+ }
+ String found = builder.toString();
+ assertTrue("entry " + num + "/" + uas.size()+": wrong browser detected: browser={"+expected+"}, found={"+found+"}, ua={"+ua+"}", expected.toLowerCase().startsWith(found.toLowerCase()));
+ }
+ }
+
+ protected void checkRobots(BrowserTool tool, Map<String, String> uas)
+ {
+ int num = 0;
+ for (Map.Entry<String, String> entry : uas.entrySet())
+ {
+ ++num;
+ String robot = entry.getValue();
+ String ua = entry.getKey();
+ tool.setUserAgentString(ua);
+ assertTrue("entry " + num + "/" + uas.size()+": robot not detected: robot={"+robot+"}, ua={"+ua+"}", tool.isRobot());
+ }
+ }
+
+ protected void checkOperatingSystems(BrowserTool tool, Map<String, String> uas)
+ {
+ int num = 0;
+ for (Map.Entry<String, String> entry : uas.entrySet())
+ {
+ ++num;
+ String expected = entry.getValue();
+ String ua = entry.getKey();
+ tool.setUserAgentString(ua);
+ UAEntity os = tool.getOperatingSystem();
+ assertNotNull("entry " + num + "/" + uas.size()+": operating system not detected: os={"+expected+"}, ua={" + ua + "}", os);
+ assertEquals("entry " + num + "/" + uas.size()+": operating system not correctly detected: os={" + expected + "}, found={" + os.getName() + "}, ua={"+ua+"}", expected.toLowerCase(), os.getName().toLowerCase());
+ }
+ }
+
+ public @Test void ctorBrowserTool() throws Exception
+ {
+ try
+ {
+ new BrowserTool();
+ }
+ catch (Exception e)
+ {
+ fail("Constructor 'BrowserTool()' failed due to: " + e);
+ }
+ }
+
+ public @Test void testBrowserParsing() throws Exception
+ {
+ BrowserTool tool = new BrowserTool();
+ tool.setLog(new MockLogger(false, false));
+ Map uas = readUAs("browsers.txt");
+ checkBrowsers(tool, uas);
+ }
+
+ public @Test void testRobotParsing() throws Exception
+ {
+ BrowserTool tool = new BrowserTool();
+ tool.setLog(new MockLogger(false, false));
+ Map uas = readUAs("robots.txt");
+ checkRobots(tool, uas);
+ }
+
+ public @Test void testOperatingSystemParsing() throws Exception
+ {
+ BrowserTool tool = new BrowserTool();
+ tool.setLog(new MockLogger(false, false));
+ Map uas = readUAs("operating_systems.txt");
+ checkOperatingSystems(tool, uas);
+ }
+}