hlship      2005/06/07 07:22:08

  Modified:    .        status.xml
               framework/src/descriptor/META-INF tapestry.request.xml
               framework/src/test/org/apache/tapestry/services/impl
                        TestRequestLocaleManager.java
               framework/src/java/org/apache/tapestry/services/impl
                        RequestLocaleManagerImpl.java
               src/documentation/content/xdocs/UsersGuide localization.xml
                        configuration.xml
  Log:
  Add configuration property org.apache.tapestry.accepted-locales, used to 
limit localization to a finite set of locales.
  
  Revision  Changes    Path
  1.115     +1 -0      jakarta-tapestry/status.xml
  
  Index: status.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-tapestry/status.xml,v
  retrieving revision 1.114
  retrieving revision 1.115
  diff -u -r1.114 -r1.115
  --- status.xml        6 Jun 2005 22:28:19 -0000       1.114
  +++ status.xml        7 Jun 2005 14:22:08 -0000       1.115
  @@ -66,6 +66,7 @@
          <action type="fix" dev="HLS">Make inherited bindings (a holdover from 
the 3.0 DTDs) override (quietly) default parameter bindings.</action>
          <action type="fix" dev="HLS">Properly identify when portal mode or 
window state has changed.</action>
          <action type="add" dev="HLS">Add deprecated attribute to 
&lt;component-specification&gt; and &lt;parameter&gt;.</action>
  +       <action type="add" dev="HLS">Add configuration property 
org.apache.tapestry.accepted-locales, used to limit localization to a finite 
set of locales.</action>
       </release>
       <release version="4.0-alpha-3" date="May 16 2005">
         <action type="add" dev="HLS">Add initial support for the validator: 
binding prefix.</action>
  
  
  
  1.31      +6 -1      
jakarta-tapestry/framework/src/descriptor/META-INF/tapestry.request.xml
  
  Index: tapestry.request.xml
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tapestry/framework/src/descriptor/META-INF/tapestry.request.xml,v
  retrieving revision 1.30
  retrieving revision 1.31
  diff -u -r1.30 -r1.31
  --- tapestry.request.xml      1 Jun 2005 14:25:55 -0000       1.30
  +++ tapestry.request.xml      7 Jun 2005 14:22:08 -0000       1.31
  @@ -36,15 +36,20 @@
       
       Encapsulates the logic for extracting the locale for the current request.
       
  -    <invoke-factory model="threaded">
  +    <invoke-factory model="pooled">
         <construct class="impl.RequestLocaleManagerImpl">
           <set-service property="request" 
service-id="tapestry.globals.WebRequest"/>
           <set-object property="cookieSource" 
value="infrastructure:cookieSource"/>
           <set-service property="threadLocale" 
service-id="hivemind.ThreadLocale"/>
  +        <set-object property="acceptedLocales" 
value="app-property:org.apache.tapestry.accepted-locales"/>
         </construct>
       </invoke-factory>
     </service-point>  
     
  +  <contribution configuration-id="hivemind.FactoryDefaults">
  +    <default symbol="org.apache.tapestry.accepted-locales" value=""/>
  +  </contribution>
  +  
     <service-point id="CookieSource">
       
       Allows access to incoming HTTP cookie values for the active (per-thread) 
request.
  
  
  
  1.7       +45 -2     
jakarta-tapestry/framework/src/test/org/apache/tapestry/services/impl/TestRequestLocaleManager.java
  
  Index: TestRequestLocaleManager.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tapestry/framework/src/test/org/apache/tapestry/services/impl/TestRequestLocaleManager.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- TestRequestLocaleManager.java     18 Apr 2005 17:07:51 -0000      1.6
  +++ TestRequestLocaleManager.java     7 Jun 2005 14:22:08 -0000       1.7
  @@ -76,7 +76,7 @@
   
           Locale actual = manager.extractLocaleForCurrentRequest();
   
  -        assertSame(Locale.JAPANESE, actual);
  +        assertEquals(Locale.JAPANESE, actual);
   
           verifyControls();
       }
  @@ -175,7 +175,7 @@
   
           Locale actual = manager.extractLocaleForCurrentRequest();
   
  -        assertSame(Locale.JAPANESE, actual);
  +        assertEquals(Locale.JAPANESE, actual);
   
           verifyControls();
   
  @@ -190,4 +190,47 @@
   
           verifyControls();
       }
  +
  +    public void testGetLocaleValuesAreCached()
  +    {
  +        RequestLocaleManagerImpl manager = new RequestLocaleManagerImpl();
  +
  +        Locale l1 = manager.getLocale("en");
  +        Locale l2 = manager.getLocale("en");
  +
  +        assertSame(l1, l2);
  +    }
  +
  +    /**
  +     * Test when filtering of incoming locales is disabled.
  +     */
  +
  +    public void testFilterDisabled()
  +    {
  +        RequestLocaleManagerImpl manager = new RequestLocaleManagerImpl();
  +
  +        Locale l = manager.filterRequestedLocale("en");
  +
  +        assertEquals(Locale.ENGLISH, l);
  +    }
  +
  +    /**
  +     * Test with filtering enabled.
  +     */
  +
  +    public void testFilterEnabled()
  +    {
  +        RequestLocaleManagerImpl manager = new RequestLocaleManagerImpl();
  +        manager.setAcceptedLocales("en,fr");
  +        manager.initializeService();
  +
  +        assertEquals(Locale.ENGLISH, manager.filterRequestedLocale("en"));
  +        assertEquals(Locale.ENGLISH, manager.filterRequestedLocale("en_US"));
  +        assertEquals(Locale.FRENCH, manager.filterRequestedLocale("fr"));
  +        assertEquals(Locale.FRENCH, manager.filterRequestedLocale("fr_FR"));
  +
  +        // Unrecognized locales filter to the first accepted locale.
  +
  +        assertEquals(Locale.ENGLISH, 
manager.filterRequestedLocale("foo_bar_BAZ"));
  +    }
   }
  \ No newline at end of file
  
  
  
  1.10      +92 -13    
