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();
+ }
+
+}