KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > wings > session > Browser


1 /*
2  * $Id: Browser.java,v 1.7 2005/02/15 19:52:52 neurolabs Exp $
3  * Copyright 2000,2005 wingS development team.
4  *
5  * This file is part of wingS (http://www.j-wings.org).
6  *
7  * wingS is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation; either version 2.1
10  * of the License, or (at your option) any later version.
11  *
12  * Please see COPYING for the complete licence.
13  */

14 package org.wings.session;
15
16 import org.apache.regexp.RE;
17
18 import java.io.FileReader JavaDoc;
19 import java.io.LineNumberReader JavaDoc;
20 import java.util.Locale JavaDoc;
21 import java.util.StringTokenizer JavaDoc;
22
23
24 /**
25  * Detect the browser from the user-agent string passed in the HTTP header.
26  *
27  * @author <a HREF="mailto:andre@lison.de">Andre Lison</a>
28  * @version $Revision: 1.7 $
29  */

30 public class Browser {
31     protected String JavaDoc agent;
32     private int majorVersion;
33     private double minorVersion;
34     private String JavaDoc release;
35     private String JavaDoc os;
36     private OSType osType = OSType.UNKNOWN;
37     private String JavaDoc osVersion;
38     private String JavaDoc browserName;
39     private Locale JavaDoc browserLocale;
40     private BrowserType browserType = BrowserType.UNKNOWN;
41
42     /**
43      * Create a new browser object and start scanning for
44      * browser, os and client language in given string.
45      *
46      * @param agent the "User-Agent" string from the request.
47      */

48     public Browser(String JavaDoc agent)
49             throws org.apache.regexp.RESyntaxException {
50         this.agent = agent;
51         detect();
52     }
53
54     /**
55      * Get the browser browserName (Mozilla, MSIE, Opera etc.).
56      */

57     public String JavaDoc getBrowserName() {
58         return browserName;
59     }
60
61     /**
62      * @return A classification of the browser {@link BrowserType}
63      */

64     public BrowserType getBrowserType() {
65         return browserType;
66     }
67
68     /**
69      * Get the browser major version.
70      * <br>f.e. the major version for <i>Netscape 6.2</i> is <i>6</i>.
71      *
72      * @return the major version or <i>0</i> if not found
73      */

74     public int getMajorVersion() {
75         return majorVersion;
76     }
77
78     /**
79      * Get the minor version. This is the number after the
80      * dot in the version string.
81      * <br>f.e. the minor version for <i>Netscape 6.01</i> is <i>0.01</i>.
82      *
83      * @return the minor version if found, <i>0</i> otherwise
84      */

85     public double getMinorVersion() {
86         return minorVersion;
87     }
88
89     /**
90      * Get additional information about browser version.
91      * <br>f.e. the release for <i>MSIE 6.1b</i> is <i>b</i>.
92      *
93      * @return the release or <i>null</i>, if not available.
94      */

95     public String JavaDoc getRelease() {
96         return release;
97     }
98
99     /**
100      * Get the operating system string provided by the browser. {@link OSType}
101      *
102      * @return the os browserName or <i>null</i>, if not available.
103      */

104     public String JavaDoc getOs() {
105         return os;
106     }
107
108     /**
109      * Get the operating system version.
110      *
111      * @return the os version or <i>null</i>, if not available.
112      */

113     public String JavaDoc getOsVersion() {
114         return osVersion;
115     }
116
117     /**
118      * Get the operating system type.
119      *
120      * @return A valid {@link OSType}
121      */

122     public OSType getOsType() {
123         return osType;
124     }
125
126     /**
127      * Get the browser/client locale.
128      *
129      * @return the found locale or the default server locale
130      * specified by {@link Locale#getDefault} if not found.
131      */

132     public Locale JavaDoc getClientLocale() {
133         return browserLocale;
134     }
135
136     /* regexps are not threadsafe, we have to create them. */
137     protected final RE RE_START = new RE("^([a-zA-Z0-9_\\-]+)(/([0-9])\\.([0-9]+))?");
138     protected final RE RE_MSIE = new RE("MSIE ([0-9])\\.([0-9]+)([a-z])?");
139     protected final RE RE_MSIE_WIN_LANG_OS = new RE("[wW]in(dows)? ([A-Z0-9]+) ?([0-9]\\.[0-9])?");
140     protected final RE RE_MSIE_MAC_LANG_OS = new RE("Mac_PowerPC");
141     protected final RE RE_NS_LANG_OS = new RE("\\[([a-z-]+)\\][ a-zA-Z0-9-]*\\(([a-zA-Z\\-]+)/?([0-9]* ?[.a-zA-Z0-9 ]*);");
142     protected final RE RE_NS_X11_LANG_OS = new RE("\\(X11; U; ([a-zA-Z-]+) ([0-9\\.]+)[^\\);]+\\)");
143     protected final RE RE_NS6_LANG_OS = new RE("\\(([a-zA-Z0-9]+); [a-zA-Z]+; ([a-zA-Z0-9_]+)( ([a-zA-Z0-9]+))?; ([_a-zA-Z-]+);");
144     protected final RE RE_LANG = new RE("\\[([_a-zA-Z-]+)\\]");
145     protected final RE RE_OPERA = new RE("((; )|\\()([a-zA-Z0-9\\-]+)[ ]+([a-zA-Z0-9\\.]+)([^;\\)]*)(; U)?\\) RE_OPERA ([0-9]+)\\.([0-9]+)[ ]+\\[([_a-zA-Z-]+)\\]");
146     protected final RE RE_OPERA_LANG_OS = new RE("\\(([a-zA-Z0-9\\-]+) ([0-9\\.]+)[^)]+\\)[ \t]*\\[([a-z_]+)\\]");
147     protected final RE RE_KONQUEROR_OS = new RE("Konqueror/([0-9\\.]+); ([a-zA-Z0-9\\-]+)");
148     protected final RE RE_GALEON_OS = new RE("\\(([a-zA-Z0-9]+); U; Galeon; ([0-9]+)\\.([0-9]+);");
149     protected final RE Gecko_Engine = new RE("Gecko/[0-9]*( ([a-zA-Z]+)+[0-9]*/([0-9]+)\\.([0-9]+)([a-zA-Z0-9]*))?");
150
151     /**
152      * That does all the work.
153      */

154     protected void detect()
155             throws org.apache.regexp.RESyntaxException {
156         if (agent == null || agent.length() == 0)
157             return;
158         String JavaDoc mav, miv, lang = null;
159
160         if (RE_START.match(agent)) {
161             browserName = RE_START.getParen(1);
162             mav = RE_START.getParen(3);
163             miv = RE_START.getParen(4);
164             
165             /* RE_MSIE hides itself behind Mozilla or different browserName,
166                good idea, congratulation Bill !
167             */

168             if (RE_MSIE.match(agent)) {
169                 browserName = "MSIE";
170                 browserType = BrowserType.IE;
171                 mav = RE_MSIE.getParen(1);
172                 miv = RE_MSIE.getParen(2);
173                 release = RE_MSIE.getParen(3);
174
175                 if (RE_MSIE_WIN_LANG_OS.match(agent)) {
176                     osType = OSType.WINDOWS;
177                     os = "Windows";
178                     osVersion = RE_MSIE_WIN_LANG_OS.getParen(2) +
179                             (RE_MSIE_WIN_LANG_OS.getParen(3) == null ?
180                             "" :
181                             " " + RE_MSIE_WIN_LANG_OS.getParen(3));
182                 } else if (RE_MSIE_MAC_LANG_OS.match(agent)) {
183                     os = "MacOS";
184                     osType = OSType.MACOS;
185                 }
186             }
187             /* Mozilla has to different id's; one up to version 4
188                and a second for version >= 5
189             */

190             else if (browserName.equals("Mozilla") || browserName == null) {
191                 browserName = "Mozilla";
192                 browserType = BrowserType.MOZILLA;
193
194                 /* old mozilla */
195                 if (RE_NS_LANG_OS.match(agent)) {
196                     lang = RE_NS_LANG_OS.getParen(1);
197                     os = RE_NS_LANG_OS.getParen(2);
198                     osVersion = RE_NS_LANG_OS.getParen(3);
199
200                     if (os.equals("X")) {
201                         if (RE_NS_X11_LANG_OS.match(agent)) {
202                             os = RE_NS_X11_LANG_OS.getParen(1);
203                             osVersion = RE_NS_X11_LANG_OS.getParen(2);
204                             osType = OSType.UNIX;
205                         }
206                     }
207                 }
208                 /* NS5, NS6 Galeon etc. */
209                 else if (RE_GALEON_OS.match(agent)) {
210                     browserName = "Galeon";
211                     browserType = BrowserType.GECKO;
212                     os = RE_GALEON_OS.getParen(1);
213                     if (os.equals("X11")) {
214                         os = "Unix";
215                         osType = OSType.UNIX;
216                     }
217                     mav = RE_GALEON_OS.getParen(2);
218                     miv = RE_GALEON_OS.getParen(3);
219                 } else if (RE_NS6_LANG_OS.match(agent)) {
220                     os = RE_NS6_LANG_OS.getParen(2);
221                     lang = RE_NS6_LANG_OS.getParen(5);
222                 }
223                 /* realy seldom but is there */
224                 else if (RE_MSIE_WIN_LANG_OS.match(agent)) {
225                     os = "Windows";
226                     osType = OSType.WINDOWS;
227                     osVersion = RE_MSIE_WIN_LANG_OS.getParen(2) +
228                             (RE_MSIE_WIN_LANG_OS.getParen(3) == null ?
229                             "" :
230                             " " + RE_MSIE_WIN_LANG_OS.getParen(3));
231                 }
232                 /* Konqueror */
233                 else if (RE_KONQUEROR_OS.match(agent)) {
234                     browserName = "Konqueror";
235                     browserType = BrowserType.KONQUEROR;
236                     StringTokenizer JavaDoc strtok = new StringTokenizer JavaDoc(RE_KONQUEROR_OS.getParen(1), ".");
237                     mav = strtok.nextToken();
238                     if (strtok.hasMoreTokens())
239                         miv = strtok.nextToken();
240                     if (strtok.hasMoreTokens())
241                         release = strtok.nextToken();
242                     os = RE_KONQUEROR_OS.getParen(2);
243                 }
244                 /* f*ck, what's that ??? */
245                 else {
246                     browserName = "Mozilla";
247                     browserType = BrowserType.MOZILLA;
248                 }
249                 
250                 /* reformat browser os */
251                 if (os != null && os.startsWith("Win") &&
252                         (osVersion == null || osVersion.length() == 0)
253                 ) {
254                     osVersion = os.substring(3, os.length());
255                     os = "Windows";
256                     osType = OSType.WINDOWS;
257                 }
258                 /* just any windows */
259                 if (os != null && os.equals("Win")) {
260                     os = "Windows";
261                     osType = OSType.WINDOWS;
262                 }
263             }
264             /* Opera identified as opera, that's easy! */
265             else if (browserName.equals("Opera")) {
266                 browserType = BrowserType.OPERA;
267                 if (RE_MSIE_WIN_LANG_OS.match(agent)) {
268                     os = "Windows";
269                     osType = OSType.WINDOWS;
270                     osVersion = RE_MSIE_WIN_LANG_OS.getParen(2) +
271                             (RE_MSIE_WIN_LANG_OS.getParen(3) == null ?
272                             "" :
273                             " " + RE_MSIE_WIN_LANG_OS.getParen(3));
274                 } else if (RE_OPERA_LANG_OS.match(agent)) {
275                     os = RE_OPERA_LANG_OS.getParen(1);
276                     osVersion = RE_OPERA_LANG_OS.getParen(2);
277                     lang = RE_OPERA_LANG_OS.getParen(3);
278                 }
279             }
280             
281             /* Opera identified as something else (Mozilla, IE ...) */
282             if (RE_OPERA.match(agent)) {
283                 browserName = "Opera";
284                 browserType = BrowserType.OPERA;
285                 os = RE_OPERA.getParen(3);
286                 osVersion = RE_OPERA.getParen(4);
287                 mav = RE_OPERA.getParen(7);
288                 miv = RE_OPERA.getParen(8);
289                 lang = RE_OPERA.getParen(10);
290             }
291
292             /* detect gecko */
293             if (Gecko_Engine.match(agent)) {
294                 browserType = BrowserType.GECKO;
295                 if (Gecko_Engine.getParen(2) != null)
296                     browserName = Gecko_Engine.getParen(2);
297                 if (Gecko_Engine.getParen(3) != null)
298                     mav = Gecko_Engine.getParen(3);
299                 if (Gecko_Engine.getParen(4) != null)
300                     miv = Gecko_Engine.getParen(4);
301                 if (Gecko_Engine.getParen(5) != null)
302                     release = Gecko_Engine.getParen(5);
303             }
304             
305             /* try to find language in uncommon places if not detected before */
306             if (lang == null) {
307                 if (RE_LANG.match(agent)) {
308                     lang = RE_LANG.getParen(1);
309                 }
310             }
311
312             try {
313                 majorVersion = new Integer JavaDoc(mav).intValue();
314             } catch (NumberFormatException JavaDoc ex) {
315                 majorVersion = 0;
316             }
317
318             try {
319                 minorVersion = new Double JavaDoc("0." + miv).doubleValue();
320             } catch (NumberFormatException JavaDoc ex) {
321                 minorVersion = 0f;
322             }
323
324             if (lang == null)
325                 browserLocale = Locale.getDefault();
326             else {
327                 /* Mozilla does that, maybe any other browser too ? */
328                 lang = lang.replace('-', '_');
329
330                 /* test for country extension */
331                 StringTokenizer JavaDoc strtok = new StringTokenizer JavaDoc(lang, "_");
332                 String JavaDoc l = strtok.nextToken();
333                 if (strtok.hasMoreElements())
334                     browserLocale = new Locale JavaDoc(l, strtok.nextToken());
335                 else
336                     browserLocale = new Locale JavaDoc(l, "");
337             }
338
339             if (osType == OSType.UNKNOWN && os != null) {
340                 if (os.equals("Windows"))
341                     osType = OSType.WINDOWS;
342                 else if (os.equals("MacOS"))
343                     osType = OSType.MACOS;
344                 else if (
345                         os.equals("Linux") ||
346                         os.equals("AIX") ||
347                         os.equals("SunOS") ||
348                         os.equals("HP-UX") ||
349                         os.equals("Solaris") ||
350                         os.equals("BSD")
351                 ) {
352                     osType = OSType.UNIX;
353                 } else if (os.equals("os")) {
354                     osType = OSType.IBMOS;
355                 }
356             }
357         }
358     }
359
360     /**
361      * @return true if browser supports the following notation for CSS selectors: <code>DIV > P</code>
362      */

363     public boolean supportsCssChildSelector() {
364         return browserType != BrowserType.IE;
365     }
366
367     /**
368      * just for testing ...
369      */

370     public static void main(String JavaDoc[] args) {
371         try {
372             if (args.length != 1) {
373                 System.err.println("Usage: java " + new Browser("").getClass().getName() + " <agents file>");
374                 return;
375             }
376             FileReader JavaDoc fi = new FileReader JavaDoc(args[0]);
377             LineNumberReader JavaDoc lnr = new LineNumberReader JavaDoc(fi);
378             String JavaDoc line;
379             while ((line = lnr.readLine()) != null) {
380                 System.out.println(line);
381                 System.out.println("\t" + new Browser(line).toString());
382             }
383             fi.close();
384         } catch (Exception JavaDoc ex) {
385             ex.printStackTrace();
386         }
387     }
388
389     /**
390      * Get a full human readable representation of the browser.
391      */

392     public String JavaDoc toString() {
393         return browserName + " v" + (majorVersion + minorVersion) + (release == null ? "" : "-" + release) +
394                 "["+browserType+"], " + browserLocale + ", " + osType.getName() + ": " + os + " " + osVersion;
395     }
396
397
398 }
399
Popular Tags