jakarta-tapestry/framework/src/java/org/apache/tapestry/services/impl/RequestLocaleManagerImpl.java
  
  Index: RequestLocaleManagerImpl.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/services/impl/RequestLocaleManagerImpl.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- RequestLocaleManagerImpl.java     18 Apr 2005 17:06:38 -0000      1.9
  +++ RequestLocaleManagerImpl.java     7 Jun 2005 14:22:08 -0000       1.10
  @@ -14,19 +14,23 @@
   
   package org.apache.tapestry.services.impl;
   
  +import java.util.Arrays;
  +import java.util.HashMap;
  +import java.util.HashSet;
   import java.util.Locale;
  +import java.util.Map;
  +import java.util.Set;
   
   import org.apache.hivemind.service.ThreadLocale;
   import org.apache.tapestry.TapestryConstants;
  +import org.apache.tapestry.TapestryUtils;
   import org.apache.tapestry.services.CookieSource;
   import org.apache.tapestry.services.RequestLocaleManager;
  -import org.apache.tapestry.util.StringSplitter;
   import org.apache.tapestry.web.WebRequest;
   
   /**
  - * Identifies the Locale provided by the client (either in a 
Tapestry-specific cookie, or
  - * interpolated from the HTTP header. TODO: Add the ability to "filter down" 
Locales down to a
  - * predifined set (specified using some form of HiveMInd configuration).
  + * Service tapestry.request.RequestLocaleManager. Identifies the Locale 
provided by the client
  + * (either in a Tapestry-specific cookie, or interpolated from the HTTP 
header.
    * 
    * @author Howard Lewis Ship
    * @since 4.0
  @@ -47,17 +51,85 @@
   
       private ThreadLocale _threadLocale;
   
  +    /**
  +     * Set from symbol org.apache.tapestry.accepted-locales, a 
comma-seperated list of locale names.
  +     * The first name is the default for requests that can't be matched 
against the other locale
  +     * names. May also be blank, in which case, whatever locale was provided 
in the request is
  +     * accepted (which is Tapestry 3.0 behavior).
  +     */
  +
  +    private String _acceptedLocales;
  +
  +    private Locale _defaultLocale;
  +
  +    /**
  +     * Set of locale names. Incoming requests will be matched to one of 
these locales.
  +     */
  +
  +    private Set _acceptedLocaleNamesSet = new HashSet();
  +
  +    /**
  +     * Cache of Locales, keyed on locale name.
  +     */
  +
  +    private Map _localeCache = new HashMap();
  +
  +    public void initializeService()
  +    {
  +        String[] names = TapestryUtils.split(_acceptedLocales);
  +
  +        if (names.length == 0)
  +            return;
  +
  +        _defaultLocale = getLocale(names[0]);
  +
  +        _acceptedLocaleNamesSet.addAll(Arrays.asList(names));
  +
  +    }
  +
       public Locale extractLocaleForCurrentRequest()
       {
           String localeName = 
_cookieSource.readCookieValue(TapestryConstants.LOCALE_COOKIE_NAME);
   
  -        _requestLocale = (localeName != null) ? getLocale(localeName) : 
_request.getLocale();
  +        String requestedLocale = (localeName != null) ? localeName : 
_request.getLocale()
  +                .toString();
  +
  +        _requestLocale = filterRequestedLocale(requestedLocale);
   
           _threadLocale.setLocale(_requestLocale);
   
           return _requestLocale;
       }
   
  +    /**
  +     * Converts the request locale name into a Locale instance; applies 
filters (based on
  +     * acceptedLocales) if enabled.
  +     */
  +
  +    Locale filterRequestedLocale(String localeName)
  +    {
  +        if (_acceptedLocaleNamesSet.isEmpty())
  +            return getLocale(localeName);
  +
  +        while (true)
  +        {
  +            if (_acceptedLocaleNamesSet.contains(localeName))
  +                return getLocale(localeName);
  +
  +            localeName = stripTerm(localeName);
  +
  +            if (localeName.length() == 0)
  +                return _defaultLocale;
  +        }
  +    }
  +
  +    private String stripTerm(String localeName)
  +    {
  +        int scorex = localeName.lastIndexOf('_');
  +
  +        return scorex < 0 ? "" : localeName.substring(0, scorex);
  +    }
  +
       public void persistLocale()
       {
           Locale locale = _threadLocale.getLocale();
  @@ -68,20 +140,22 @@
           _cookieSource.writeCookieValue(TapestryConstants.LOCALE_COOKIE_NAME, 
locale.toString());
       }
   
  -    private Locale getLocale(String name)
  +    Locale getLocale(String name)
       {
  -        // There used to be a cache of Locale (keyed on name), but since 
this service is
  -        // threaded, there's no point (short of making it static, which is 
too ugly for words).
  -        // Instead, we should have a LocaleCache service for that purpose. 
