myfaces-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ima...@apache.org
Subject svn commit: r380195 - in /myfaces/commons/trunk/src/main/java/org/apache/myfaces/renderkit/html/util: AddResource.java AddResourceFactory.java DefaultAddResource.java
Date Thu, 23 Feb 2006 18:44:21 GMT
Author: imario
Date: Thu Feb 23 10:44:17 2006
New Revision: 380195

URL: http://svn.apache.org/viewcvs?rev=380195&view=rev
Log:
TOMAHAWK-108: made AddResource request scope so it is
request safe now

Modified:
    myfaces/commons/trunk/src/main/java/org/apache/myfaces/renderkit/html/util/AddResource.java
    myfaces/commons/trunk/src/main/java/org/apache/myfaces/renderkit/html/util/AddResourceFactory.java
    myfaces/commons/trunk/src/main/java/org/apache/myfaces/renderkit/html/util/DefaultAddResource.java

Modified: myfaces/commons/trunk/src/main/java/org/apache/myfaces/renderkit/html/util/AddResource.java
URL: http://svn.apache.org/viewcvs/myfaces/commons/trunk/src/main/java/org/apache/myfaces/renderkit/html/util/AddResource.java?rev=380195&r1=380194&r2=380195&view=diff
==============================================================================
--- myfaces/commons/trunk/src/main/java/org/apache/myfaces/renderkit/html/util/AddResource.java
(original)
+++ myfaces/commons/trunk/src/main/java/org/apache/myfaces/renderkit/html/util/AddResource.java
Thu Feb 23 10:44:17 2006
@@ -40,6 +40,11 @@
 
     // Methods to add resources
 
+	/**
+	 * set the context path of the web-app
+	 */
+	public void setContextPath(String contextPath);
+	
     /**
      * Insert a [script src="url"] entry at the current location in the response.
      * The resource is expected to be in the classpath, at the same location as the
@@ -214,9 +219,6 @@
     public void serveResource(ServletContext context, HttpServletRequest request,
             HttpServletResponse response) throws IOException;
 
-
-    public boolean hasHeaderBeginInfos(HttpServletRequest request);
-
     /**
      * Parses the response to mark the positions where code will be inserted
      */
@@ -245,4 +247,8 @@
     public void writeResponse(HttpServletRequest request,
             HttpServletResponse response) throws IOException;
 
+    /**
+     * check there is something to write to the header
+     */
+	public boolean hasHeaderBeginInfos();
 }

