Author: hlship
Date: Tue Nov 28 11:36:06 2006
New Revision: 480168

URL: http://svn.apache.org/viewvc?view=rev&rev=480168
Log:
Begin adding infrastructure to support localization.

Added:
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LocalizationFilter.java
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LocalizationFilterTest.java
Modified:
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Translator.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationException.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Validator.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/CheckForUpdatesFilter.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/WebRequestImpl.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/WebRequest.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/conf.apt
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/reload.apt

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Translator.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Translator.java?view=diff&rev=480168&r1=480167&r2=480168
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Translator.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Translator.java
 Tue Nov 28 11:36:06 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.apache.tapestry;
 
 /**

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationException.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationException.java?view=diff&rev=480168&r1=480167&r2=480168
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationException.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ValidationException.java
 Tue Nov 28 11:36:06 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.apache.tapestry;
 
 /**

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Validator.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Validator.java?view=diff&rev=480168&r1=480167&r2=480168
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Validator.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Validator.java
 Tue Nov 28 11:36:06 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.apache.tapestry;
 
 import sun.security.validator.ValidatorException;

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/CheckForUpdatesFilter.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/CheckForUpdatesFilter.java?view=diff&rev=480168&r1=480167&r2=480168
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/CheckForUpdatesFilter.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/CheckForUpdatesFilter.java
 Tue Nov 28 11:36:06 2006
@@ -12,98 +12,103 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.internal.services;
-
-import java.io.IOException;
-
-import org.apache.tapestry.internal.util.Holder;
+package org.apache.tapestry.internal.services;
+
+import java.io.IOException;
+
+import org.apache.tapestry.internal.util.Holder;
 import org.apache.tapestry.ioc.internal.util.ConcurrentBarrier;
 import org.apache.tapestry.ioc.internal.util.Invokable;
-import org.apache.tapestry.services.WebRequest;
-import org.apache.tapestry.services.WebRequestFilter;
-import org.apache.tapestry.services.WebRequestHandler;
-import org.apache.tapestry.services.WebResponse;
-
-/**
- * Implements a barrier that periodically asks the
- * [EMAIL PROTECTED] org.apache.tapestry.internal.services.UpdateListenerHub} 
to check for updates to files.
- * The UpdateListenerHub is invoked from a write method, meaning that when it 
is called, all other
- * threads will be blocked.
- * <p>
- * TODO: Allow the check interval to be configurable, to reflect a production 
environment
- */
-public class CheckForUpdatesFilter implements WebRequestFilter
-{
-    private long _lastCheck = 0;
-
-    private long _checkInterval = 10; // ms
-
-    private final UpdateListenerHub _updateListenerHub;
-
-    private final ConcurrentBarrier _barrier = new ConcurrentBarrier();
-
-    public CheckForUpdatesFilter(UpdateListenerHub updateListenerHub)
-    {
-        _updateListenerHub = updateListenerHub;
-    }
-
-    public boolean service(final WebRequest request, final WebResponse 
response,
-            final WebRequestHandler handler) throws IOException
-    {
-        final Holder<IOException> exceptionHolder = new Holder<IOException>();
-
-        Invokable<Boolean> invokable = new Invokable<Boolean>()
-        {
-            public Boolean invoke()
-            {
-                if (System.currentTimeMillis() - _lastCheck >= _checkInterval)
-                    runCheck();
-
-                try
-                {
-                    return handler.service(request, response);
-                }
-                catch (IOException ex)
-                {
-                    exceptionHolder.put(ex);
-                    return false;
-                }
-            }
-        };
-
-        boolean result = _barrier.withRead(invokable);
-
-        IOException ex = exceptionHolder.get();
-
-        if (ex != null)
-            throw ex;
-
-        return result;
-    }
-
-    private void runCheck()
-    {
-        Runnable runnable = new Runnable()
-        {
-            public void run()
-            {
-                // On a race condition, multiple threads may hit this method 
briefly. If we've
-                // already done a check, don't run it again.
-
-                if (System.currentTimeMillis() - _lastCheck >= _checkInterval)
-                {
-
-                    // Fire the update event which will force a number of 
checks and then
-                    // corresponding invalidation events.
-
-                    _updateListenerHub.fireUpdateEvent();
-
-                    _lastCheck = System.currentTimeMillis();
-                }
-            }
-        };
-
-        _barrier.withWrite(runnable);
-    }
-
-}
+import org.apache.tapestry.services.WebRequest;
+import org.apache.tapestry.services.WebRequestFilter;
+import org.apache.tapestry.services.WebRequestHandler;
+import org.apache.tapestry.services.WebResponse;
+
+/**
+ * Implements a barrier that periodically asks the
+ * [EMAIL PROTECTED] org.apache.tapestry.internal.services.UpdateListenerHub} 
to check for updates to files.
+ * The UpdateListenerHub is invoked from a write method, meaning that when it 
is called, all other
+ * threads will be blocked.
+ */
+public class CheckForUpdatesFilter implements WebRequestFilter
+{
+    private long _lastCheck = 0;
+
+    private final long _checkInterval;
+
+    private final UpdateListenerHub _updateListenerHub;
+
+    private final ConcurrentBarrier _barrier = new ConcurrentBarrier();
+
+    private final Runnable _checker = new Runnable()
+    {
+        public void run()
+        {
+            // On a race condition, multiple threads may hit this method 
briefly. If we've
+            // already done a check, don't run it again.
+
+            if (System.currentTimeMillis() - _lastCheck >= _checkInterval)
+            {
+
+                // Fire the update event which will force a number of checks 
and then
+                // corresponding invalidation events.
+
+                _updateListenerHub.fireUpdateEvent();
+
+                _lastCheck = System.currentTimeMillis();
+            }
+        }
+    };
+
+    /**
+     * @param updateListenerHub
+     *            invoked, at intervals, to spur the process of detecting 
changes
+     * @param checkInterval
+     *            interval, in milliseconds, between checks
+     */
+    public CheckForUpdatesFilter(UpdateListenerHub updateListenerHub, long 
checkInterval)
+    {
+        _updateListenerHub = updateListenerHub;
+        _checkInterval = checkInterval;
+    }
+
+    public boolean service(final WebRequest request, final WebResponse 
response,
+            final WebRequestHandler handler) throws IOException
+    {
+        final Holder<IOException> exceptionHolder = new Holder<IOException>();
+
+        Invokable<Boolean> invokable = new Invokable<Boolean>()
+        {
+            public Boolean invoke()
+            {
+                if (System.currentTimeMillis() - _lastCheck >= _checkInterval)
+                    _barrier.withWrite(_checker);
+
+                // And, now, back to code within the read lock.
+                
+                try
+                {
+                    return handler.service(request, response);
+                }
+                catch (IOException ex)
+                {
+                    exceptionHolder.put(ex);
+                    return false;
+                }
+            }
+        };
+
+        // Obtain a read lock while handling the request. This will not impair 
parallel operations, except when a file check
+        // is needed (the exclusive write lock will block threads attempting 
to get a read lock).
+        
+        boolean result = _barrier.withRead(invokable);
+
+        IOException ex = exceptionHolder.get();
+
+        if (ex != null)
+            throw ex;
+
+        return result;
+    }
+
+}

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java?view=diff&rev=480168&r1=480167&r2=480168
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java
 Tue Nov 28 11:36:06 2006