Have to balance
  -        // cost of invoking that service vs. the cost of creating new Locale 
instances all the time.
  +        Locale result = (Locale) _localeCache.get(name);
  +
  +        if (result == null)
  +        {
  +            result = constructLocale(name);
  +            _localeCache.put(name, result);
  +        }
   
  -        return constructLocale(name);
  +        return result;
       }
   
       private Locale constructLocale(String name)
       {
  -        StringSplitter splitter = new StringSplitter('_');
  -        String[] terms = splitter.splitToArray(name);
  +        String[] terms = TapestryUtils.split(name, '_');
   
           switch (terms.length)
           {
  @@ -115,4 +189,9 @@
       {
           _threadLocale = threadLocale;
       }
  +
  +    public void setAcceptedLocales(String acceptedLocales)
  +    {
  +        _acceptedLocales = acceptedLocales;
  +    }
   }
  \ No newline at end of file
  
  
  
  1.7       +34 -0     
jakarta-tapestry/src/documentation/content/xdocs/UsersGuide/localization.xml
  
  Index: localization.xml
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tapestry/src/documentation/content/xdocs/UsersGuide/localization.xml,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- localization.xml  18 Apr 2005 17:09:03 -0000      1.6
  +++ localization.xml  7 Jun 2005 14:22:08 -0000       1.7
  @@ -295,5 +295,39 @@
   </note>
         
       </section>
  +    
  +<section id="localization.accepted-locales">
  +  <title>Limiting accepted locales</title>
  +  
  +<p>
  +By default, Tapestry accepts incoming locales (as specified in the request 
HTTP header) as-is. The requested
  +locale is used as-is.  This has some implications, primarily in terms of 
resource usage.  
  +</p>  
  +
  +<p>
  +Imagine an application that is being accessed by users in the US, the UK and 
in Canada. The incoming request
  +locales will be "en_US", "en_UK" and "en_CA" (respectively). However, it is 
likely that you will only have
  +created a single localization, for English in general (locale "en").  
Despite this, there will be several different
  +versions of each page in the page pool: one for each of the above locales, 
even though they will be functionally identical.
  +</p>
  +
  +<p>
  +Ideally, what we want is to limit incoming requests so that all of the 
listed locales ("en_US", "en_UK" and "en_CA") will
  +be 'filtered down' to just "en".
  +</p>
  +
  +<p>
  +That functionality is controlled by the org.apache.tapestry.accepted-locales 
&configuration-property;. By setting
  +this property to a comma-seperated list of local names, incoming requests 
will be converted
  +to the closest match.  For example, the the property could be configured to 
"en,fr,de" to support English, French and German.
  +</p>
  +
  +<p>
  +Matching takes place by stripping off "terms" (the locale variant, then the 
locale country code) from the locale name.  So "en_US" would be stripped to 
"en" (which would match).
  +When no match can be found, the <em>first</em> locale in the list is treated 
as the default.  In the prior example, Russian users
  +would be matched to the "en" locale.
  +</p>
  +
  +</section>    
     </body>
   </document>
  \ No newline at end of file
  
  
  
  1.14      +10 -0     
jakarta-tapestry/src/documentation/content/xdocs/UsersGuide/configuration.xml
  
  Index: configuration.xml
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tapestry/src/documentation/content/xdocs/UsersGuide/configuration.xml,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- configuration.xml 18 Apr 2005 17:09:03 -0000      1.13
  +++ configuration.xml 7 Jun 2005 14:22:08 -0000       1.14
  @@ -325,6 +325,16 @@
     </tr>
     
     <tr>
  +    <td>org.apache.tapestry.accepted-locales</td>
  +    <td>
  +    Controls which locales are supported by the application; see the
  +    documentation on
  +    <link href="localization.html#localization.accepted-locales">limiting 
accepted locales</link>
  +    for details.
  +    </td>
  +  </tr>
  +  
  +  <tr>
        <td>org.apache.tapestry.asset.dir, org.apache.tapestry.asset.URL</td>
        
     <td>
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to