Modified: myfaces/commons/trunk/src/main/java/org/apache/myfaces/renderkit/html/util/AddResourceFactory.java
URL: http://svn.apache.org/viewcvs/myfaces/commons/trunk/src/main/java/org/apache/myfaces/renderkit/html/util/AddResourceFactory.java?rev=380195&r1=380194&r2=380195&view=diff
==============================================================================
--- myfaces/commons/trunk/src/main/java/org/apache/myfaces/renderkit/html/util/AddResourceFactory.java
(original)
+++ myfaces/commons/trunk/src/main/java/org/apache/myfaces/renderkit/html/util/AddResourceFactory.java
Thu Feb 23 10:44:17 2006
@@ -16,19 +16,19 @@
 
 package org.apache.myfaces.renderkit.html.util;
 
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import javax.faces.context.FacesContext;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.myfaces.config.MyfacesConfig;
 import org.apache.myfaces.util.ClassUtils;
 
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.faces.context.FacesContext;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.util.HashMap;
-import java.util.Map;
-
 /**
  * This class provides the ability to instantiate AddResource objects.
  * By default, this class will instantiate instances of
@@ -47,126 +47,204 @@
  */
 public class AddResourceFactory
 {
-
+	private final static String CACHE_MAP_KEY = "org.apache.myfaces.AddResourceFactory.CACHE_MAP_KEY";

+	
     protected static final Log log = LogFactory.getLog(AddResourceFactory.class);
 
-    /**
-     * Map of AddResource instances keyed by context path. This map will have
-     * more than one entry only if the myfaces library is in the "shared"
-     * classpath of a container where more than one webapp can see it
-     * simultaneously.
-     */
-    private static final Map _addResourceMap = new HashMap();
-
+    public static class RequestMapWrapper implements Map
+    {
+    	private final HttpServletRequest request;
+    	
+    	public RequestMapWrapper(final HttpServletRequest request)
+    	{
+    		this.request = request;    		
+    	}
+    	
+		public int size()
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public boolean isEmpty()
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public boolean containsKey(Object key)
+		{
+			if (key == null)
+			{
+				throw new UnsupportedOperationException("'null' key not supported");
+			}
+			return request.getAttribute(key.toString()) != null;
+		}
+
+		public boolean containsValue(Object value)
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public Object get(Object key)
+		{
+			if (key == null)
+			{
+				throw new UnsupportedOperationException("'null' key not supported");
+			}
+			return request.getAttribute(key.toString());
+		}
+
+		public Object put(Object key, Object value)
+		{
+			if (key == null)
+			{
+				throw new UnsupportedOperationException("'null' key not supported");
+			}
+			
+			Object old = request.getAttribute(key.toString());
+			request.setAttribute(key.toString(), value);
+			return old;
+		}
+
+		public Object remove(Object key)
+		{
+			if (key == null)
+			{
+				throw new UnsupportedOperationException("'null' key not supported");
+			}
+			
+			Object old = request.getAttribute(key.toString());
+			request.removeAttribute(key.toString());
+			return old;
+		}
+
+		public void putAll(Map arg)
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public void clear()
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public Set keySet()
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public Collection values()
+		{
+			throw new UnsupportedOperationException();
+		}
+
+		public Set entrySet()
+		{
+			throw new UnsupportedOperationException();
+		}
+    	
+    }
     /**
      * Internal factory method.
      * <p>
      * Return an instance of AddResource keyed by context path, or create one
-     * if no such instance already exists. Note that the same AddResource object
-     * is shared among all threads servicing the same webapp, so all methods
-     * on this class are required to be threadsafe.
+     * if no such instance already exists. The instance will be cached using the
+     * given Map, most likely this will the the request map of your servlet request.
+     * Therefore every request uses its own AddResource instance. 
+     * </p>
      * <p>
      * Note that this method is package-scope for the purposes of unit-testing only.
      * This method should be treated as private by non-test code.
+     * </p>
+     * 
+     * @param cacheMap the map used for caching of the instance. if null, a new instance
will be created all the time (for tests)
+     * @param contextPath context path of your web-app
+     * @param addResourceClassName class name of a class implementing the @link AddResource
interface
      */
-    static AddResource getInstance(String contextPath, String addResourceClassName)
+    static AddResource getInstance(Map cacheMap, String contextPath, String addResourceClassName)
     {
-        // Yes, this method does use a variant of the "double locking" idiom
-        // which is well documented to be invalid for general use. However
-        // it is believed safe for use here because AddResource objects in
-        // _addResourceMap are never removed or replaced.
-        AddResource instance = (AddResource) _addResourceMap.get(contextPath);
+        AddResource instance = null;
+        
+        if (cacheMap != null)
+        {
+        	instance = (AddResource) cacheMap.get(CACHE_MAP_KEY);
+        }
+        
         if (instance == null)
         {
-            synchronized (_addResourceMap)
-            {
-                instance = (AddResource) _addResourceMap.get(contextPath);
-                if (instance == null)
-                {
-                	if (addResourceClassName == null)
-                	{
-                		// For efficiency don't use reflection unless it is necessary
-                        instance = new DefaultAddResource(contextPath);                	

-                	}
-                	else
-                	{
-                		try
-                		{
-                			Class addResourceClass = ClassUtils.classForName(addResourceClassName);
-                			
-                			if (AddResource.class.isAssignableFrom(addResourceClass)) 
-                			{
-                				// Look for an appropriate constructor
-                				Constructor[] constructors = addResourceClass.getDeclaredConstructors();
-                				
-                				for (int i = 0; i < constructors.length; i++)
-                				{
-                					Class[] parameters = constructors[i].getParameterTypes();
-
-                					if (parameters.length == 1 && String.class.isAssignableFrom(parameters[i]))

-                					{
-                						instance = (AddResource) constructors[i].newInstance(new String[] {contextPath});
-                						log.info("Found AddResource class '" + addResourceClass.getName() +
"'");
-                						break;
-                					}
-                				}
-                				
-                				if (instance == null)
-                				{
-                        			log.error("Invalid AddResource class (" + addResourceClass.getName()

-                    					+ "). Must include single argument (context path) constructor.");
               					
-                				}
-                			}
-                			else
-                			{
-                    			log.error("Invalid AddResource class (" + addResourceClass.getName()

-                    					+ "). Must implement the AddResource interface.");
-                			}
-                		}
-                		catch (ClassNotFoundException e)
-                		{
-                			log.error("AddResource class not found. Using default class instead",
e);
-                		} 
-                		catch (IllegalArgumentException e) {
-                			// This should not happen as the constructor has been checked
-                			log.error(e);
-						} 
-                		catch (InstantiationException e) {
-                			log.error("Invalid AddResource class. Must be non-abstract", e);
-						} 
-                		catch (IllegalAccessException e) {
-                			log.error("Could not access AddResource class", e);
-						} 
-                		catch (InvocationTargetException e) {
-                			log.error(e);
-						}
-						finally
-						{
-							// Ensure there is always an AddResource object available
-							if (instance == null)
-							{
-								instance = new DefaultAddResource(contextPath);                			              
 				
-							}
-						}
-                	}
-                    _addResourceMap.put(contextPath, instance);
-                }
-            }
+        	if (addResourceClassName == null)
+        	{
+        		// For efficiency don't use reflection unless it is necessary
+                instance = new DefaultAddResource();                		
+				instance.setContextPath(contextPath);
+        	}
+        	else
+        	{
+        		try
+        		{
+        			Class addResourceClass = ClassUtils.classForName(addResourceClassName);
+        			
+        			if (AddResource.class.isAssignableFrom(addResourceClass)) 
+        			{
+        				AddResource tmpInstance = (AddResource) addResourceClass.newInstance();
+        				tmpInstance.setContextPath(contextPath);
+
+        				// only use a fully initialized instance
+        				instance = tmpInstance;
+        			}
+        			else
+        			{
+            			log.error("Invalid AddResource class (" + addResourceClass.getName() 
+            					+ "). Must implement the AddResource interface.");
+        			}
+        		}
+        		catch (ClassNotFoundException e)
+        		{
+        			log.error("AddResource class not found. Using default class instead", e);
+        		} 
+        		catch (IllegalArgumentException e) {
+        			// This should not happen as the constructor has been checked
+        			log.error(e);
+				} 
+        		catch (InstantiationException e) {
+        			log.error("Invalid AddResource class. Must be non-abstract", e);
+				} 
+        		catch (IllegalAccessException e) {
+        			log.error("Could not access AddResource class", e);
+				} 
+				finally
+				{
+					// Ensure there is always an AddResource object available
+					if (instance == null)
+					{
+						instance = new DefaultAddResource();
+						instance.setContextPath(contextPath);
+					}
+				}
+        	}
+        	
+        	if (cacheMap != null)
+        	{
+        		cacheMap.put(CACHE_MAP_KEY, instance);
+        	}
         }
+        
         return instance;
     }
 
     public static AddResource getInstance(FacesContext context)
     {
-        return getInstance(context.getExternalContext().getRequestContextPath(),
+        return getInstance(
+        		context.getExternalContext().getRequestMap(),
+        		context.getExternalContext().getRequestContextPath(),
                            MyfacesConfig.getCurrentInstance(context.getExternalContext()).getAddResourceClass());
     }
 
     public static AddResource getInstance(HttpServletRequest request)
     {
         ServletContext servletContext = ((HttpServletRequest)request).getSession().getServletContext();
-        return getInstance(request.getContextPath(),
-                           MyfacesConfig.getAddResourceClassFromServletContext(servletContext));
+        return getInstance(
+        		new RequestMapWrapper(request),
+        		request.getContextPath(),
+        		MyfacesConfig.getAddResourceClassFromServletContext(servletContext));
     }
-
 }

Modified: myfaces/commons/trunk/src/main/java/org/apache/myfaces/renderkit/html/util/DefaultAddResource.java
URL: http://svn.apache.org/viewcvs/myfaces/commons/trunk/src/main/java/org/apache/myfaces/renderkit/html/util/DefaultAddResource.java?rev=380195&r1=380194&r2=380195&view=diff
==============================================================================
--- myfaces/commons/trunk/src/main/java/org/apache/myfaces/renderkit/html/util/DefaultAddResource.java
(original)
+++ myfaces/commons/trunk/src/main/java/org/apache/myfaces/renderkit/html/util/DefaultAddResource.java
Thu Feb 23 10:44:17 2006
@@ -81,21 +81,14 @@
 
     private static final String RESOURCE_VIRTUAL_PATH = "/faces/myFacesExtensionResource";
 
-    private static final String HEADER_BEGIN_INFO_REQUEST_ATTRIBUTE_NAME = AddResource.class
-            .getName()
-            + ".HEADER_BEGIN_INFO";
-
-    private static final String BODY_END_INFO_REQUEST_ATTRIBUTE_NAME = AddResource.class.getName()
-            + ".BODY_END_INFO";
-
-    private static final String BODY_ONLOAD_INFO_REQUEST_ATTRIBUTE_NAME = AddResource.class
-            .getName()
-            + ".BODY_ONLOAD_INFO";
-
     private static final String RESOURCES_CACHE_KEY = AddResource.class.getName() + ".CACHE_KEY";
 
-    protected final String _contextPath;
+    protected String _contextPath;
 
+    private Set headerBeginInfo;
+    private Set bodyEndInfo;
+    private Set bodyOnloadInfo;
+    
     private StringBuffer originalResponse;
     protected boolean parserCalled = false;
     protected int headerInsertPosition = -1;
@@ -104,9 +97,8 @@
     protected int afterBodyContentInsertPosition = -1;
     protected int beforeBodyEndPosition = -1;
 
-    protected DefaultAddResource(String contextPath)
+    protected DefaultAddResource()
     {
-        _contextPath = contextPath;
     }
 
     // Methods to add resources
@@ -555,71 +547,56 @@
 
     // Positioned stuffs
 
-    protected Set getHeaderBeginInfos(HttpServletRequest request)
+    protected Set getHeaderBeginInfos()
     {
-        Set set = (Set) request.getAttribute(HEADER_BEGIN_INFO_REQUEST_ATTRIBUTE_NAME);
-        if (set == null)
-        {
-            set = new LinkedHashSet();
-            request.setAttribute(HEADER_BEGIN_INFO_REQUEST_ATTRIBUTE_NAME, set);
-        }
-        return set;
+    	if (headerBeginInfo == null)
+    	{
+    		headerBeginInfo = new LinkedHashSet();
+    	}
+        return headerBeginInfo;
     }
 
-    protected Set getBodyEndInfos(HttpServletRequest request)
+    protected Set getBodyEndInfos()
     {
-        Set set = (Set) request.getAttribute(BODY_END_INFO_REQUEST_ATTRIBUTE_NAME);
-        if (set == null)
-        {
-            set = new LinkedHashSet();
-            request.setAttribute(BODY_END_INFO_REQUEST_ATTRIBUTE_NAME, set);
-        }
-        return set;
+    	if (bodyEndInfo == null)
+    	{
+    		bodyEndInfo = new LinkedHashSet();
+    	}
+        return bodyEndInfo;
     }
 
-    protected Set getBodyOnloadInfos(HttpServletRequest request)
+    protected Set getBodyOnloadInfos()
     {
-        Set set = (Set) request.getAttribute(BODY_ONLOAD_INFO_REQUEST_ATTRIBUTE_NAME);
-        if (set == null)
-        {
-            set = new LinkedHashSet();
-            request.setAttribute(BODY_ONLOAD_INFO_REQUEST_ATTRIBUTE_NAME, set);
-        }
-        return set;
+    	if (bodyOnloadInfo == null)
+    	{
+    		bodyOnloadInfo = new LinkedHashSet();
+    	}
+        return bodyOnloadInfo;
     }
 
     private void addPositionedInfo(FacesContext context, ResourcePosition position, PositionedInfo
info)
     {
         if (HEADER_BEGIN.equals(position))
         {
-            //todo: fix this to work in PortletRequest as well
-            HttpServletRequest request = (HttpServletRequest) context.getExternalContext()
-                    .getRequest();
-            Set set = getHeaderBeginInfos(request);
+            Set set = getHeaderBeginInfos();
             set.add(info);
         }
         else if (BODY_END.equals(position))
         {
-            //todo: fix this to work in PortletRequest as well
-            HttpServletRequest request = (HttpServletRequest) context.getExternalContext()
-                    .getRequest();
-            Set set = getBodyEndInfos(request);
+            Set set = getBodyEndInfos();
             set.add(info);
 
         }
         else if (BODY_ONLOAD.equals(position))
         {
-            //todo: fix this to work in PortletRequest as well
-            HttpServletRequest request = (HttpServletRequest) context.getExternalContext()
-                    .getRequest();
-            Set set = getBodyOnloadInfos(request);
+            Set set = getBodyOnloadInfos();
             set.add(info);
         }
     }
 
-    public boolean hasHeaderBeginInfos(HttpServletRequest request)
+    public boolean hasHeaderBeginInfos()
     {
-        return request.getAttribute(HEADER_BEGIN_INFO_REQUEST_ATTRIBUTE_NAME) != null;
+        return headerBeginInfo != null;
     }
 
     /**
@@ -711,7 +688,7 @@
             HtmlBufferResponseWriterWrapper writerWrapper = HtmlBufferResponseWriterWrapper
                     .getInstance(writer);
 
-            for (Iterator i = getBodyEndInfos(request).iterator(); i.hasNext();)
+            for (Iterator i = getBodyEndInfos().iterator(); i.hasNext();)
             {
                 writerWrapper.write("\n");
 
@@ -730,11 +707,11 @@
         if (bodyInsertPosition > 0)
         {
             StringBuffer buf = new StringBuffer();
-            Set bodyInfos = getBodyOnloadInfos(request);
+            Set bodyInfos = getBodyOnloadInfos();
             if (bodyInfos.size() > 0)
             {
                 int i = 0;
-                for (Iterator it = getBodyOnloadInfos(request).iterator(); it.hasNext();)
+                for (Iterator it = getBodyOnloadInfos().iterator(); it.hasNext();)
                 {
                     AttributeInfo positionedInfo = (AttributeInfo) it.next();
                     if (i == 0)
@@ -760,7 +737,7 @@
             if (addHeaderTags)
                 writerWrapper.write("<head>");
 
-            for (Iterator i = getHeaderBeginInfos(request).iterator(); i.hasNext();)
+            for (Iterator i = getHeaderBeginInfos().iterator(); i.hasNext();)
             {
                 writerWrapper.write("\n");
 
@@ -1108,4 +1085,18 @@
             return afterBodyEndPosition;
         }
     }
+
+    /**
+     * the context path for the web-app.<br />
+     * You can set the context path only once, every subsequent set will throw an SecurityException
+     */
+	public void setContextPath(String contextPath)
+	{
+		if (_contextPath != null)
+		{
+			throw new SecurityException("context path already set");
+		}
+		
+        _contextPath = contextPath;
+	}
 }



Mime
View raw message