@@ -30,6 +30,7 @@
 import org.apache.tapestry.internal.util.IntegerRange;
 import org.apache.tapestry.ioc.Location;
 import org.apache.tapestry.ioc.LogSource;
+import org.apache.tapestry.ioc.MappedConfiguration;
 import org.apache.tapestry.ioc.OrderedConfiguration;
 import org.apache.tapestry.ioc.annotations.Contribute;
 import org.apache.tapestry.ioc.annotations.Id;
@@ -43,6 +44,7 @@
 import org.apache.tapestry.ioc.services.LoggingDecorator;
 import org.apache.tapestry.ioc.services.PropertyAccess;
 import org.apache.tapestry.ioc.services.ThreadCleanupHub;
+import org.apache.tapestry.ioc.services.ThreadLocale;
 import org.apache.tapestry.ioc.services.TypeCoercer;
 import org.apache.tapestry.services.ApplicationInitializer;
 import org.apache.tapestry.services.ApplicationInitializerFilter;
@@ -56,6 +58,7 @@
 import org.apache.tapestry.services.PersistentFieldManager;
 import org.apache.tapestry.services.PersistentFieldStrategy;
 import org.apache.tapestry.services.RequestExceptionHandler;
+import org.apache.tapestry.services.RequestGlobals;
 import org.apache.tapestry.services.WebContext;
 import org.apache.tapestry.services.WebRequest;
 import org.apache.tapestry.services.WebRequestFilter;
