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 }