001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package com.sun.rave.web.ui.util;
042:
043: import java.util.Map;
044: import java.util.StringTokenizer;
045:
046: import javax.faces.context.FacesContext;
047:
048: /**
049: * This utility class parses the user agent of a HttpServletRequest
050: * object to determine browser type, version, and platform.
051: * <p>
052: * The code of this utility class is based on "The
053: * Ultimate JavaScript Client Sniffer", version 3.03 which is located
054: * at the following URL.
055: * </p><p>
056: * http://www.mozilla.org/docs/web-developer/sniffer/browser_type.html
057: * </p><p>
058: * Usage Example:
059: * </p><p><pre>
060: * FacesContext context = FacesContext.getCurrentInstance();
061: * ClientSniffer cs = new ClientSniffer(context);
062: *
063: * String stylesheet = CCStyle.IE6_UP_CSS;
064: *
065: * if (isIe6up()) {
066: * stylesheet = CCStyle.IE6_UP_CSS;
067: * } else if (isIe5up()) {
068: * stylesheet = CCStyle.IE5_UP_CSS;
069: * } else if (isNav6up()) {
070: * stylesheet = CCStyle.NS6_UP_CSS;
071: * } else if (isNav4up() && isWin()) {
072: * stylesheet = CCStyle.NS4_WIN_CSS;
073: * } else if (isNav4up() && isSun()) {
074: * stylesheet = CCStyle.NS4_SOL_CSS;
075: * }
076: * </pre></p><p>
077: *
078: * @version 1.10 02/06/04
079: * @author Sun Microsystems, Inc.
080: */
081: public class ClientSniffer {
082: // User Agent Headers (DON'T DELETE).
083: //
084: // Windows 2000
085: // ------------
086: //
087: // IE 5.0 Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)
088: // Netscape 4.7 Mozilla/4.7 [en] (WinNT; U)
089: // Netscape 6.2.1 mozilla/5.0 (windows; u; win98; en-us; rv:0.9.4)
090: // gecko/20011128 netscape6/6.2.1
091: // Netscape 7.02 Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US;
092: // rv:1.0.2) Gecko/20030208 Netscape/7.02
093: // Netscape 7.1 Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4)
094: // Gecko/20030624 Netscape/7.1 (ax)
095: // Mozilla 1.4 Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4)
096: // Gecko/20030624
097: //
098: // SunOS
099: // -----
100: //
101: // Netscape 4.78 Mozilla/4.78 [en] (X11; U; SunOS 5.10 sun4u)
102: // Netscape 6.2.1 mozilla/5.0 (x11; u; sunos sun4u; en-us; rv:0.9.4)
103: // gecko/20011206 netscape6/6.2.1
104: // Netscape 6.2.2 Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:0.9.4.1)
105: // Gecko/20020406 Netscape6/6.2.2
106: // Netscape 7.0 Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.0.1)
107: // Gecko/20020920 Netscape/7.0
108: // Mozilla 1.1 Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.1)
109: // Gecko/20020827
110: // HotJava 1.0.1 HotJava/1.0.1/JRE1.1.3
111: // Generic Profile/MIDP-1.0 Configuration/CLDC-1.0
112:
113: // User agent.
114: private String agent = null;
115:
116: // User agent major version number.
117: private int major = -1;
118:
119: /**
120: * Default constructor.
121: *
122: * @param context <code>FacesContext</code> which should be used to
123: * extract the user agent.
124: */
125: public ClientSniffer(FacesContext context) {
126: String version = null;
127: setUserAgent(context);
128: // <RAVE>
129: agent = getUserAgent();
130: // </RAVE>
131:
132: // Parse user agent.
133: if (agent != null) {
134:
135: StringTokenizer st = new StringTokenizer(agent, "/");
136:
137: // Parse out user agent name.
138: if (st.hasMoreTokens()) {
139: st.nextToken();
140: }
141:
142: // Get user agent version number.
143: if (st.hasMoreTokens()) {
144: version = st.nextToken();
145: }
146:
147: // Remove white space & extra info.
148: st = new StringTokenizer(version);
149:
150: if (st.hasMoreTokens()) {
151: version = st.nextToken();
152: }
153: }
154:
155: // Parse user agent major version number.
156: if (version != null) {
157: StringTokenizer st = new StringTokenizer(version, ".");
158:
159: if (st.hasMoreTokens()) {
160: try {
161: major = Integer.parseInt(st.nextToken());
162: } catch (NumberFormatException ex) {
163: // Ignore
164: }
165: }
166: }
167: }
168:
169: /**
170: * <P> This method gets an instance of this class associated with the
171: * given <code>FacesContext</code>. It will look in the request scope
172: * to see if an instance already exists, if not, it will create
173: * one.</P>
174: *
175: * @param context The <code>FacesContext</code>
176: *
177: * @return A <code>ClientSniffer</code> instance.
178: */
179: public static ClientSniffer getInstance(FacesContext context) {
180: // Look for a cached one
181: Map requestMap = context.getExternalContext().getRequestMap();
182: ClientSniffer sniffer = (ClientSniffer) requestMap
183: .get("__sniffer");
184:
185: if (sniffer == null) {
186: // Not yet created, create one
187: sniffer = new ClientSniffer(context);
188: requestMap.put("__sniffer", sniffer);
189: }
190:
191: // Return the sniffer
192: return sniffer;
193: }
194:
195: /**
196: * <P> This method initializes the user agent via the supplied
197: * <code>FacesContext</code>. It will use the
198: * <code>ExternalContext</code> to get at the request header Map.
199: * It will use this Map to obtain the value for
200: * <code>USER-AGENT</code>.</P>
201: *
202: * @param context The <code>FacesContext</code>
203: */
204: protected void setUserAgent(FacesContext context) {
205: // <RAVE>
206: Map headerMap = context.getExternalContext()
207: .getRequestHeaderMap();
208: if (null != headerMap) {
209: agent = (String) headerMap.get("USER-AGENT");
210: if (null != agent) {
211: agent = agent.toLowerCase();
212: }
213: }
214: // </RAVE>
215: }
216:
217: /**
218: * Get the user agent.
219: *
220: * @return The user agent.
221: */
222: public String getUserAgent() {
223: return agent;
224: }
225:
226: /**
227: * Get the user agent major version number.
228: *
229: * @return The user agent major version number or
230: * -1 if the version number was not retrieved.
231: */
232: public int getUserAgentMajor() {
233: return major;
234: }
235:
236: /**
237: * Test if the user agent was generated on Windows platform.
238: *
239: * @return true or false
240: */
241: public boolean isWin() {
242: boolean result = false;
243:
244: if ((agent != null)
245: && ((agent.indexOf("win") != -1) || (agent
246: .indexOf("16bit") != -1))) {
247: result = true;
248: }
249:
250: return result;
251: }
252:
253: /**
254: * Test if the user agent was generated on Sun platform.
255: *
256: * @return true or false
257: */
258: public boolean isSun() {
259: boolean result = false;
260:
261: if ((agent != null) && (agent.indexOf("sunos") != -1)) {
262: result = true;
263: }
264:
265: return result;
266: }
267:
268: /**
269: * Test if the user agent was generated by Gecko engine.
270: *
271: * @return true or false
272: */
273: public boolean isGecko() {
274: boolean result = false;
275:
276: if ((agent != null) && (agent.indexOf("gecko") != -1)) {
277: result = true;
278: }
279:
280: return result;
281: }
282:
283: /**
284: * Test if the user agent was generated by Navigator.
285: *
286: * @return true or false
287: */
288: public boolean isNav() {
289: boolean result = false;
290:
291: if ((agent != null) && (agent.indexOf("mozilla") != -1)
292: && (agent.indexOf("spoofer") == -1)
293: && (agent.indexOf("compatible") == -1)
294: && (agent.indexOf("opera") == -1)
295: && (agent.indexOf("webtv") == -1)
296: && (agent.indexOf("hotjava") == -1)) {
297: // The header for Netscape 4.x is similar to the header
298: // for the Mozilla browser; however, Netscape 4.x does not
299: // implement the Gecko engine.
300: if (!(isGecko() && (agent.indexOf("netscape") == -1))) {
301: result = true;
302: }
303: }
304:
305: return result;
306: }
307:
308: /**
309: * Test if the user agent was generated by Navigator,
310: * version 4.x.
311: *
312: * @return true or false
313: */
314: public boolean isNav4() {
315: boolean result = false;
316:
317: if (isNav() && (major == 4)) {
318: result = true;
319: }
320:
321: return result;
322: }
323:
324: /**
325: * Test if the user agent was generated by Navigator,
326: * version 4.x or above.
327: *
328: * @return true or false
329: */
330: public boolean isNav4up() {
331: boolean result = false;
332:
333: if (isNav() && (major >= 4)) {
334: result = true;
335: }
336:
337: return result;
338: }
339:
340: /**
341: * Test if the user agent was generated by Navigator,
342: * version 6.x.
343: *
344: * @return true or false
345: */
346: public boolean isNav6() {
347: boolean result = false;
348: // <RAVE>
349: if (isNav() && (major == 5) && (null != agent)
350: && (agent.indexOf("netscape6") != -1)) {
351: // </RAVE>
352: result = true;
353: }
354:
355: return result;
356: }
357:
358: /**
359: * Test if the user agent was generated by Navigator,
360: * version 6.x or above.
361: *
362: * @return true or false
363: */
364: public boolean isNav6up() {
365: boolean result = false;
366:
367: if (isNav() && major >= 5) {
368: result = true;
369: }
370:
371: return result;
372: }
373:
374: /**
375: * Test if the user agent was generated by Navigator,
376: * version 7.x.
377: *
378: * @return true or false
379: */
380: public boolean isNav7() {
381: boolean result = false;
382: // <RAVE>
383: if (isNav() && major == 5 && (null != agent)
384: && (agent.indexOf("netscape/7") != -1)) {
385: // </RAVE>
386: result = true;
387: }
388:
389: return result;
390: }
391:
392: /**
393: * Test if the user agent was generated by Navigator,
394: * version 7.0.
395: *
396: * @return true or false
397: */
398: public boolean isNav70() {
399: boolean result = false;
400: // <RAVE>
401: if (isNav() && major == 5 && (null != agent)
402: && (agent.indexOf("netscape/7.0") != -1)) {
403: // </RAVE>
404: result = true;
405: }
406:
407: return result;
408: }
409:
410: /**
411: * Test if the user agent was generated by Navigator,
412: * version 7.x or above.
413: *
414: * @return true or false
415: */
416: public boolean isNav7up() {
417: boolean result = false;
418:
419: if (isNav() && (major >= 5) && !isNav4() && !isNav6()) {
420: result = true;
421: }
422:
423: return result;
424: }
425:
426: /**
427: * Test if the user agent was generated by Internet Explorer.
428: *
429: * @return true or false
430: */
431: public boolean isIe() {
432: boolean result = false;
433:
434: if ((agent != null) && (agent.indexOf("msie") != -1)
435: && (agent.indexOf("opera") == -1)) {
436: result = true;
437: }
438:
439: return result;
440: }
441:
442: /**
443: * Test if the user agent was generated by Internet Explorer,
444: * version 3.x.
445: *
446: * @return true or false
447: */
448: public boolean isIe3() {
449: boolean result = false;
450:
451: if (isIe() && (major < 4)) {
452: result = true;
453: }
454:
455: return result;
456: }
457:
458: /**
459: * Test if the user agent was generated by Internet Explorer,
460: * version 4.x.
461: *
462: * @return true or false
463: */
464: public boolean isIe4() {
465: boolean result = false;
466: // <RAVE>
467: if (isIe() && (major == 4) && (null != agent)
468: && (agent.indexOf("msie 4") != -1)) {
469: // </RAVE>
470: result = true;
471: }
472:
473: return result;
474: }
475:
476: /**
477: * Test if the user agent was generated by Internet Explorer,
478: * version 5.x.
479: *
480: * @return true or false
481: */
482: public boolean isIe5() {
483: boolean result = false;
484: // <RAVE>
485: if (isIe() && (major == 4) && (null != agent)
486: && (agent.indexOf("msie 5") != -1)) {
487: // </RAVE>
488: result = true;
489: }
490:
491: return result;
492: }
493:
494: /**
495: * Test if the user agent was generated by Internet Explorer,
496: * version 5.x or above.
497: *
498: * @return true or false
499: */
500: public boolean isIe5up() {
501: boolean result = false;
502:
503: if (isIe() && !isIe3() && !isIe4()) {
504: result = true;
505: }
506:
507: return result;
508: }
509:
510: /**
511: * Test if the user agent was generated by Internet Explorer,
512: * version 6.x.
513: *
514: * @return true or false
515: */
516: public boolean isIe6() {
517: boolean result = false;
518: // <RAVE>
519: if (isIe() && (major == 4) && (null != agent)
520: && (agent.indexOf("msie 6") != -1)) {
521: // </RAVE>
522: result = true;
523: }
524:
525: return result;
526: }
527:
528: /**
529: * Test if the user agent was generated by Internet Explorer,
530: * version 6.x or above.
531: *
532: * @return true or false
533: */
534: public boolean isIe6up() {
535: boolean result = false;
536:
537: if (isIe() && !isIe3() && !isIe4() && !isIe5()) {
538: result = true;
539: }
540:
541: return result;
542: }
543:
544: /**
545: * This method is used by the Theme.
546: *
547: * @param context The <code>FacesContext</code>
548: *
549: * @return The {@link ClientType}.
550: */
551: public static ClientType getClientType(FacesContext context) {
552: // </RAVE>
553: Map map = context.getExternalContext().getRequestHeaderMap();
554: if (null == map) {
555: return ClientType.OTHER;
556: }
557: String agent = (String) map.get("USER-AGENT");
558:
559: if (agent == null) {
560: return ClientType.OTHER;
561: }
562: // </RAVE>
563: agent = agent.toLowerCase();
564: if (agent.indexOf("gecko") != -1) {
565: return ClientType.GECKO;
566: } else if (agent.indexOf("msie 6") != -1) {
567: return ClientType.IE6;
568: } else if (agent.indexOf("msie 5.5") != -1) {
569: return ClientType.IE5_5;
570: } else {
571: return ClientType.OTHER;
572: }
573: }
574: }
|