@@ -236,12 +239,27 @@
      * before:*.*.
      */
     @Contribute("tapestry.WebRequestHandler")
-    public void 
contributeWebRequestFilters(OrderedConfiguration<WebRequestFilter> 
configuration)
+    public void 
contributeWebRequestFilters(OrderedConfiguration<WebRequestFilter> 
configuration,
+            @InjectService("tapestry.RequestGlobals")
+            final RequestGlobals requestGlobals, 
@InjectService("tapestry.ioc.ThreadLocale")
+            ThreadLocale threadLocale, 
@Inject("${tapestry.file-check-interval}")
+            long checkInterval, @Inject("${tapestry.supported-locales}")
+            String localeNames)
     {
-        configuration.add(
-                "CheckForUpdates",
-                new CheckForUpdatesFilter(_updateListenerHub),
-                "before:*.*");
+        configuration.add("CheckForUpdates", new 
CheckForUpdatesFilter(_updateListenerHub,
+                checkInterval), "before:*.*");
+
+        configuration.add("Localization", new LocalizationFilter(threadLocale, 
localeNames));
+    }
+
+    /**
+     * Contributes factory defaults that map be overridden.
+     */
+    @Contribute("tapestry.ioc.FactoryDefaults")
+    public void contributeFactoryDefaults(MappedConfiguration<String, String> 
configuration)
+    {
+        configuration.add("tapestry.file-check-interval", "1000"); // 1 second
+        configuration.add("tapestry.supported-locales", "en");
     }
 
     /**

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LocalizationFilter.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LocalizationFilter.java?view=auto&rev=480168
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LocalizationFilter.java
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LocalizationFilter.java
 Tue Nov 28 11:36:06 2006
@@ -0,0 +1,127 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.internal.services;
+
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newSet;
+import static 
org.apache.tapestry.ioc.internal.util.CollectionFactory.newThreadSafeMap;
+
+import java.io.IOException;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tapestry.ioc.services.ThreadLocale;
+import org.apache.tapestry.services.WebRequest;
+import org.apache.tapestry.services.WebRequestFilter;
+import org.apache.tapestry.services.WebRequestHandler;
+import org.apache.tapestry.services.WebResponse;
+
+/**
+ * Responsible for determining the locale for the current request. Currently, 
this is based on the
+ * client's web browser. Later extensions will store the current locale as a 
cookie, or as a session
+ * attribute.
+ */
+public class LocalizationFilter implements WebRequestFilter
+{
+    private final ThreadLocale _threadLocale;
+
+    private final Locale _defaultLocale;
+
+    private final Set<String> _acceptedLocaleNames;
+
+    private final Map<String, Locale> _localeCache = newThreadSafeMap();
+
+    public LocalizationFilter(ThreadLocale threadLocale, String 
acceptedLocaleNames)
+    {
+        _threadLocale = threadLocale;
+
+        String[] names = acceptedLocaleNames.split(",");
+
+        _defaultLocale = toLocale(names[0]);
+
+        _acceptedLocaleNames = newSet(names);
+    }
+
+    Locale toLocale(String localeName)
+    {
+        Locale result = _localeCache.get(localeName);
+
+        if (result == null)
+        {
+            result = constructLocale(localeName);
+            _localeCache.put(localeName, result);
+        }
+
+        return result;
+    }
+
+    private Locale constructLocale(String name)
+    {
+        String[] terms = name.split("_");
+
+        switch (terms.length)
+        {
+            case 1:
+                return new Locale(terms[0], "");
+
+            case 2:
+                return new Locale(terms[0], terms[1]);
+
+            case 3:
+
+                return new Locale(terms[0], terms[1], terms[2]);
+
+            default:
+
+                throw new IllegalArgumentException();
+        }
+    }
+
+    public boolean service(WebRequest request, WebResponse response, 
WebRequestHandler handler)
+            throws IOException
+    {
+        Locale locale = extractLocaleFromRequest(request);
+
+        _threadLocale.setLocale(locale);
+
+        return handler.service(request, response);
+    }
+
+    public Locale extractLocaleFromRequest(WebRequest request)
+    {
+        String localeName = request.getLocale().toString();
+
+        while (true)
+        {
+            if (_acceptedLocaleNames.contains(localeName))
+                return toLocale(localeName);
+
+            localeName = stripTerm(localeName);
+
+            if (localeName.length() == 0)
+                break;
+        }
+
+        return _defaultLocale;
+    }
+
+    static String stripTerm(String localeName)
+    {
+        int scorex = localeName.lastIndexOf('_');
+
+        return scorex < 0 ? "" : localeName.substring(0, scorex);
+    }
+
+}

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/WebRequestImpl.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/WebRequestImpl.java?view=diff&rev=480168&r1=480167&r2=480168
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/WebRequestImpl.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/WebRequestImpl.java
 Tue Nov 28 11:36:06 2006
