1 package org.apache.turbine.util; 2 3 /* 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the 9 * "License"); you may not use this file except in compliance 10 * with the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, 15 * software distributed under the License is distributed on an 16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 * KIND, either express or implied. See the License for the 18 * specific language governing permissions and limitations 19 * under the License. 20 */ 21 22 import java.util.concurrent.ConcurrentHashMap; 23 import java.util.concurrent.ConcurrentMap; 24 25 import nl.basjes.parse.useragent.UserAgent; 26 import nl.basjes.parse.useragent.UserAgentAnalyzer; 27 28 /** 29 * This class parses the user agent string and provides getters for 30 * its parts. It uses (<a href="https://yauaa.basjes.nl/">YAUAA</a>). 31 * 32 * The initialization step for a full UserAgentAnalyzer 33 * (i.e. all fields) usually takes something in the range of 2-5 seconds. 34 * 35 * @author <a href="mailto:frank.kim@clearink.com">Frank Y. Kim</a> 36 * @author <a href="mailto:leon@clearink.com">Leon Atkisnon</a> 37 * @author <a href="mailto:mospaw@polk-county.com">Chris Mospaw</a> 38 * @author <a href="mailto:bgriffin@cddb.com">Benjamin Elijah Griffin</a> 39 * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a> 40 */ 41 public class BrowserDetector 42 { 43 /** The user agent string. */ 44 private String userAgentString = ""; 45 46 /** The user agent parser */ 47 private static UserAgentAnalyzer uaa = UserAgentAnalyzer 48 .newBuilder() 49 .withFields(UserAgent.AGENT_NAME, 50 UserAgent.AGENT_VERSION, 51 UserAgent.OPERATING_SYSTEM_NAME) 52 .hideMatcherLoadStats() 53 .build(); 54 55 /** The user agent cache. */ 56 private static volatile ConcurrentMap<String, UserAgent> userAgentCache = 57 new ConcurrentHashMap<>(); 58 59 /** The browser name specified in the user agent string. */ 60 private String browserName = ""; 61 62 /** 63 * The browser version specified in the user agent string. If we 64 * can't parse the version just assume an old browser. 65 */ 66 private float browserVersion = (float) 1.0; 67 68 /** 69 * The browser platform specified in the user agent string. 70 */ 71 private String browserPlatform = "unknown"; 72 73 /** 74 * Constructor used to initialize this class. 75 * 76 * @param userAgentString A String with the user agent field. 77 */ 78 public BrowserDetector(String userAgentString) 79 { 80 this.userAgentString = userAgentString; 81 UserAgent userAgent = getUserAgent(); 82 83 // Get the browser name and version. 84 browserName = userAgent.getValue(UserAgent.AGENT_NAME); 85 String version = userAgent.getValue(UserAgent.AGENT_VERSION); 86 browserVersion = toFloat(version); 87 88 // Try to figure out what platform. 89 browserPlatform = userAgent.getValue(UserAgent.OPERATING_SYSTEM_NAME); 90 } 91 92 /** 93 * Constructor used to initialize this class. 94 * 95 * @param data The Turbine RunData object. 96 */ 97 public BrowserDetector(RunData data) 98 { 99 this(data.getUserAgent()); 100 } 101 102 /** 103 * The browser name specified in the user agent string. 104 * 105 * @return A String with the browser name. 106 */ 107 public String getBrowserName() 108 { 109 return browserName; 110 } 111 112 /** 113 * The browser platform specified in the user agent string. 114 * 115 * @return A String with the browser platform. 116 */ 117 public String getBrowserPlatform() 118 { 119 return browserPlatform; 120 } 121 122 /** 123 * The browser version specified in the user agent string. 124 * 125 * @return A String with the browser version. 126 */ 127 public float getBrowserVersion() 128 { 129 return browserVersion; 130 } 131 132 /** 133 * The user agent string for this class. 134 * 135 * @return A String with the user agent. 136 */ 137 public String getUserAgentString() 138 { 139 return userAgentString; 140 } 141 142 /** 143 * The user agent for this class. 144 * 145 * @return A user agent. 146 */ 147 public UserAgent getUserAgent() 148 { 149 return parse(userAgentString); 150 } 151 152 /** 153 * Helper method to initialize this class. 154 * 155 * @param userAgentString the user agent string 156 */ 157 private static UserAgent parse(String userAgentString) 158 { 159 return userAgentCache.computeIfAbsent(userAgentString, uaa::parse); 160 } 161 162 /** 163 * Helper method to convert String to a float. 164 * 165 * @param s A String. 166 * @return The String converted to float. 167 */ 168 private static final float toFloat(String s) 169 { 170 return Float.parseFloat(s); 171 } 172 }