View Javadoc
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 YAUAA (https://yauaa.basjes.nl/)
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 }