@@ -12,60 +12,66 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.internal.services;
-
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-
+package org.apache.tapestry.internal.services;
+
+import java.util.List;
+import java.util.Locale;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
 import org.apache.tapestry.ioc.internal.util.InternalUtils;
-import org.apache.tapestry.services.WebRequest;
-import org.apache.tapestry.services.WebSession;
-
-/**
- * Basic implementation of [EMAIL PROTECTED] 
org.apache.tapestry.services.WebRequest} that wraps around an
- * [EMAIL PROTECTED] javax.servlet.http.HttpServletRequest}.
- */
-public class WebRequestImpl implements WebRequest
-{
-    private final HttpServletRequest _request;
-
-    public WebRequestImpl(HttpServletRequest request)
-    {
-        _request = request;
-    }
-
-    public List<String> getParameterNames()
-    {
-        return InternalUtils.toList(_request.getParameterNames());
-    }
-
-    public String getParameter(String name)
-    {
-        return _request.getParameter(name);
-    }
-
-    public String[] getParameters(String name)
-    {
-        return _request.getParameterValues(name);
-    }
-
-    public String getPath()
-    {
-        return _request.getServletPath();
-    }
-
-    public String getContextPath()
-    {
-        return _request.getContextPath();
-    }
-
-    public WebSession getSession(boolean create)
-    {
-        HttpSession session = _request.getSession(create);
-
-        return session == null ? null : new WebSessionImpl(session);
-    }
-
-}
+import org.apache.tapestry.services.WebRequest;
+import org.apache.tapestry.services.WebSession;
+
+/**
+ * Basic implementation of [EMAIL PROTECTED] 
org.apache.tapestry.services.WebRequest} that wraps around an
+ * [EMAIL PROTECTED] javax.servlet.http.HttpServletRequest}.
+ */
+public class WebRequestImpl implements WebRequest
+{
+    private final HttpServletRequest _request;
+
+    public WebRequestImpl(HttpServletRequest request)
+    {
+        _request = request;
+    }
+
+    public List<String> getParameterNames()
+    {
+        return InternalUtils.toList(_request.getParameterNames());
+    }
+
+    public String getParameter(String name)
+    {
+        return _request.getParameter(name);
+    }
+
+    public String[] getParameters(String name)
+    {
+        return _request.getParameterValues(name);
+    }
+
+    public String getPath()
+    {
+        return _request.getServletPath();
+    }
+
+    public String getContextPath()
+    {
+        return _request.getContextPath();
+    }
+
+    public WebSession getSession(boolean create)
+    {
+        HttpSession session = _request.getSession(create);
+
+        return session == null ? null : new WebSessionImpl(session);
+    }
+
+    public Locale getLocale()
+    {
+        return _request.getLocale();
+    }
+
+}

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/WebRequest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/WebRequest.java?view=diff&rev=480168&r1=480167&r2=480168
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/WebRequest.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/WebRequest.java
 Tue Nov 28 11:36:06 2006
