"When the job ad specified that an 'enterprise' Senior Java Developer was needed, I knew I'd be in a treat for some enterprisey goodness," writes Chris B, "but what I didn't expect was the User Agent Detection Generation Framework. Here's what the API for this framework looks like."

"It's apparently designed to put an end to the extreme challenge of parsing user agent strings sent by various web browsers and devices. Here's what the UserAgent implementation looks like. I mean, an implementation; this is, naturally, extensible enough to handle any user agent parsing factory implementation."

"Based on the commit history, it took several months to create this masterpiece. There are more than forty Java classes, eight interfaces, and several hundred lines of XML configuration. Speaking of which, here's the configuration XML for Firefox:"

<!-- ============================================================================================================== -->
<!--                                                     Firefox                                                    -->
<!-- ============================================================================================================== -->

<!-- Firefox -->
<ua:UserAgent ua:id="Mozilla Firefox" ua:browser="Firefox" ua:version="$6" ua:platform="$1">
  <ua:Element ua:id="mobile" ua:type="boolean" ua:value="false" />
  <ua:Element ua:id="osName" ua:type="string" ua:value="$2" />
  <ua:Element ua:id="osVersion" ua:type="number" ua:value="$3" />
  <ua:Element ua:id="engineName" ua:type="string" ua:value="Gecko" />
  <ua:Element ua:id="engineVersion" ua:type="number" ua:value="$4" />
  <ua:Detection>
    <!-- 
      Mozilla/5.0 (Windows; U; Windows NT 5.1; nl-NL; rv:1.7.5) Gecko/20041202 Firefox/1.0
      Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.8) Gecko/20050511 Firefox/1.0.4
      Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.10) Gecko/20050716 Firefox/1.0.6
      Mozilla/5.0 (Windows; U; Windows NT 5.1; nl; rv:1.8) Gecko/20051107 Firefox/1.5
      Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1
      Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1
      Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.0.4) Gecko/20060508 Firefox/1.5.0.4 
      Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5        
		Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.3a5pre) Gecko/20100418 Minefield/3.7a5pre
		Mozilla/5.0 (Windows NT 5.1; rv:2.0b6) Gecko/20100101 Firefox/4.0b6        
    -->
    <ua:RegExp>Mozilla/5.0 \((Windows).*(Windows NT) (\d+\.\d+).*rv:(\d+\.\d+).*\).*Gecko/(\d+).*Firefox/(\d+\.\d+).*</ua:RegExp>
    <ua:RegExp>Mozilla/5.0 \(.*(Windows) (NT) (\d+\.\d+).*rv:(\d+\.\d+).*\).*Gecko/(\d+).*Firefox/(\d+\.\d+).*</ua:RegExp>
    <ua:RegExp>Mozilla/5.0 \((Windows).*(Windows NT) (\d+\.\d+).*rv:(\d+\.\d+).*\).*Gecko/(\d+).*Minefield/(\d+\.\d+).*</ua:RegExp>

    <!-- 
      Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.8) Gecko/20050609 Firefox/1.0.4
      Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.9) Gecko/20050711 Firefox/1.0.5
      Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.2) Gecko/20060308 Firefox/1.5.0.2
      Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3
      Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.6) Gecko/20060808 Fedora/1.5.0.6-2.fc5 Firefox/1.5.0.6 pango-text
      Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.8.1) Gecko/20060601 Firefox/2.0 (Ubuntu-edgy)
      Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.2) Gecko/20070220 Firefox/2.0.0.2
      Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.2) Gecko/20070221 SUSE/2.0.0.2-6.1 Firefox/2.0.0.2         
      Mozilla/5.0 (X11; U; Linux i686; en-US; rv:2.0a1pre) Gecko/2008060602 Minefield/4.0a1pre
		Mozilla/5.0 (X11; Linux x86_64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
    -->
    <ua:RegExp>Mozilla/5.0 \((X11); U; (\w+)().*rv:(\d+\.\d+).*\).*Gecko/(\d+).*Firefox/(\d+\.\d+).*</ua:RegExp>
    <ua:RegExp>Mozilla/5.0 \((X11); (\w+)().*rv:(\d+\.\d+).*\).*Gecko/(\d+).*Firefox/(\d+\.\d+).*</ua:RegExp>
    <ua:RegExp>Mozilla/5.0 \((X11); U; (\w+)().*rv:(\d+\.\d+).*\).*Gecko/(\d+).*Minefield/(\d+\.\d+).*</ua:RegExp>
    <ua:RegExp>Mozilla/5.0 \((X11); (\w+)().*rv:(\d+\.\d+).*\).*Gecko/(\d+).*Minefield/(\d+\.\d+).*</ua:RegExp>


    <!-- 
      Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7
      Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
				Mozilla/5.0 (Macintosh; Intel Mac OS X 10.5; rv:5.0) Gecko/20100101 Firefox/5.0  
    -->
    <ua:RegExp>Mozilla/5.0 \((Macintosh); U; ([^;]+)().*rv:(\d+\.\d+).*\).*Gecko/(\d+).*Firefox/(\d+\.\d+).*</ua:RegExp>
    <ua:RegExp>Mozilla/5.0 \((Macintosh); ([^;]+)().*rv:(\d+\.\d+).*\).*Gecko/(\d+).*Firefox/(\d+\.\d+).*</ua:RegExp>
	  	<ua:RegExp>Mozilla/5.0 \((Macintosh); U; ([^;]+)().*rv:(\d+\.\d+).*\).*Gecko/(\d+).*Minefield/(\d+\.\d+).*</ua:RegExp>
	  	<ua:RegExp>Mozilla/5.0 \((Macintosh); ([^;]+)().*rv:(\d+\.\d+).*\).*Gecko/(\d+).*Minefield/(\d+\.\d+).*</ua:RegExp>

  </ua:Detection>
</ua:UserAgent>