Gatein Mobile Detection And Redirection Mapping: XML Configuration

Version 5

    XML Configuration File

     

    location: /config/gatein/gatein-site-redirection.xml

     

    <device-configuration>
    <device-redirects>
       <device-redirect>
        <!-- initial site accessed by user -->
        <origin-site>foo</origin-site>
        <redirects>
         <redirect>
           <!-- redirect site to use if any condition is met -->
           <redirect-site>bar</redirect-site>
           <enabled>true</enabled> <!-- true by default -->
           <conditions>
             <condition>
                <!-- a condition to be met in order to perform a redirect -->
                ...
             </condition>
             <condition>
               <!-- another condition, only looked at if the first condition is not met -->
               ...
             </condition>
           </conditions>
           <mappings>
              <!-- node mappings between servers -->
              ...
           </mappings>
         </redirect>
         <redirect>
           <redirect-site>foo</redirect-site>
           ...
         </redirect>
        </redirects>
    </device-redirect>
    <device-redirect>
       <!-- another site to consider for redirection-->
        ...
    </device-redirect>
    <device-redirects>
    </device-configuration>
    

     

    Notes:

    • Each site can have multiple redirect sites (ie a site can have a redirect for a phone site and a tablet site, or another device site).
    • Ordering matters. The redirects and condition checks will be done in a sequential manner and will stop on the first positive result.
    • A match is considered if any one <condition> is true. Each child <condition> should be thought of as a OR operation.
    • The <mappings> element can only appear once and controls how the mapping between the nodes on the origin site and redirect site

     

     

    Redirection Conditions

    User-Agent

    <condition>
      <user-agent>
        <contains>foo</contains>
        <does-not-contain>bar</does-not-contain>
      </user-agent>
    </condition>
    

     

    Allows for pattern matching in the User Agent string. Performs a Matcher.find using java.util.regex.Pattern to determine if the string contains the pattern or not.

    • <contains>: if the user agent string contains this pattern
    • <does-not-contain>: if the user agent string does not contain this pattern

     

    A user agent condition can contain multiple <contains> and <does-not-contain> elements. The condition is considered to pass if any of the <contains> is found in the user agent string but none of the <does-not-contain>.

     

    Note: Patterns are considered case-sensitive by default, but can be toggled on or off using (?i) and (?-i)

     

    User-Agent Condition Examples

    If the condition should pass if 'foo' OR 'bar' is found in the user agent string:

    <condition>
      <user-agent>
        <contains>foo</contains>
        <contains>bar</contains>
      </user-agent>
    </condition>
    

     

    Note: Also possible to use Pattern syntax to handle OR:

    <condition>
      <user-agent>
        <contains>foo|bar</contains>
      </user-agent>
    </condition>
    

     

    If we wish the condition to pass if the user agent string contains for AND bar, we need to use a slightly more complex Pattern (this does a real AND where the order doesn't matter)

    <condition>
      <user-agent>
        <contains>(?=.*foo)(?=.*bar)</contains>
      </user-agent>
    </condition>
    

     

    If we want to check if foo AND bar exist, and foo always comes before bar, we can check with:

    <condition>
      <user-agent>
        <contains>foo.*bar</contains>
      </user-agent>
    </condition>
    

     

    The following condition will be considered a pass if the user agent does not contain ('foo' AND 'bar') or if does not contain 'baz'

    <condition>
      <user-agent>
        <does-not-contain>(?=.*foo)(?=.*bar)</does-not-contain>
        <does-not-contain>baz</does-not-contain>
      </user-agent>
    </condition>
    

    More Complex Example:

    Passes If the user agent:

    contains any of: Android (case insensitive), ipod, or iphone

    But not ipad or Fennec

    <condition>
      <user-agent>
        <contains>(?i)android</contains>
        <contains>ip(od|phone)</contains>
        <does-not-contain>ipad</does-not-contain>
        <does-not-contain>Fennec</does-not-contain>
      </user-agent>
    </condition>
    

     

     

    Device Property

     

    <condition>
      <device-property>
        <name>foo</name>
        <less-than>1000</less-than>
        <greater-than>400</greater-than>
      </user-agent>
    </condition>
    

     

    Allows for matching against a specific device property. The follow options are available:

    • <name>: the property name
    • <matches>: a pattern to match against (uses java.util.regex.Pattern and Matcher.matches not Matcher.find)
    • <less-than>: if the property value is less than this number
    • <greater-than>: if the property value is greater than this number
    • <equals>: if the property equals this value

     

    Note: If a condition has multiple device-properties, then ALL device properties must match. If you wish to handle OR you must use multiple conditions.

     

     

    Device Property Condition Examples

     

    If the device property 'foo' is less-than 1000:

    <condition>
      <device-property>
        <name>foo</name>
        <less-than>1000</less-than>
      </device-property>
    </condition>
    

     

     

    If the device property 'foo' is between 1000 and 500:

    <condition>
      <device-property>
        <name>foo</name>
        <less-than>1000</less-than>
        <greater-than>500</greater-than>
      </device-property>
    </condition>
    

     

    If the device property 'foo' equals 'true':

    <condition>
      <device-property>
        <name>foo</name>
        <equals>true</equals>
      </device-property>
    </condition>
    

     

    If the device property 'foo' matches a pattern

    <condition>
      <device-property>
        <name>foo</name>
        <matches>^foobar.*</matches> <!-- in this case it has to start with foobar but can end in anything -->
      </device-property>
    </condition>
    

     

    If the device property 'foo' is true, AND device property 'bar' is greater than 500.

    <condition>
      <device-property>
        <name>foo</name>
        <equals>true</equals>
      </device-property>
      <device-property>
        <name>bar</name>
        <greater-than>500</greater-than>
      </device-property>
    </condition>
    

     

    If the device property 'foo' is true, OR device property 'bar' is greater than 500. In this situation we must use two conditions

    <condition>
      <device-property>
        <name>foo</name>
        <equals>true</equals>
      </device-property>
    </condition>
    <condition>
      <device-property>
        <name>bar</name>
        <greater-than>500</greater-than>
      </device-property>
    </condition>
    

     

    Examples Using Both User-Agent and Device Properties.

     

    If the user agent contains 'Android' AND the device property 'device.width' is less than 1000.

    <condition>
      <user-agent>
        <contains>Android</contains>
      </user-agent>
      <device-property>
        <name>device.width</name>
        <less-than>1000</less-than>
      </device-property>
    </condition>
    

     

    If the user agent contains 'Android' OR the device property 'device.width' is less than 1000

    <condition>
      <user-agent>
        <contains>Android</contains>
      </user-agent>
    </condition>
    <condition>
      <device-property>
        <name>device.width</name>
        <less-than>1000</less-than>
      </device-property>
    </condition>
    

    Node Mappings

     

    Specifies the mapping between the origin site and the redirect site.

     

    <node-mapping>
      <use-node-name-mapping>true</use-node-name-mapping>
      <unresolved-nodes>REDIRECT</unresolved-nodes>
      <node-map>
        <origin-node>foo</origin-node>
        <redirect-node>foo_1</redirect-node>
      </node-map>
      <node-map>
        <origin-node>bar</orgin-node>
        <redirect-node>bar_1</redirect-node>
      </node-map>
    </node-mapping>
    

     

    Mapping configuration options:

    • <node-map> : explicity specify a mapping between a specific node on the origin site and a specific node on the redirect site
    • <user-node-name-mapping> : specify if node name maching should be used or not (default true).
      • this will perform a redirect if the node names are the same between the sites
    • <unresolved-nodes> : how to handle if we encounter a node on the origin site which doesn't exist on the redirect site. Possible options are:
      • NO_REDIRECT: go to the origin site instead
      • REDIRECT : perform the redirect anyway and let the redirect site take care of trying to configure the node from the url
      • ROOT: perform a redirect to the root of the redirect site (ie no node specified on the redirect).
      • COMMON_ANCESTOR_NAME_MATCH: try and match to the names of the parent nodes, it no match will redirect to the root of the redirect site

     

    Node Mapping Examples

     

     

    Always just redirect to the root node. Doesn't check if nodes exist or not. Useful if the mobile site is drastically different in content and redirection based on mappings doesn't make sense

    <node-mapping>
      <use-node-name-mapping>false</use-node-name-mapping>
      <unresolved-nodes>ROOT</unresolved-nodes>
    </node-mapping>
    

     

    Don't perform any mapping checks, just change the site name in the url for the redirect. Useful if the node names are the same between the origin and redirect site and/or you don't want to waste time performing checks if the node exists or not.

    <node-mapping>
      <use-node-name-mapping>false</use-node-name-mapping>
      <unresolved-nodes>REDIRECT</unresolved-nodes>
    </node-mapping>
    

     

    Redirect to /bar if the request node on the origin site is /foo, otherwise redirect to the root of the redirect site

    <node-mapping>
      <use-node-name-mapping>false</use-node-name-mapping>
      <unresolved-nodes>REDIRECT</unresolved-nodes>
      <node-map>
         <origin-node>/foo</origin-node>
         <redirect-node>/bar<redirect-node>
      </node-map>
    </node-mapping>
    

     

    Redirect to /site_map is the origin node is /sitemap, otherwise just map based on the node names. If no node on the other site exists, then don't do a redirect. Useful if you want to make sure that a URL takes you to the node specified.

    <node-mapping>
      <use-node-name-mapping>true</use-node-name-mapping>
      <unresolved-nodes>NO_REDIRECT</unresolved-nodes>
      <node-map>
         <origin-node>/sitemap</origin-node>
         <redirect-node>/site_map<redirect-node>
      </node-map>
    </node-mapping>