@@ -12,52 +12,56 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.services;
-
-import java.util.List;
-
-/**
- * Generic version of [EMAIL PROTECTED] javax.servlet.http.HttpServletRequest}.
- */
-public interface WebRequest
-{
-    /** Returns a list of query parameter names, in alphabetical order. */
-    List<String> getParameterNames();
-
-    /**
-     * Returns the query parameter value for the given name. Returns null if 
no such parameter is in
-     * the request. For a multi-valued parameter, returns just the first value.
-     */
-    String getParameter(String name);
-
-    /**
-     * Returns the parameter values for the given name. Returns null if no 
such parameter is in the
-     * request.
-     */
-    String[] getParameters(String name);
-
-    /**
-     * Returns the path portion of the request, which starts with a "/" and 
contains everything up
-     * to the start of the query parameters. It doesn't include the context 
path.
-     * 
-     * @return
-     */
-    String getPath();
-
-    /**
-     * Returns the context path portion of the URI. This always starts with a 
"/" character and does
-     * not end with one, with the exception of servlets in the root context, 
which return the empty
-     * string.
-     */
-    String getContextPath();
-
-    /**
-     * Gets the [EMAIL PROTECTED] WebSession}. If create is false and the 
session has not be created
-     * previously, returns null.
-     * 
-     * @param create
-     *            true to force the creation of the session
-     * @return the session (or null if create is false the session has not 
been previously created)
-     */
-    WebSession getSession(boolean create);
-}
+package org.apache.tapestry.services;
+
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Generic version of [EMAIL PROTECTED] javax.servlet.http.HttpServletRequest}.
+ */
+public interface WebRequest
+{
+    /** Returns a list of query parameter names, in alphabetical order. */
+    List<String> getParameterNames();
+
+    /**
+     * Returns the query parameter value for the given name. Returns null if 
no such parameter is in
+     * the request. For a multi-valued parameter, returns just the first value.
+     */
+    String getParameter(String name);
+
+    /**
+     * Returns the parameter values for the given name. Returns null if no 
such parameter is in the
+     * request.
+     */
+    String[] getParameters(String name);
+
+    /**
+     * Returns the path portion of the request, which starts with a "/" and 
contains everything up
+     * to the start of the query parameters. It doesn't include the context 
path.
+     * 
+     * @return
+     */
+    String getPath();
+
+    /**
+     * Returns the context path portion of the URI. This always starts with a 
"/" character and does
+     * not end with one, with the exception of servlets in the root context, 
which return the empty
+     * string.
+     */
+    String getContextPath();
+
+    /**
+     * Gets the [EMAIL PROTECTED] WebSession}. If create is false and the 
session has not be created
+     * previously, returns null.
+     * 
+     * @param create
+     *            true to force the creation of the session
+     * @return the session (or null if create is false the session has not 
been previously created)
+     */
+    WebSession getSession(boolean create);
+
+    /** Returns the locale of the client as determined from the request 
headers. */
+    Locale getLocale();
+}

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java?view=diff&rev=480168&r1=480167&r2=480168
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
 Tue Nov 28 11:36:06 2006
@@ -20,6 +20,7 @@
 
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.IOException;
 import java.io.OutputStream;
 import java.lang.annotation.Annotation;
 import java.net.MalformedURLException;
@@ -27,6 +28,7 @@
 import java.net.URLClassLoader;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Locale;
 import java.util.UUID;
 
 import javax.servlet.http.HttpServletRequest;
