You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@wookie.apache.org by sc...@apache.org on 2011/11/01 22:39:20 UTC
svn commit: r1196296 -
/incubator/wookie/trunk/src/org/apache/wookie/server/LocalizedResourceFilter.java
Author: scottbw
Date: Tue Nov 1 21:39:20 2011
New Revision: 1196296
URL: http://svn.apache.org/viewvc?rev=1196296&view=rev
Log:
Refactored the LocalizedResourceFilter to only store metadata (widget URI, preferred locale, default locale) in session attributes and not the instance id_key.
Modified:
incubator/wookie/trunk/src/org/apache/wookie/server/LocalizedResourceFilter.java
Modified: incubator/wookie/trunk/src/org/apache/wookie/server/LocalizedResourceFilter.java
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/server/LocalizedResourceFilter.java?rev=1196296&r1=1196295&r2=1196296&view=diff
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/server/LocalizedResourceFilter.java (original)
+++ incubator/wookie/trunk/src/org/apache/wookie/server/LocalizedResourceFilter.java Tue Nov 1 21:39:20 2011
@@ -29,6 +29,7 @@ import javax.servlet.http.HttpServletReq
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.configuration.Configuration;
+import org.apache.wookie.beans.IWidget;
import org.apache.wookie.beans.IWidgetInstance;
import org.apache.wookie.beans.util.IPersistenceManager;
import org.apache.wookie.beans.util.PersistenceManagerFactory;
@@ -38,156 +39,255 @@ import org.apache.wookie.w3c.util.Widget
import com.ibm.icu.util.ULocale;
/**
- * A Filter for implementing rules for folder-based localization. Redirects requests
- * for widget resources to resources in appropriate locale folders.
+ * A Filter for implementing rules for folder-based localization. Redirects
+ * requests for widget resources to resources in appropriate locale folders.
*
- * Note that this relies on servlet session management, which relies on cookies being
- * enabled in the browser.
+ * Note that this relies on servlet session management, which relies on cookies
+ * being enabled in the browser.
*
- * This filter runs for a lot of what are otherwise completely static resources, so its a real
- * drag on server performance
+ * This filter runs for a lot of what are otherwise completely static resources,
+ * so its a real drag on server performance
*/
public class LocalizedResourceFilter implements Filter {
- private FilterConfig filterConfig = null;
+ private FilterConfig filterConfig = null;
- public void destroy() {
- }
+ public void destroy() {
+ }
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException {
+ public void doFilter(ServletRequest request, ServletResponse response,
+ FilterChain chain) throws IOException, ServletException {
- // If I have an instance key in the query, set it in the session
- // This will only happen if the resource is the Start File for the Widget
- String idkey = ((HttpServletRequest)request).getParameter("idkey");
- // We use the "localized" querystring parameter to indicate a resource
- // has already been processed by this algorithm once, to prevent hunting and
- // infinite recursion
- String localized = ((HttpServletRequest)request).getParameter("localized");
- if (idkey!=null) filterConfig.getServletContext().setAttribute("id_key", idkey);
- // Skip if already localized
- if (localized == null){
- // Find the instance key in the current session
- String key = (String)filterConfig.getServletContext().getAttribute("id_key");
- if (key != null){
- IPersistenceManager persistenceManager = PersistenceManagerFactory.getPersistenceManager();
- IWidgetInstance instance = persistenceManager.findWidgetInstanceByIdKey(key);
- if (instance != null){
- // Only if we have a valid instance and a resource which has no localization
- // parameter do we start the locale algorithm
-
- // Get the original request URL
- String uri = ((HttpServletRequest)request).getRequestURL().toString();
- URL url = new URL(uri);
- String path = url.getPath();
-
- // Process the resource with the localization algorithm
- String localizedPath = getLocalizedResource(path, instance);
-
- // Redirect to localized resource URL only if different from the original resource URL
- if (!path.equals(localizedPath)){
- uri = uri.replace(path, localizedPath);
- if (uri.contains("?")){
- uri += "&localized=1";
- } else {
- uri += "?localized=1";
- }
- URL newUrl = new URL(uri);
- ((HttpServletResponse)response).sendRedirect(newUrl.toString());
- return;
- }
- }
- }
- }
- chain.doFilter(request, response);
- }
-
- public void init(FilterConfig filterConfig) throws ServletException {
- this.filterConfig = filterConfig;
- }
-
- /**
- * Process a resource path in the context of a widget instance, identify
- * the path for any resource which matches the path in a locale folder
- * which matches the locale preference for the widget instance.
- *
- * If no locale preference is set for the instance, the default server locale
- * is used.
- *
- * If no localized path can be determined, the method returns the original path supplied.
- *
- * @param originalPath
- * @param instance
- * @return the localized path for the resource; if none is found, the original path is returned
- */
- private String getLocalizedResource(String originalPath, IWidgetInstance instance){
- // Remove the context URI from the path, or this will mess up
- // the algorithm for locating the file using its real path
- String context = filterConfig.getServletContext().getContextPath();
- String basePath = originalPath.substring(originalPath.indexOf(context)+context.length());
-
- // Strip out the widget base path to obtain just the resource itself
- String widgetPath = getWidgetInstanceBasePath(instance);
- int start = originalPath.indexOf(widgetPath)+widgetPath.length();
-
- String resource;
- try {
- resource = originalPath.substring(start);
- } catch (Exception e) {
- return originalPath;
- }
-
- // If the resource already contains a locale, remove it for the purposes of searching
- // This is because local links witin widgets can target localized files - e.g.
- // In the example widget below, there will be a link from locales/es/index.html to "locales/es/images/test.png"
- // but we need to consider this as a request for /images/test.png
- //
- // index.html
- // /images/test.png
- // /locales/es/index.html
- //
- if (resource.startsWith("locales/")){
- String[] parts = resource.split("/");
- String prefix = "/"+parts[0]+"/"+parts[1]+"/";
- String nonLocalResource = resource.substring(resource.indexOf(prefix)+prefix.length());
- basePath = basePath.replace(resource, nonLocalResource);
- resource = nonLocalResource;
- }
-
- // For each locale in the list see if a matching localized resource exists.
- // If it does, return it and terminate this algorithm
- List<ULocale> locales = LocalizationUtils.getProcessedLocaleList(new String[]{instance.getLang()});
- for (ULocale locale:locales){
- String path = basePath.replace(resource, "locales/"+locale.toLanguageTag().toLowerCase()+"/"+resource);
- String filePath = filterConfig.getServletContext().getRealPath(path);
- if (new File(filePath).exists()) return context+path;
- }
-
- // As the next resort, we'll try defautLocale
- if (instance.getWidget().getDefaultLocale() != null){
- String path = basePath.replace(resource, "locales/"+instance.getWidget().getDefaultLocale().toLowerCase()+"/"+resource);
- String filePath = filterConfig.getServletContext().getRealPath(path);
- if (new File(filePath).exists()) return context+path;
+ // We use the "localized" querystring parameter to indicate a resource
+ // has already been processed by this algorithm once, to prevent hunting and
+ // infinite recursion
+ String localized = ((HttpServletRequest) request).getParameter("localized");
+
+ //
+ // Skip if already localized
+ //
+ if (localized == null) {
+
+ //
+ // Get the Widget this resource request is related to
+ //
+ IWidget widget = getWidgetFromRequest(request);
+
+ //
+ // Only if we have a valid instance and a resource which has no
+ // localization parameter do we start the locale algorithm
+ //
+ if (widget != null) {
+
+ //
+ // Get the original request URL
+ //
+ String uri = ((HttpServletRequest) request).getRequestURL().toString();
+ URL url = new URL(uri);
+ String path = url.getPath();
+
+ //
+ // Process the resource with the localization algorithm
+ //
+ String localizedPath = getLocalizedResource(path);
+
+ //
+ // Redirect to localized resource URL only if different from the
+ // original resource URL
+ //
+ if (!path.equals(localizedPath)) {
+ uri = uri.replace(path, localizedPath);
+ if (uri.contains("?")) {
+ uri += "&localized=1";
+ } else {
+ uri += "?localized=1";
+ }
+ URL newUrl = new URL(uri);
+ ((HttpServletResponse) response).sendRedirect(newUrl.toString());
+ return;
}
+ }
+ }
+ chain.doFilter(request, response);
+ }
+
+ public void init(FilterConfig filterConfig) throws ServletException {
+ this.filterConfig = filterConfig;
+ }
+
+ /**
+ * Process a resource path in the context of a widget instance, identify the
+ * path for any resource which matches the path in a locale folder which
+ * matches the locale preference for the widget instance.
+ *
+ * If no locale preference is set for the instance, the default server locale
+ * is used.
+ *
+ * If no localized path can be determined, the method returns the original
+ * path supplied.
+ *
+ * @param originalPath
+ * @param instance
+ * @return the localized path for the resource; if none is found, the original
+ * path is returned
+ */
+ private String getLocalizedResource(String originalPath) {
- // All attempts to locate a localized copy have failed, so we must try to find a non-localized version instead
- if (new File(filterConfig.getServletContext().getRealPath(basePath)).exists()) return context+basePath;
-
- // No localized or even non-localized file exists, so just return the original. This situation shouldn't arise except
- // where, e.g., the original request was for a non-existing resource
- return originalPath;
- }
-
- /**
- * Return the base path for a widget instance
- * @param instance
- * @return
- */
- private String getWidgetInstanceBasePath(IWidgetInstance instance){
- String guid = instance.getWidget().getGuid();
- Configuration config = (Configuration) filterConfig.getServletContext().getAttribute("properties");
- final String localWidgetFolderPath = filterConfig.getServletContext().getContextPath()+config.getString("widget.widgetfolder");
- return WidgetPackageUtils.getURLForWidget(localWidgetFolderPath, guid, "");
- }
+ //
+ // Remove the context URI from the path, or this will mess up
+ // the algorithm for locating the file using its real path
+ //
+ String context = filterConfig.getServletContext().getContextPath();
+ String basePath = originalPath.substring(originalPath.indexOf(context)
+ + context.length());
+
+ //
+ // Strip out the widget base path to obtain just the resource itself
+ //
+ String widgetPath = getWidgetBasePath();
+ int start = originalPath.indexOf(widgetPath) + widgetPath.length();
+ String resource;
+ try {
+ resource = originalPath.substring(start);
+ } catch (Exception e) {
+ return originalPath;
+ }
+
+ //
+ // If the resource already contains a locale, remove it for the purposes of
+ // searching
+ // This is because local links within widgets can target localized files -
+ // e.g.
+ // In the example widget below, there will be a link from
+ // locales/es/index.html to "locales/es/images/test.png"
+ // but we need to consider this as a request for /images/test.png
+ //
+ // index.html
+ // /images/test.png
+ // /locales/es/index.html
+ //
+ if (resource.startsWith("locales/")) {
+ String[] parts = resource.split("/");
+ String prefix = "/" + parts[0] + "/" + parts[1] + "/";
+ String nonLocalResource = resource.substring(resource.indexOf(prefix)
+ + prefix.length());
+ basePath = basePath.replace(resource, nonLocalResource);
+ resource = nonLocalResource;
+ }
+
+ //
+ // For each locale in the list see if a matching localized resource exists.
+ // If it does, return it and terminate this algorithm
+ //
+ List<ULocale> locales = LocalizationUtils.getProcessedLocaleList(new String[] { getPreferredLocale() });
+ for (ULocale locale : locales) {
+ String path = basePath.replace(resource, "locales/" + locale.toLanguageTag().toLowerCase() + "/" + resource);
+ String filePath = filterConfig.getServletContext().getRealPath(path);
+ if (new File(filePath).exists())
+ return context + path;
+ }
+
+ //
+ // As the next resort, we'll try defautLocale
+ //
+ String defaultLocale = getWidgetDefaultLocale();
+ if (defaultLocale != null) {
+ String path = basePath.replace(resource, "locales/" + defaultLocale.toLowerCase() + "/" + resource);
+ String filePath = filterConfig.getServletContext().getRealPath(path);
+ if (new File(filePath).exists())
+ return context + path;
+ }
+
+ //
+ // All attempts to locate a localized copy have failed, so we must try to
+ // find a non-localized version instead
+ //
+ if (new File(filterConfig.getServletContext().getRealPath(basePath)).exists())
+ return context + basePath;
+
+ //
+ // No localized or even non-localized file exists, so just return the
+ // original. This situation shouldn't arise except
+ // where, e.g., the original request was for a non-existing resource
+ //
+ return originalPath;
+ }
+
+ /**
+ * Return the base path for a widget instance
+ *
+ * @param instance
+ * @return
+ */
+ private String getWidgetBasePath() {
+ Configuration config = (Configuration) filterConfig.getServletContext().getAttribute("properties");
+ final String localWidgetFolderPath = filterConfig.getServletContext().getContextPath() + config.getString("widget.widgetfolder");
+ return WidgetPackageUtils.getURLForWidget(localWidgetFolderPath, getWidgetGuid(), "");
+ }
+
+ /**
+ * Inspect the request path and identify the widget based on the path
+ * components
+ *
+ * @param request
+ * @return
+ */
+ private IWidget getWidgetFromRequest(ServletRequest request) {
+ //
+ // If I have an instance key in the query, use it to look up the widget
+ // it belongs to, and put the widget URI and localization preferences into the session
+ //
+ // This will only happen if the resource is the Start File for the Widget
+ //
+ String idkey = ((HttpServletRequest) request).getParameter("idkey");
+ if (idkey != null){
+ IPersistenceManager persistenceManager = PersistenceManagerFactory.getPersistenceManager();
+ IWidgetInstance instance = persistenceManager.findWidgetInstanceByIdKey(idkey);
+ if (instance != null) {
+ filterConfig.getServletContext().setAttribute("widget-id", instance.getWidget().getGuid());
+ filterConfig.getServletContext().setAttribute("widget-instance-locale", instance.getLang());
+ filterConfig.getServletContext().setAttribute("widget-default-locale", instance.getWidget().getDefaultLocale());
+ return instance.getWidget();
+ }
+ }
+
+ //
+ // Get the widget id from the session, and if its not null, obtain the widget it relates to
+ //
+ String guid = (String) filterConfig.getServletContext().getAttribute("widget-id");
+ if (guid != null) {
+ IPersistenceManager persistenceManager = PersistenceManagerFactory.getPersistenceManager();
+ return persistenceManager.findWidgetByGuid(guid);
+ }
+
+ //
+ // No widget found
+ //
+ return null;
+ }
+
+ /**
+ * Get the GUID of the widget that the resource in the current context belongs to
+ * @return
+ */
+ private String getWidgetGuid(){
+ return (String) filterConfig.getServletContext().getAttribute("widget-id");
+ }
+
+ /**
+ * Get the preferred locale of the widget instances that the resource in the current context belongs to
+ * @return
+ */
+ private String getPreferredLocale(){
+ return (String) filterConfig.getServletContext().getAttribute("widget-instance-locale");
+ }
+
+ /**
+ * Get the defaultLocale attribute for the widget that the resource in the current context belongs to
+ * @return
+ */
+ private String getWidgetDefaultLocale(){
+ return (String) filterConfig.getServletContext().getAttribute("widget-default-locale");
+ }
}