@@ -37,6 +39,7 @@
 import org.apache.tapestry.annotations.Parameter;
 import org.apache.tapestry.ioc.Location;
 import org.apache.tapestry.ioc.ServiceLocator;
+import org.apache.tapestry.ioc.services.ThreadLocale;
 import org.apache.tapestry.ioc.test.IOCTestCase;
 import org.apache.tapestry.model.ComponentModel;
 import org.apache.tapestry.model.MutableComponentModel;
@@ -49,6 +52,7 @@
 import org.apache.tapestry.services.InjectionProvider;
 import org.apache.tapestry.services.MethodSignature;
 import org.apache.tapestry.services.WebRequest;
+import org.apache.tapestry.services.WebRequestHandler;
 import org.apache.tapestry.services.WebResponse;
 import org.apache.tapestry.services.WebSession;
 
@@ -371,5 +375,25 @@
     protected final void train_getContainer(ComponentResources resources, 
Component container)
     {
         expect(resources.getContainer()).andReturn(container).atLeastOnce();
+    }
+
+    protected final WebRequestHandler newWebRequestHandler()
+    {
+        return newMock(WebRequestHandler.class);
+    }
+
+    protected final ThreadLocale newThreadLocale()
+    {
+        return newMock(ThreadLocale.class);
+    }
+
+    protected final void train_service(WebRequestHandler handler, WebRequest 
request, WebResponse response, boolean result) throws IOException
+    {
+        expect(handler.service(request, response)).andReturn(result);
+    }
+
+    protected final void train_getLocale(WebRequest request, Locale locale)
+    {
+        expect(request.getLocale()).andReturn(locale).atLeastOnce();
     }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/conf.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/conf.apt?view=diff&rev=480168&r1=480167&r2=480168
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/conf.apt 
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/conf.apt Tue Nov 
28 11:36:06 2006
@@ -59,4 +59,25 @@
   
   If such a class exists, it is added to the IoC Registry. It is not an error 
for your application to not have a module, though
   any non-trivial application will likely have one.
+  
+* Configuration Symbols
+
+  Tapestry may also be configured via 
{{{../tapestry-ioc/symbols.html}symbols}}.  A certain number of built-in 
services
+  (some of which are not even public) are configured via symbols.  These 
symbols can be overridden
+  by contributing to the tapestry.ioc.ApplicationDefaults service 
configuration, or on the command line
+  by defining JVM System Properties with the -D command line option.
+  
+  [tapestry.file-check-interval]
+    Time (in milliseconds) between file system checks. During a file system 
check, only a single thread is active (all others
+    are blocked) and any files loaded are checked for changes (this is part of 
{{{reload.html}automatic component reloading}}).
+
+    The default is 1000 (one second),  and is usually overridden with a higher 
value in production (say, between one and five minutes).
+
+  [tapestry.supported-locales]
+    A comma-separated list of supported locales.  Incoming requests as 
"narrowed" to one of these locales, based on closest match.
+    If no match can be found, the first locale in the list is treated as the 
default.
+    
+    The default is (currently) "en". 
+    
+
   

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/reload.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/reload.apt?view=diff&rev=480168&r1=480167&r2=480168
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/reload.apt 
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/reload.apt Tue 
Nov 28 11:36:06 2006
@@ -12,9 +12,6 @@
   In Tapestry 5, <page and component> classes will automatically reload when 
changed.  Likewise, changes to
   component templates  and other related resources will also be picked up 
immediately.
   
-  <Note: eventually, there will be some configuration to control how often 
changes are checked for. Currently it is forced
-  to operate on virtually every request, which is fine for development but not 
appropriate for production.>
-  
 * Template Reloading
 
   When a template changes, all page instances (as well as the hiearchy of 
components below them) are discarded and
@@ -26,7 +23,7 @@
 * Class Reloading
 
   On a change to <any> class inside a controlled package (or any sub-package 
of a controlled package), Tapestry will
-  discard all page instances and the class loader.
+  discard all page instances, and discard the class loader.
   
   {{{persist.html}Persistent data}} on the pages will usually not be affected 
(as it is stored separately, in the session).
   This allows you to make fairly significant changes to a component class even 
while the application continues to run.

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LocalizationFilterTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LocalizationFilterTest.java?view=auto&rev=480168
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LocalizationFilterTest.java
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LocalizationFilterTest.java
 Tue Nov 28 11:36:06 2006
@@ -0,0 +1,123 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.internal.services;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import org.apache.tapestry.ioc.services.ThreadLocale;
+import org.apache.tapestry.services.WebRequest;
+import org.apache.tapestry.services.WebRequestFilter;
+import org.apache.tapestry.services.WebRequestHandler;
+import org.apache.tapestry.services.WebResponse;
+import org.apache.tapestry.test.TapestryTestCase;
+import org.testng.annotations.Test;
+
+public class LocalizationFilterTest extends TapestryTestCase
+{
+    @Test
+    public void locale_split()
+    {
+        assertEquals(LocalizationFilter.stripTerm("foo_bar_Baz"), "foo_bar");
+        assertEquals(LocalizationFilter.stripTerm("foo_bar"), "foo");
+        assertEquals(LocalizationFilter.stripTerm("foo"), "");
+    }
+
+    @Test
+    public void to_locale_is_cached()
+    {
+        LocalizationFilter filter = new LocalizationFilter(null, "en");
+
+        Locale l1 = filter.toLocale("en");
+
+        assertEquals(l1.toString(), "en");
+
+        checkLocale(l1, "en", "", "");
+
+        assertSame(filter.toLocale("en"), l1);
+    }
+
+    private void checkLocale(Locale l, String expectedLanguage, String 
expectedCountry,
+            String expectedVariant)
+    {
+        assertEquals(l.getLanguage(), expectedLanguage);
+        assertEquals(l.getCountry(), expectedCountry);
+        assertEquals(l.getVariant(), expectedVariant);
+    }
+
+    @Test
+    public void to_locale()
+    {
+        LocalizationFilter filter = new LocalizationFilter(null, "en");
+
+        checkLocale(filter.toLocale("en"), "en", "", "");
+        checkLocale(filter.toLocale("klingon_Gach"), "klingon", "GACH", "");
+        checkLocale(filter.toLocale("klingon_Gach_snuff"), "klingon", "GACH", 
"snuff");
+    }
+
+    @Test
+    public void known_locale() throws IOException
+    {
+        ThreadLocale threadLocale = newThreadLocale();
+        WebRequestHandler handler = newWebRequestHandler();
+        WebRequest request = newWebRequest();
+        WebResponse response = newWebResponse();
+
+        train_getLocale(request, Locale.CANADA_FRENCH);
+
+        // We don't actually verify that setLocale() occurs before service(),
+        // but sometimes you just have to trust that the code executes in the
+        // order its written.
+
+        threadLocale.setLocale(Locale.FRENCH);
+
+        train_service(handler, request, response, true);
+
+        replay();
+
+        WebRequestFilter filter = new LocalizationFilter(threadLocale, 
"en,fr");
+
+        assertTrue(filter.service(request, response, handler));
+
+        verify();
+    }
+
+    @Test
+    public void unknown_locale_uses_default_locale() throws IOException
+    {
+        ThreadLocale threadLocale = newThreadLocale();
+        WebRequestHandler handler = newWebRequestHandler();
+        WebRequest request = newWebRequest();
+        WebResponse response = newWebResponse();
+
+        train_getLocale(request, Locale.JAPANESE);
+
+        // This time, no real match, so the default (the first locale in the 
list)
+        // will be used.
+
+        threadLocale.setLocale(Locale.ENGLISH);
+
+        train_service(handler, request, response, false);
+
+        replay();
+
+        WebRequestFilter filter = new LocalizationFilter(threadLocale, 
"en,fr");
+
+        assertFalse(filter.service(request, response, handler));
+
+        verify();
+    }
+
+}


Reply via email to