You are viewing a plain text version of this content. The canonical link for it is here.
Posted to portalapps-dev@portals.apache.org by wo...@apache.org on 2009/10/01 19:56:44 UTC

svn commit: r820733 - in /portals/applications/webcontent/trunk: webcontent-jar/ webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/ webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/ webconte...

Author: woonsan
Date: Thu Oct  1 17:56:43 2009
New Revision: 820733

URL: http://svn.apache.org/viewvc?rev=820733&view=rev
Log:
APA-17: Allowing glob expressions in pass mapping configurations.

Added:
    portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestProxyPathMappings.java   (with props)
    portals/applications/webcontent/trunk/webcontent-jar/src/test/resources/
    portals/applications/webcontent/trunk/webcontent-jar/src/test/resources/log4j.properties   (contents, props changed)
      - copied, changed from r820182, portals/applications/webcontent/trunk/webcontent-jar/src/test/java/log4j.properties
Removed:
    portals/applications/webcontent/trunk/webcontent-jar/src/test/java/log4j.properties
Modified:
    portals/applications/webcontent/trunk/webcontent-jar/pom.xml
    portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapper.java
    portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapperProvider.java
    portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyPathMapperImpl.java
    portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyPathMapperProviderImpl.java
    portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyServlet.java
    portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/PassMappingLinkRewritingParserAaptor.java
    portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java
    portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/SimpleLinkRewritingParserAaptor.java
    portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestReverseProxyLinkRewritingParserAaptor.java
    portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy.properties
    portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/portlet.xml

Modified: portals/applications/webcontent/trunk/webcontent-jar/pom.xml
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/pom.xml?rev=820733&r1=820732&r2=820733&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/pom.xml (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/pom.xml Thu Oct  1 17:56:43 2009
@@ -45,6 +45,7 @@
     <commons-httpclient.version>3.0.1</commons-httpclient.version>
     <commons-beanutils.version>1.8.0</commons-beanutils.version>
     <commons-configuration.version>1.6</commons-configuration.version>
+    <easymock.version>2.5.2</easymock.version>
   </properties>
 
   <!-- Dependencies -->
@@ -197,7 +198,12 @@
         </exclusion>
       </exclusions>
     </dependency>
-
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymock</artifactId>
+      <version>${easymock.version}</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
   <build>
     <plugins>

Modified: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapper.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapper.java?rev=820733&r1=820732&r2=820733&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapper.java (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapper.java Thu Oct  1 17:56:43 2009
@@ -16,27 +16,52 @@
  */
 package org.apache.portals.applications.webcontent.proxy;
 
+
 /**
  * proxy path mapper interface for http reverse proxy service.
  * 
  * @version $Id$
  */
-public interface HttpReverseProxyPathMapper
+public interface HttpReverseProxyPathMapper extends Cloneable
 {
     
     /**
+     * Returns the name
+     * @return
+     */
+    public String getName();
+    
+    /**
+     * Sets the name
+     * @return
+     */
+    public void setName(String name);
+    
+    /**
      * Returns the local base path to be mapped to remote base url.
      * @return
      */
     public String getLocalBasePath();
     
     /**
+     * Sets the local base path to be mapped to remote base url.
+     * @return
+     */
+    public void setLocalBasePath(String localBasePath);
+    
+    /**
      * Returns the remote base url mapped by the local path.
      * @return
      */
     public String getRemoteBaseURL();
     
     /**
+     * Sets the remote base url mapped by the local path.
+     * @return
+     */
+    public void setRemoteBaseURL(String removeBaseURL);
+    
+    /**
      * Generates a remote url mapped by the path.
      * <P>It returns a translated remote URL or null if the translation fails.</P>
      * @param localPath
@@ -52,4 +77,10 @@
      */
     public String getLocalPath(String remoteURL);
     
+    /**
+     * Clone object
+     * @return
+     */
+    public Object clone();
+    
 }
\ No newline at end of file

Modified: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapperProvider.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapperProvider.java?rev=820733&r1=820732&r2=820733&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapperProvider.java (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapperProvider.java Thu Oct  1 17:56:43 2009
@@ -44,16 +44,16 @@
     public HttpReverseProxyPathMapper findMapperByRemoteURL(String remoteURL);
     
     /**
-     * Finds a reverse proxy rewriter controller based on the request
+     * Gets a reverse proxy rewriter controller corresponded to proxy path mapper
      * @return
      */
-    public RewriterController findRewriterController(HttpServletRequest request);
+    public RewriterController getRewriterController(HttpReverseProxyPathMapper proxyPathMapper);
     
     /**
-     * Finds a reverse proxy rewriter rules based on the request
+     * Gets a reverse proxy rewriter rules corresponded to proxy path mapper
      * @return
      */
-    public Ruleset findRewriterRuleset(HttpServletRequest request);
+    public Ruleset getRewriterRuleset(HttpReverseProxyPathMapper proxyPathMapper);
     
     /**
      * Returns unmodifiable proxy path mappers.

Modified: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyPathMapperImpl.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyPathMapperImpl.java?rev=820733&r1=820732&r2=820733&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyPathMapperImpl.java (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyPathMapperImpl.java Thu Oct  1 17:56:43 2009
@@ -26,25 +26,56 @@
  */
 public class DefaultHttpReverseProxyPathMapperImpl implements HttpReverseProxyPathMapper
 {
+    private String name;
     private String localBasePath;
     private String remoteBaseURL;
     
-    public DefaultHttpReverseProxyPathMapperImpl(String localBasePath, String remoteBaseURL)
+    private int hash;
+    
+    public DefaultHttpReverseProxyPathMapperImpl()
     {
+    }
+    
+    public DefaultHttpReverseProxyPathMapperImpl(String name, String localBasePath, String remoteBaseURL)
+    {
+        this.name = name;
         this.localBasePath = localBasePath;
         this.remoteBaseURL = remoteBaseURL;
     }
     
+    public String getName()
+    {
+        return name;
+    }
+    
+    public void setName(String name)
+    {
+        this.name = name;
+        this.hash = 0;
+    }
+    
     public String getLocalBasePath()
     {
         return localBasePath;
     }
-
+    
+    public void setLocalBasePath(String localBasePath)
+    {
+        this.localBasePath = localBasePath;
+        this.hash = 0;
+    }
+    
     public String getRemoteBaseURL()
     {
         return remoteBaseURL;
     }
-
+    
+    public void setRemoteBaseURL(String remoteBaseURL)
+    {
+        this.remoteBaseURL = remoteBaseURL;
+        this.hash = 0;
+    }
+    
     public String getRemoteURL(String localPath)
     {
         if (StringUtils.startsWith(localPath, localBasePath))
@@ -65,4 +96,43 @@
         return null;
     }
     
+    @Override
+    public Object clone()
+    {
+        DefaultHttpReverseProxyPathMapperImpl cloned = new DefaultHttpReverseProxyPathMapperImpl();
+        cloned.name = name;
+        cloned.localBasePath = localBasePath;
+        cloned.remoteBaseURL = remoteBaseURL;
+        return cloned;
+    }
+    
+    @Override
+    public int hashCode()
+    {
+        if (hash == 0)
+        {
+            hash = new StringBuilder(40).append(name).append(':').append(localBasePath).append(':').append(remoteBaseURL).toString().hashCode();
+        }
+        
+        return hash;
+    }
+    
+    @Override
+    public boolean equals(Object o)
+    {
+        if (hash != o.hashCode())
+        {
+            return false;
+        }
+        
+        if (o instanceof HttpReverseProxyPathMapper)
+        {
+            HttpReverseProxyPathMapper mapper = (HttpReverseProxyPathMapper) o;
+            return (StringUtils.equals(name, mapper.getName()) && 
+                            StringUtils.equals(localBasePath, mapper.getLocalBasePath()) &&
+                            StringUtils.equals(remoteBaseURL, mapper.getRemoteBaseURL()));
+        }
+        
+        return false;
+    }
 }

Modified: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyPathMapperProviderImpl.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyPathMapperProviderImpl.java?rev=820733&r1=820732&r2=820733&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyPathMapperProviderImpl.java (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyPathMapperProviderImpl.java Thu Oct  1 17:56:43 2009
@@ -16,17 +16,23 @@
  */
 package org.apache.portals.applications.webcontent.proxy.impl;
 
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import javax.servlet.http.HttpServletRequest;
 
-import org.apache.commons.collections.KeyValue;
 import org.apache.commons.lang.StringUtils;
 import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapper;
 import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapperProvider;
 import org.apache.portals.applications.webcontent.rewriter.RewriterController;
 import org.apache.portals.applications.webcontent.rewriter.rules.Ruleset;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Default <CODE>HttpReverseProxyPathMapperProvider</CODE> implementation
@@ -36,90 +42,285 @@
 public class DefaultHttpReverseProxyPathMapperProviderImpl implements HttpReverseProxyPathMapperProvider
 {
     
+    private static String [] GLOB_EXPR_SEARCHES = { "*", ".", "/", "?", "+" };
+    
+    private static String [] GLOB_EXPR_REPLACES = { "(.+)", "\\.", "\\/", "\\?", "\\+" };
+    
+    private static String [] GROUP_REF_SEARCHES = { "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9" };
+    
+    private static String [] GROUP_REF_REPLACES = { "(.+)", "(.+)", "(.+)", "(.+)", "(.+)", "(.+)", "(.+)", "(.+)", "(.+)" };
+    
+    private static Logger log = LoggerFactory.getLogger(DefaultHttpReverseProxyPathMapperProviderImpl.class);
+    
     /**
      * Proxy path mappers
      */
     private List<HttpReverseProxyPathMapper> proxyPathMappers;
     
     /**
+     * Proxy path Glob mappers
+     */
+    private List<HttpReverseProxyPathMapper> proxyPathGlobMappers;
+    
+    /**
      * rewriter controller mappers
      */
-    private List<KeyValue> rewriterControllerPairs;
+    private Map<HttpReverseProxyPathMapper, RewriterController> rewriterControllerMap;
     
     /**
      * rewriter rulesets
      */
-    private List<KeyValue> rewriterRulesetPairs;
+    private Map<HttpReverseProxyPathMapper, Ruleset> rewriterRulesetMap;
+    
+    private Map<HttpReverseProxyPathMapper, Pattern> localBasePathGlobPatternMap;
+    
+    private Map<HttpReverseProxyPathMapper, Pattern> remoteBaseURLGlobPatternMap;
     
     public DefaultHttpReverseProxyPathMapperProviderImpl(List<HttpReverseProxyPathMapper> proxyPathMappers, 
-                                                         List<KeyValue> rewriterControllerPairs,
-                                                         List<KeyValue> rewriterRulesetPairs)
+                                                         Map<HttpReverseProxyPathMapper, RewriterController> rewriterControllerMap,
+                                                         Map<HttpReverseProxyPathMapper, Ruleset> rewriterRulesetMap)
     {
-        this.proxyPathMappers = proxyPathMappers;
-        this.rewriterControllerPairs = rewriterControllerPairs;
-        this.rewriterRulesetPairs = rewriterRulesetPairs;
+        this.rewriterControllerMap = rewriterControllerMap;
+        this.rewriterRulesetMap = rewriterRulesetMap;
+        
+        this.proxyPathMappers = Collections.synchronizedList(new ArrayList<HttpReverseProxyPathMapper>());
+        this.proxyPathGlobMappers = new ArrayList<HttpReverseProxyPathMapper>();
+        
+        for (HttpReverseProxyPathMapper proxyPathMapper : proxyPathMappers)
+        {
+            if (!StringUtils.contains(proxyPathMapper.getLocalBasePath(), '*'))
+            {
+                this.proxyPathMappers.add(proxyPathMapper);
+            }
+            else
+            {
+                this.proxyPathGlobMappers.add(proxyPathMapper);
+            }
+        }
+        
+        this.localBasePathGlobPatternMap = Collections.synchronizedMap(new HashMap<HttpReverseProxyPathMapper, Pattern>());
+        this.remoteBaseURLGlobPatternMap = Collections.synchronizedMap(new HashMap<HttpReverseProxyPathMapper, Pattern>());
     }
     
     public HttpReverseProxyPathMapper findMapper(HttpServletRequest request)
     {
+        HttpReverseProxyPathMapper mapper = null;
         String pathInfo = request.getPathInfo();
         
-        for (HttpReverseProxyPathMapper proxyPathMapper : proxyPathMappers)
+        int mapperCount = proxyPathMappers.size();
+        
+        for (int i = 0; i < mapperCount; i++)
         {
+            HttpReverseProxyPathMapper proxyPathMapper = proxyPathMappers.get(i);
+            
             if (StringUtils.startsWith(pathInfo, proxyPathMapper.getLocalBasePath()))
             {
                 return proxyPathMapper;
             }
         }
         
-        return null;
-    }
-    
-    public HttpReverseProxyPathMapper findMapperByRemoteURL(String remoteURL)
-    {
-        if (remoteURL != null)
+        if (!proxyPathGlobMappers.isEmpty())
         {
-            for (HttpReverseProxyPathMapper proxyPathMapper : proxyPathMappers)
+            for (HttpReverseProxyPathMapper proxyPathMapper : proxyPathGlobMappers)
             {
-                if (StringUtils.startsWith(remoteURL, proxyPathMapper.getRemoteBaseURL()))
+                Pattern pattern = localBasePathGlobPatternMap.get(proxyPathMapper);
+                
+                if (pattern == null)
                 {
-                    return proxyPathMapper;
+                    try
+                    {
+                        pattern = Pattern.compile(StringUtils.replaceEach(proxyPathMapper.getLocalBasePath(), GLOB_EXPR_SEARCHES, GLOB_EXPR_REPLACES));
+                    }
+                    catch (Exception e)
+                    {
+                        if (log.isDebugEnabled())
+                        {
+                            log.error("Failed to create regular expression pattern. Blacklisted: " + proxyPathMapper.getLocalBasePath(), e);
+                        }
+                        else
+                        {
+                            log.error("Failed to create regular expression pattern. Blacklisted: {}. {}", proxyPathMapper.getLocalBasePath(), e);
+                        }
+                    }
+                    
+                    if (pattern != null)
+                    {
+                        localBasePathGlobPatternMap.put(proxyPathMapper, pattern);
+                    }
+                }
+                
+                if (pattern != null)
+                {
+                    Matcher matcher = pattern.matcher(pathInfo);
+                    
+                    if (matcher.lookingAt())
+                    {
+                        int groupCount = matcher.groupCount();
+                        String [] replaces = new String[groupCount];
+                        String [] searches = new String[groupCount];
+                        
+                        for (int i = 0; i < groupCount; i++)
+                        {
+                            replaces[i] = matcher.group(i + 1);
+                            searches[i] = "$" + (i + 1);
+                        }
+                        
+                        HttpReverseProxyPathMapper cloned = (HttpReverseProxyPathMapper) proxyPathMapper.clone();
+                        String localBasePath = matcher.group(0);
+                        cloned.setName(proxyPathMapper.getName() + ":" + localBasePath);
+                        cloned.setLocalBasePath(localBasePath);
+                        cloned.setRemoteBaseURL(StringUtils.replaceEach(proxyPathMapper.getRemoteBaseURL(), searches, replaces));
+                        
+                        RewriterController rewriterController = rewriterControllerMap.get(proxyPathMapper);
+                        Ruleset rewriterRules = rewriterRulesetMap.get(proxyPathMapper);
+                        
+                        if (rewriterController != null)
+                        {
+                            rewriterControllerMap.put(cloned, rewriterController);
+                        }
+                        
+                        if (rewriterRules != null)
+                        {
+                            rewriterRulesetMap.put(cloned, rewriterRules);
+                        }
+                        
+                        synchronized (proxyPathMappers)
+                        {
+                            if (!proxyPathMappers.contains(cloned))
+                            {
+                                proxyPathMappers.add(cloned);
+                            }
+                        }
+                        
+                        return cloned;
+                    }
                 }
             }
         }
         
         return null;
     }
-
-    public RewriterController findRewriterController(HttpServletRequest request)
+    
+    public HttpReverseProxyPathMapper findMapperByRemoteURL(String remoteURL)
     {
-        String pathInfo = request.getPathInfo();
+        if (remoteURL == null)
+        {
+            return null;
+        }
+        
+        int mapperCount = proxyPathMappers.size();
         
-        for (KeyValue pair : rewriterControllerPairs)
+        for (int i = 0; i < mapperCount; i++)
         {
-            if (StringUtils.startsWith(pathInfo, (String) pair.getKey()))
+            HttpReverseProxyPathMapper proxyPathMapper = proxyPathMappers.get(i);
+            
+            if (StringUtils.startsWith(remoteURL, proxyPathMapper.getRemoteBaseURL()))
             {
-                return (RewriterController) pair.getValue();
+                return proxyPathMapper;
             }
         }
         
-        return null;
-    }
-    
-    public Ruleset findRewriterRuleset(HttpServletRequest request)
-    {
-        String pathInfo = request.getPathInfo();
-        
-        for (KeyValue pair : rewriterRulesetPairs)
+        if (!proxyPathGlobMappers.isEmpty())
         {
-            if (StringUtils.startsWith(pathInfo, (String) pair.getKey()))
+            for (HttpReverseProxyPathMapper proxyPathMapper : proxyPathGlobMappers)
             {
-                return (Ruleset) pair.getValue();
+                Pattern pattern = remoteBaseURLGlobPatternMap.get(proxyPathMapper);
+                
+                if (pattern == null)
+                {
+                    try
+                    {
+                        String expr = StringUtils.replaceEach(proxyPathMapper.getRemoteBaseURL(), GLOB_EXPR_SEARCHES, GLOB_EXPR_REPLACES);
+                        expr = StringUtils.replaceEach(expr, GROUP_REF_SEARCHES, GROUP_REF_REPLACES);
+                        pattern = Pattern.compile(expr);
+                    }
+                    catch (Exception e)
+                    {
+                        if (log.isDebugEnabled())
+                        {
+                            log.error("Failed to create regular expression pattern: " + proxyPathMapper.getRemoteBaseURL(), e);
+                        }
+                        else
+                        {
+                            log.error("Failed to create regular expression pattern: {}. {}", proxyPathMapper.getRemoteBaseURL(), e);
+                        }
+                    }
+                    
+                    if (pattern != null)
+                    {
+                        remoteBaseURLGlobPatternMap.put(proxyPathMapper, pattern);
+                    }
+                }
+                
+                if (pattern != null)
+                {
+                    Matcher matcher = pattern.matcher(remoteURL);
+                    
+                    if (matcher.lookingAt())
+                    {
+                        int groupCount = matcher.groupCount();
+                        String [] replaces = new String[groupCount];
+                        String [] searches = new String[groupCount];
+                        
+                        for (int i = 0; i < groupCount; i++)
+                        {
+                            replaces[i] = matcher.group(i + 1);
+                            searches[i] = "$" + (i + 1);
+                        }
+                        
+                        HttpReverseProxyPathMapper cloned = (HttpReverseProxyPathMapper) proxyPathMapper.clone();
+                        String remoteBaseURL = matcher.group(0);
+                        cloned.setRemoteBaseURL(remoteBaseURL);
+                        String localBasePath = proxyPathMapper.getLocalBasePath();
+                        
+                        for (int i = 1; StringUtils.contains(localBasePath, '*'); i++)
+                        {
+                            localBasePath = StringUtils.replaceOnce(localBasePath, "*", "$" + i);
+                        }
+                        
+                        localBasePath = StringUtils.replaceEach(localBasePath, searches, replaces);
+                        cloned.setName(proxyPathMapper.getName() + ":" + localBasePath);
+                        cloned.setLocalBasePath(localBasePath);
+                        
+                        RewriterController rewriterController = rewriterControllerMap.get(proxyPathMapper);
+                        Ruleset rewriterRules = rewriterRulesetMap.get(proxyPathMapper);
+                        
+                        if (rewriterController != null)
+                        {
+                            rewriterControllerMap.put(cloned, rewriterController);
+                        }
+                        
+                        if (rewriterRules != null)
+                        {
+                            rewriterRulesetMap.put(cloned, rewriterRules);
+                        }
+                        
+                        synchronized (proxyPathMappers)
+                        {
+                            if (!proxyPathMappers.contains(cloned))
+                            {
+                                proxyPathMappers.add(cloned);
+                            }
+                        }
+                        
+                        return cloned;
+                    }
+                }
             }
         }
         
         return null;
     }
+
+    public RewriterController getRewriterController(HttpReverseProxyPathMapper proxyPathMapper)
+    {
+        return rewriterControllerMap.get(proxyPathMapper);
+    }
+    
+    public Ruleset getRewriterRuleset(HttpReverseProxyPathMapper proxyPathMapper)
+    {
+        return rewriterRulesetMap.get(proxyPathMapper);
+    }
     
     public List<HttpReverseProxyPathMapper> getProxyPathMappers()
     {

Modified: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyServlet.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyServlet.java?rev=820733&r1=820732&r2=820733&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyServlet.java (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyServlet.java Thu Oct  1 17:56:43 2009
@@ -34,8 +34,6 @@
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.commons.beanutils.BeanUtils;
-import org.apache.commons.collections.KeyValue;
-import org.apache.commons.collections.keyvalue.DefaultKeyValue;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.PropertiesConfiguration;
 import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
@@ -133,22 +131,24 @@
         
         List<HttpReverseProxyPathMapper> proxyPathMappers = new ArrayList<HttpReverseProxyPathMapper>();
         
-        List<KeyValue> rewriterControllerPairs = new ArrayList<KeyValue>();
-        List<KeyValue> rewriterRulesetPairs = new ArrayList<KeyValue>();
+        Map<HttpReverseProxyPathMapper, RewriterController> rewriterControllerMap = new HashMap<HttpReverseProxyPathMapper, RewriterController>();
+        Map<HttpReverseProxyPathMapper, Ruleset> rewriterRulesetMap = new HashMap<HttpReverseProxyPathMapper, Ruleset>();
         
         Configuration passConf = configuration.subset("proxy.reverse.pass");
         String [] pathNames = passConf.getStringArray("");
         
-        try
+        for (String pathName : pathNames)
         {
-            for (String pathName : pathNames)
+            Configuration pathPassConf = passConf.subset(pathName);
+            
+            String localBasePath = pathPassConf.getString("local");
+            String remoteBaseURL = pathPassConf.getString("remote");
+            
+            try
             {
-                Configuration pathPassConf = passConf.subset(pathName);
-                
-                String localBasePath = pathPassConf.getString("local");
-                String remoteBaseURL = pathPassConf.getString("remote");
-                
-                proxyPathMappers.add(new DefaultHttpReverseProxyPathMapperImpl(localBasePath, remoteBaseURL));
+                HttpReverseProxyPathMapper proxyPathMapper = 
+                    new DefaultHttpReverseProxyPathMapperImpl(pathName, localBasePath, remoteBaseURL);
+                proxyPathMappers.add(proxyPathMapper);
                 
                 Configuration rewritersConf = pathPassConf.subset("rewriter");
                 
@@ -158,25 +158,33 @@
                     
                     if (rewriterController != null)
                     {
-                        rewriterControllerPairs.add(new DefaultKeyValue(localBasePath, rewriterController));
+                        rewriterControllerMap.put(proxyPathMapper, rewriterController);
                         
                         String rules = rewritersConf.getString("rules");
                         Ruleset ruleset = loadRewriterRuleset(rewriterController, rules);
                         
                         if (ruleset != null)
                         {
-                            rewriterRulesetPairs.add(new DefaultKeyValue(localBasePath, ruleset));
+                            rewriterRulesetMap.put(proxyPathMapper, ruleset);
                         }
                     }
                 }
             }
-        }
-        catch (Exception e)
-        {
-            throw new ServletException("Failed to initialize url mappings. " + e);
+            catch (Exception e)
+            {
+                if (log.isDebugEnabled())
+                {
+                    log.error("Failure in initializing path mappings.", e);
+                }
+                else
+                {
+                    log.error("Failure in initializing path mappings. {}", e.toString());
+                }
+            }
         }
         
-        HttpReverseProxyPathMapperProvider proxyPathMapperProvider = new DefaultHttpReverseProxyPathMapperProviderImpl(proxyPathMappers, rewriterControllerPairs, rewriterRulesetPairs);
+        HttpReverseProxyPathMapperProvider proxyPathMapperProvider = 
+            new DefaultHttpReverseProxyPathMapperProviderImpl(proxyPathMappers, rewriterControllerMap, rewriterRulesetMap);
         HttpReverseProxyService tempProxyService = new RewritableHttpReverseProxyServiceImpl(proxyPathMapperProvider);
         
         Configuration serverConf = configuration.subset("proxy.server");

Modified: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/PassMappingLinkRewritingParserAaptor.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/PassMappingLinkRewritingParserAaptor.java?rev=820733&r1=820732&r2=820733&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/PassMappingLinkRewritingParserAaptor.java (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/PassMappingLinkRewritingParserAaptor.java Thu Oct  1 17:56:43 2009
@@ -24,6 +24,8 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.apache.commons.collections.KeyValue;
+import org.apache.commons.collections.keyvalue.DefaultKeyValue;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.LineIterator;
 import org.apache.commons.lang.StringUtils;
@@ -34,6 +36,8 @@
 import org.apache.portals.applications.webcontent.rewriter.ParserAdaptor;
 import org.apache.portals.applications.webcontent.rewriter.Rewriter;
 import org.apache.portals.applications.webcontent.rewriter.RewriterException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * A simple reverse proxy link rewriting parser adaptor implementation.
@@ -46,17 +50,29 @@
 public class PassMappingLinkRewritingParserAaptor implements ParserAdaptor, ReverseProxyRewritingContextAware
 {
     
-    private ReverseProxyRewritingContext reverseProxyRewritingContext;
+    private static Logger log = LoggerFactory.getLogger(PassMappingLinkRewritingParserAaptor.class);
     
-    private Pattern linkBasePathPattern = Pattern.compile("\\s(href|src|action)\\s*=\\s*['\"]((\\/)[^'\"]+)['\"]", Pattern.CASE_INSENSITIVE);
+    protected boolean lookUpAllMappings = true;
     
-    private String [] linkRemoteBaseURLSearches = { "/", "." };
-    private String [] linkRemoteBaseURLReplaces = { "\\/", "\\." };
+    protected ReverseProxyRewritingContext reverseProxyRewritingContext;
+    
+    protected Pattern linkBasePathPattern = Pattern.compile("\\s(href|src|action)\\s*=\\s*(['\"])((\\/)[^'\"]+)['\"]", Pattern.CASE_INSENSITIVE);
+    
+    protected String [] linkRemoteBaseURLSearches = { "/", "." };
+    protected String [] linkRemoteBaseURLReplaces = { "\\/", "\\." };
+    
+    private KeyValue [] remoteURLPatternReplacesPairs;
+    private KeyValue myURLPatternReplacesPair;
     
     public PassMappingLinkRewritingParserAaptor()
     {
     }
     
+    public PassMappingLinkRewritingParserAaptor(boolean lookUpAllMappings)
+    {
+        this.lookUpAllMappings = lookUpAllMappings;
+    }
+    
     public void setReverseProxyRewritingContext(ReverseProxyRewritingContext reverseProxyRewritingContext)
     {
         this.reverseProxyRewritingContext = reverseProxyRewritingContext;
@@ -64,42 +80,45 @@
     
     public void rewrite(Rewriter rewriter, Reader reader, Writer writer) throws RewriterException
     {
-        HttpReverseProxyPathMapperProvider mapperProvider = reverseProxyRewritingContext.getHttpReverseProxyPathMapperProvider();
-        HttpReverseProxyPathMapper myProxyMapper = reverseProxyRewritingContext.getHttpReverseProxyPathMapper();
-        String rewritingContextPath = reverseProxyRewritingContext.getRewritingContextPath();
-        
-        String localBasePath = myProxyMapper.getLocalBasePath();
-        String normalizedLocalBasePath = StringUtils.removeEnd(localBasePath, "/");
-
-        List<HttpReverseProxyPathMapper> proxyMappers = mapperProvider.getProxyPathMappers();
-        int proxyMappersCount = proxyMappers.size();
-        Pattern [] proxyMapperRemoteURLPatterns = new Pattern[proxyMappersCount];
-        String [] proxyMapperMatcherReplaces = new String[proxyMappersCount];
-        
-        int index = 0;
-        for (HttpReverseProxyPathMapper proxyMapper : proxyMappers)
-        {
-            String remoteBaseURLPattern = StringUtils.replaceEach(StringUtils.removeEnd(proxyMapper.getRemoteBaseURL(), "/"), linkRemoteBaseURLSearches, linkRemoteBaseURLReplaces);
-            proxyMapperRemoteURLPatterns[index] = Pattern.compile("\\s(href|src|action)\\s*=\\s*['\"](" + remoteBaseURLPattern + "([^'\"]+))['\"]", Pattern.CASE_INSENSITIVE);
-            proxyMapperMatcherReplaces[index] = rewritingContextPath + StringUtils.removeEnd(proxyMapper.getLocalBasePath(), "/");
-            ++index;
-        }
+        String myLocalPathMatchingReplaces = createLocalPathMatchingReplaces(reverseProxyRewritingContext.getHttpReverseProxyPathMapper());
         
         PrintWriter out = new PrintWriter(new BufferedWriter(writer));
         
         for (LineIterator lineIt = IOUtils.lineIterator(reader); lineIt.hasNext(); )
         {
             String line = lineIt.nextLine();
+            String tempLine = line;
             
-            // first, replace slash leading relative paths by slash leading reverse proxying relative paths. 
-            Matcher linkBasePathMatcher = linkBasePathPattern.matcher(line);
-            line = linkBasePathMatcher.replaceAll(" $1=\"" + rewritingContextPath + normalizedLocalBasePath + "$2\"");
-            
-            // second, replace absolute urls by slash leading relative paths.
-            for (int i = 0; i < proxyMappersCount; i++)
+            if (!StringUtils.isBlank(line))
             {
-                Matcher otherLinkBasePathMatcher = proxyMapperRemoteURLPatterns[i].matcher(line);
-                line = otherLinkBasePathMatcher.replaceAll(" $1=\"" + proxyMapperMatcherReplaces[i] + "$3\"");
+                try
+                {
+                    // first, replace slash leading relative paths by slash leading reverse proxying relative paths. 
+                    Matcher linkBasePathMatcher = linkBasePathPattern.matcher(tempLine);
+                    tempLine = linkBasePathMatcher.replaceAll(" $1=$2" + myLocalPathMatchingReplaces + "$3$2");
+                    
+                    // second, replace absolute urls by slash leading relative paths.
+                    if (lookUpAllMappings)
+                    {
+                        for (KeyValue pair : getRemoteURLPatternReplacesPairs())
+                        {
+                            Matcher otherLinkBasePathMatcher = ((Pattern) pair.getKey()).matcher(tempLine);
+                            tempLine = otherLinkBasePathMatcher.replaceAll(" $1=$2" + ((String) pair.getValue()) + "$5$2");
+                        }
+                    }
+                    else
+                    {
+                        KeyValue pair = getMyURLPatternReplacesPair();
+                        Matcher otherLinkBasePathMatcher = ((Pattern) pair.getKey()).matcher(tempLine);
+                        tempLine = otherLinkBasePathMatcher.replaceAll(" $1=$2" + ((String) pair.getValue()) + "$5$2");
+                    }
+                    
+                    line = tempLine;
+                }
+                catch (Exception e)
+                {
+                    log.warn("Error during {}: {}", "replacement", e);
+                }
             }
             
             out.println(line);
@@ -108,6 +127,58 @@
         out.flush();
     }
     
+    protected Pattern createRemoteURLMatchingPattern(HttpReverseProxyPathMapper proxyMapper)
+    {
+        Pattern pattern = null;
+        String remoteBaseURLPattern = null;
+        
+        log.info("remoteBaseURL: {}", proxyMapper.getRemoteBaseURL());
+        log.info("replaced: {}", StringUtils.replaceEach(StringUtils.removeEnd(proxyMapper.getRemoteBaseURL(), "/"), linkRemoteBaseURLSearches, linkRemoteBaseURLReplaces));
+
+        remoteBaseURLPattern = StringUtils.replaceEach(StringUtils.removeEnd(proxyMapper.getRemoteBaseURL(), "/"), linkRemoteBaseURLSearches, linkRemoteBaseURLReplaces);
+        pattern = Pattern.compile("\\s(href|src|action)\\s*=\\s*(['\"])((" + remoteBaseURLPattern + ")([^'\"]+))['\"]", Pattern.CASE_INSENSITIVE);
+        
+        return pattern;
+    }
+    
+    protected String createLocalPathMatchingReplaces(HttpReverseProxyPathMapper proxyMapper)
+    {
+        return reverseProxyRewritingContext.getRewritingContextPath() + StringUtils.removeEnd(proxyMapper.getLocalBasePath(), "/");
+    }
+    
+    protected KeyValue [] getRemoteURLPatternReplacesPairs()
+    {
+        if (remoteURLPatternReplacesPairs == null)
+        {
+            HttpReverseProxyPathMapperProvider mapperProvider = reverseProxyRewritingContext.getHttpReverseProxyPathMapperProvider();
+            List<HttpReverseProxyPathMapper> proxyMappers = mapperProvider.getProxyPathMappers();
+            int proxyMappersCount = proxyMappers.size();
+            remoteURLPatternReplacesPairs = new KeyValue[proxyMappersCount];
+            
+            int index = 0;
+            for (HttpReverseProxyPathMapper proxyMapper : proxyMappers)
+            {
+                remoteURLPatternReplacesPairs[index] = 
+                    new DefaultKeyValue(createRemoteURLMatchingPattern(proxyMapper),
+                                        createLocalPathMatchingReplaces(proxyMapper));
+                ++index;
+            }
+        }
+        
+        return remoteURLPatternReplacesPairs;
+    }
+    
+    protected KeyValue getMyURLPatternReplacesPair()
+    {
+        if (myURLPatternReplacesPair == null)
+        {
+            HttpReverseProxyPathMapper proxyMapper = reverseProxyRewritingContext.getHttpReverseProxyPathMapper();
+            myURLPatternReplacesPair = new DefaultKeyValue(createRemoteURLMatchingPattern(proxyMapper), createLocalPathMatchingReplaces(proxyMapper));
+        }
+        
+        return myURLPatternReplacesPair;
+    }
+    
     public void parse(Rewriter rewriter, Reader reader) throws RewriterException
     {
         throw new UnsupportedOperationException();

Modified: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java?rev=820733&r1=820732&r2=820733&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java Thu Oct  1 17:56:43 2009
@@ -420,7 +420,7 @@
             httpRequest.abort();
             httpEntity = null;
             
-            throw new IOException(e.getLocalizedMessage());
+            throw new IOException(e.toString());
         }
         finally
         {
@@ -431,7 +431,9 @@
         }
     }
     
-    private void writeHttpEntityToClient(HttpServletRequest request, HttpServletResponse response, HttpEntity httpEntity, HttpReverseProxyPathMapper proxyPathMapper, String rewriterContextPath) throws IOException
+    private void writeHttpEntityToClient(HttpServletRequest request, HttpServletResponse response, 
+                                         HttpEntity httpEntity, 
+                                         HttpReverseProxyPathMapper proxyPathMapper, String rewriterContextPath) throws IOException
     {
         InputStream in = null;
         Reader reader = null;
@@ -448,12 +450,12 @@
             {
                 out = response.getOutputStream();
 
-                RewriterController rewriterController = proxyPathMapperProvider.findRewriterController(request);
+                RewriterController rewriterController = proxyPathMapperProvider.getRewriterController(proxyPathMapper);
                 Rewriter rewriter = null;
                 
                 if (rewriterController != null)
                 {
-                    Ruleset rewriterRuleset = proxyPathMapperProvider.findRewriterRuleset(request);
+                    Ruleset rewriterRuleset = proxyPathMapperProvider.getRewriterRuleset(proxyPathMapper);
                     
                     if (rewriterRuleset == null)
                     {

Modified: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/SimpleLinkRewritingParserAaptor.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/SimpleLinkRewritingParserAaptor.java?rev=820733&r1=820732&r2=820733&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/SimpleLinkRewritingParserAaptor.java (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/SimpleLinkRewritingParserAaptor.java Thu Oct  1 17:56:43 2009
@@ -16,85 +16,17 @@
  */
 package org.apache.portals.applications.webcontent.proxy.impl;
 
-import java.io.BufferedWriter;
-import java.io.PrintWriter;
-import java.io.Reader;
-import java.io.Writer;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.io.LineIterator;
-import org.apache.commons.lang.StringUtils;
-import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapper;
-import org.apache.portals.applications.webcontent.proxy.ReverseProxyRewritingContext;
-import org.apache.portals.applications.webcontent.proxy.ReverseProxyRewritingContextAware;
-import org.apache.portals.applications.webcontent.rewriter.ParserAdaptor;
-import org.apache.portals.applications.webcontent.rewriter.Rewriter;
-import org.apache.portals.applications.webcontent.rewriter.RewriterException;
 
 /**
- * A simple reverse proxy link rewriting parser adaptor implementation.
- * <P>
- * You can refer to this example to implement more sophisticated rewriting parser adaptor.
- * </P>
+ * A simple reverse proxy link rewriting parser adaptor implementation. 
+ * <P>This adaptor looks up its own proxy path mapper only.</P>
  * 
  * @version $Id$
  */
-public class SimpleLinkRewritingParserAaptor implements ParserAdaptor, ReverseProxyRewritingContextAware
+public class SimpleLinkRewritingParserAaptor extends PassMappingLinkRewritingParserAaptor
 {
-    
-    private ReverseProxyRewritingContext reverseProxyRewritingContext;
-    
-    private Pattern linkBasePathPattern = Pattern.compile("\\s(href|src|action)\\s*=\\s*['\"]((\\/)[^'\"]+)['\"]", Pattern.CASE_INSENSITIVE);
-    
-    private String [] linkRemoteBaseURLSearches = { "/", "." };
-    private String [] linkRemoteBaseURLReplaces = { "\\/", "\\." };
-    
     public SimpleLinkRewritingParserAaptor()
     {
+        super(false);
     }
-    
-    public void setReverseProxyRewritingContext(ReverseProxyRewritingContext reverseProxyRewritingContext)
-    {
-        this.reverseProxyRewritingContext = reverseProxyRewritingContext;
-    }
-    
-    public void rewrite(Rewriter rewriter, Reader reader, Writer writer) throws RewriterException
-    {
-        HttpReverseProxyPathMapper myProxyMapper = reverseProxyRewritingContext.getHttpReverseProxyPathMapper();
-        String rewritingContextPath = reverseProxyRewritingContext.getRewritingContextPath();
-        
-        String localBasePath = myProxyMapper.getLocalBasePath();
-        String normalizedLocalBasePath = StringUtils.removeEnd(localBasePath, "/");
-
-        String remoteBaseURLPattern = StringUtils.replaceEach(StringUtils.removeEnd(myProxyMapper.getRemoteBaseURL(), "/"), linkRemoteBaseURLSearches, linkRemoteBaseURLReplaces);
-        Pattern proxyMapperRemoteURLPattern = Pattern.compile("\\s(href|src|action)\\s*=\\s*['\"](" + remoteBaseURLPattern + "([^'\"]+))['\"]", Pattern.CASE_INSENSITIVE);
-        String proxyMapperMatcherReplace = rewritingContextPath + StringUtils.removeEnd(myProxyMapper.getLocalBasePath(), "/");
-        
-        PrintWriter out = new PrintWriter(new BufferedWriter(writer));
-        
-        for (LineIterator lineIt = IOUtils.lineIterator(reader); lineIt.hasNext(); )
-        {
-            String line = lineIt.nextLine();
-            
-            // first, replace slash leading relative paths by slash leading reverse proxying relative paths. 
-            Matcher linkBasePathMatcher = linkBasePathPattern.matcher(line);
-            line = linkBasePathMatcher.replaceAll(" $1=\"" + rewritingContextPath + normalizedLocalBasePath + "$2\"");
-            
-            // second, replace absolute urls by slash leading relative paths.
-            Matcher otherLinkBasePathMatcher = proxyMapperRemoteURLPattern.matcher(line);
-            line = otherLinkBasePathMatcher.replaceAll(" $1=\"" + proxyMapperMatcherReplace + "$3\"");
-            
-            out.println(line);
-        }
-        
-        out.flush();
-    }
-    
-    public void parse(Rewriter rewriter, Reader reader) throws RewriterException
-    {
-        throw new UnsupportedOperationException();
-    }
-    
 }

Added: portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestProxyPathMappings.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestProxyPathMappings.java?rev=820733&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestProxyPathMappings.java (added)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestProxyPathMappings.java Thu Oct  1 17:56:43 2009
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.portals.applications.webcontent.proxy;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import junit.framework.TestCase;
+
+import org.apache.portals.applications.webcontent.proxy.impl.DefaultHttpReverseProxyPathMapperImpl;
+import org.apache.portals.applications.webcontent.proxy.impl.DefaultHttpReverseProxyPathMapperProviderImpl;
+import org.apache.portals.applications.webcontent.rewriter.RewriterController;
+import org.apache.portals.applications.webcontent.rewriter.rules.Ruleset;
+import org.easymock.EasyMock;
+
+/**
+ * TestProxyPassMappings
+ * 
+ * @version $Id$
+ */
+public class TestProxyPathMappings extends TestCase
+{
+    private HttpReverseProxyPathMapperProvider pathMapperProvider;
+    
+    @Override
+    public void setUp()
+    {
+        Map<HttpReverseProxyPathMapper, RewriterController> rewriterControllerMap = new HashMap<HttpReverseProxyPathMapper, RewriterController>();
+        Map<HttpReverseProxyPathMapper, Ruleset> rewriterRulesetMap = new HashMap<HttpReverseProxyPathMapper, Ruleset>();
+        List<HttpReverseProxyPathMapper> proxyPathMappers = new ArrayList<HttpReverseProxyPathMapper>();
+        proxyPathMappers.add(new DefaultHttpReverseProxyPathMapperImpl("localhost", "/localhost/", "http://www.localhost.com/"));
+        proxyPathMappers.add(new DefaultHttpReverseProxyPathMapperImpl("apache", "/*_apache/", "http://$1.apache.org/"));
+        pathMapperProvider = new DefaultHttpReverseProxyPathMapperProviderImpl(proxyPathMappers, rewriterControllerMap, rewriterRulesetMap);
+    }
+    
+    public void testProxyPathMappings() throws Exception
+    {
+        HttpReverseProxyPathMapper mapper = null;
+        HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+
+        EasyMock.reset(request);
+        EasyMock.expect(request.getPathInfo()).andReturn("/localhost/index.html");
+        EasyMock.replay(request);
+
+        mapper = pathMapperProvider.findMapper(request);
+        assertEquals("localhost", mapper.getName());
+        mapper = pathMapperProvider.findMapperByRemoteURL("http://www.localhost.com/index.html");
+        assertEquals("localhost", mapper.getName());
+        
+        EasyMock.reset(request);
+        EasyMock.expect(request.getPathInfo()).andReturn("/www_apache/index.html");
+        EasyMock.replay(request);
+
+        mapper = pathMapperProvider.findMapper(request);
+        assertEquals("apache:/www_apache/", mapper.getName());
+        mapper = pathMapperProvider.findMapperByRemoteURL("http://www.apache.org/index.html");
+        assertEquals("apache:/www_apache/", mapper.getName());
+        assertEquals("http://www.apache.org/index.html", mapper.getRemoteURL("/www_apache/index.html"));
+        assertEquals("/www_apache/index.html", mapper.getLocalPath("http://www.apache.org/index.html"));
+        
+        EasyMock.reset(request);
+        EasyMock.expect(request.getPathInfo()).andReturn("/portals_apache/index.html");
+        EasyMock.replay(request);
+        
+        mapper = pathMapperProvider.findMapper(request);
+        assertEquals("apache:/portals_apache/", mapper.getName());
+        mapper = pathMapperProvider.findMapperByRemoteURL("http://portals.apache.org/index.html");
+        assertEquals("apache:/portals_apache/", mapper.getName());
+        assertEquals("http://portals.apache.org/index.html", mapper.getRemoteURL("/portals_apache/index.html"));
+        assertEquals("/portals_apache/index.html", mapper.getLocalPath("http://portals.apache.org/index.html"));
+    }
+    
+    public void testProxyURLMappings() throws Exception
+    {
+        HttpReverseProxyPathMapper mapper = pathMapperProvider.findMapperByRemoteURL("http://www.apache.org/index.html");
+        assertEquals("/www_apache/", mapper.getLocalBasePath());
+        
+        mapper = pathMapperProvider.findMapperByRemoteURL("http://portals.apache.org/index.html");
+        assertEquals("/portals_apache/", mapper.getLocalBasePath());
+        
+        mapper = pathMapperProvider.findMapperByRemoteURL("http://www.localhost.com/index.html");
+        assertEquals("/localhost/", mapper.getLocalBasePath());
+    }
+    
+}

Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestProxyPathMappings.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestProxyPathMappings.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestProxyPathMappings.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestReverseProxyLinkRewritingParserAaptor.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestReverseProxyLinkRewritingParserAaptor.java?rev=820733&r1=820732&r2=820733&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestReverseProxyLinkRewritingParserAaptor.java (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestReverseProxyLinkRewritingParserAaptor.java Thu Oct  1 17:56:43 2009
@@ -18,8 +18,12 @@
 
 import java.io.StringReader;
 import java.io.StringWriter;
-import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
 
 import junit.framework.TestCase;
 
@@ -29,7 +33,11 @@
 import org.apache.portals.applications.webcontent.proxy.impl.DefaultHttpReverseProxyPathMapperProviderImpl;
 import org.apache.portals.applications.webcontent.proxy.impl.DefaultReverseProxyRewritingContext;
 import org.apache.portals.applications.webcontent.proxy.impl.PassMappingLinkRewritingParserAaptor;
-import org.apache.portals.applications.webcontent.proxy.impl.SimpleLinkRewritingParserAaptor;
+import org.apache.portals.applications.webcontent.rewriter.RewriterController;
+import org.apache.portals.applications.webcontent.rewriter.rules.Ruleset;
+import org.easymock.EasyMock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * TestSimpleLinkRewritingParserAaptor
@@ -39,64 +47,75 @@
 public class TestReverseProxyLinkRewritingParserAaptor extends TestCase
 {
     
+    private static Logger log = LoggerFactory.getLogger(TestReverseProxyLinkRewritingParserAaptor.class);
+    
     private String html =
         "<html>\n" +
         "<p><a href=\"mission.html\">Mission</a> and <a href='about.html'>About</a></p>\n" +
-        "<p><a href=\"/docs/\">Documents</a></p>\n" +
+        "<p><a href=\"/docs/\">Docs</a> and <a href='/documents/'>Documents</a></p>\n" +
         "<p><a href=\"http://portals.apache.org/projectinfo.html\">Project Info.</a></p>\n" +
-        "<p><a href=\"http://www.apache.org/events.html\">Events</a></p>\n" +
+        "<p><a href=\"http://www.apache.org/events.html\">Events</a> <a href='http://www.apache.org/apachecon.html'>Apache Con</a></p>\n" +
+        "<p><a href=\"http://www.localhost.com/manager/list\">Application Management</a> <a href='http://www.localhost.com/manager/start'>Start Application</a></p>\n" +
         "</html>";
     
-    public void testSimpleRewriting() throws Exception
+    private HttpReverseProxyPathMapperProvider proxyPathMapperProvider;
+    private HttpReverseProxyPathMapper apacheProxyPathMapper;
+    private HttpReverseProxyPathMapper localhostProxyPathMapper;
+    
+    @Override
+    public void setUp()
     {
-        SimpleLinkRewritingParserAaptor parserAdaptor = new SimpleLinkRewritingParserAaptor();
-        HttpReverseProxyPathMapper portalsProxyPathMapper = new DefaultHttpReverseProxyPathMapperImpl("/portals/", "http://portals.apache.org/");
-        HttpReverseProxyPathMapper apacheProxyPathMapper = new DefaultHttpReverseProxyPathMapperImpl("/apache/", "http://www.apache.org/");
-        HttpReverseProxyPathMapper localhostProxyPathMapper = new DefaultHttpReverseProxyPathMapperImpl("/localhost/", "http://www.localhost.com/");
-        HttpReverseProxyPathMapperProvider proxyPathMapperProvider =
-            new DefaultHttpReverseProxyPathMapperProviderImpl(Arrays.asList(new HttpReverseProxyPathMapper [] { portalsProxyPathMapper, apacheProxyPathMapper, localhostProxyPathMapper }), null, null);
-        
-        ReverseProxyRewritingContext rewritingContext = 
-            new DefaultReverseProxyRewritingContext(portalsProxyPathMapper, proxyPathMapperProvider, "/webcontent/rproxy");
-        parserAdaptor.setReverseProxyRewritingContext(rewritingContext);
-        
-        StringReader reader = new StringReader(html);
-        StringWriter writer = new StringWriter();
-        parserAdaptor.rewrite(null, reader, writer);
+        apacheProxyPathMapper = new DefaultHttpReverseProxyPathMapperImpl("apache", "/*_apache/", "http://$1.apache.org/");
+        localhostProxyPathMapper = new DefaultHttpReverseProxyPathMapperImpl("localhost", "/localhost/", "http://www.localhost.com/");
         
-        List<String> lines = (List<String>) IOUtils.readLines(new StringReader(writer.toString()));
+        Map<HttpReverseProxyPathMapper, RewriterController> rewriterControllerMap = new HashMap<HttpReverseProxyPathMapper, RewriterController>();
+        Map<HttpReverseProxyPathMapper, Ruleset> rewriterRulesetMap = new HashMap<HttpReverseProxyPathMapper, Ruleset>();
+        List<HttpReverseProxyPathMapper> proxyPathMappers = new ArrayList<HttpReverseProxyPathMapper>();
+        proxyPathMappers.add(apacheProxyPathMapper);
+        proxyPathMappers.add(localhostProxyPathMapper);
         
-        assertTrue("Wrong rewriting: " + lines.get(1), StringUtils.contains(lines.get(1), "href=\"mission.html\""));
-        assertTrue("Wrong rewriting: " + lines.get(1), StringUtils.contains(lines.get(1), "href='about.html'"));
-        assertTrue("Wrong rewriting: " + lines.get(2), StringUtils.contains(lines.get(2), "href=\"/webcontent/rproxy/portals/docs/\""));
-        assertTrue("Wrong rewriting: " + lines.get(3), StringUtils.contains(lines.get(3), "href=\"/webcontent/rproxy/portals/projectinfo.html\""));
-        assertTrue("Wrong rewriting: " + lines.get(4), StringUtils.contains(lines.get(4), "href=\"http://www.apache.org/events.html\""));
+        proxyPathMapperProvider = new DefaultHttpReverseProxyPathMapperProviderImpl(proxyPathMappers, rewriterControllerMap, rewriterRulesetMap);
     }
     
     public void testPathMappingRewriting() throws Exception
     {
-        PassMappingLinkRewritingParserAaptor parserAdaptor = new PassMappingLinkRewritingParserAaptor();
-        HttpReverseProxyPathMapper portalsProxyPathMapper = new DefaultHttpReverseProxyPathMapperImpl("/portals/", "http://portals.apache.org/");
-        HttpReverseProxyPathMapper apacheProxyPathMapper = new DefaultHttpReverseProxyPathMapperImpl("/apache/", "http://www.apache.org/");
-        HttpReverseProxyPathMapper localhostProxyPathMapper = new DefaultHttpReverseProxyPathMapperImpl("/localhost/", "http://www.localhost.com/");
-        HttpReverseProxyPathMapperProvider proxyPathMapperProvider =
-            new DefaultHttpReverseProxyPathMapperProviderImpl(Arrays.asList(new HttpReverseProxyPathMapper [] { portalsProxyPathMapper, apacheProxyPathMapper, localhostProxyPathMapper }), null, null);
-        
+        HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+
+        EasyMock.reset(request);
+        EasyMock.expect(request.getPathInfo()).andReturn("/portals_apache/index.html");
+        EasyMock.replay(request);
+        proxyPathMapperProvider.findMapper(request);
+        
+        EasyMock.reset(request);
+        EasyMock.expect(request.getPathInfo()).andReturn("/www_apache/index.html");
+        EasyMock.replay(request);
+
         ReverseProxyRewritingContext rewritingContext = 
-            new DefaultReverseProxyRewritingContext(portalsProxyPathMapper, proxyPathMapperProvider, "/webcontent/rproxy");
+            new DefaultReverseProxyRewritingContext(proxyPathMapperProvider.findMapper(request), 
+                                                    proxyPathMapperProvider, 
+                                                    "/webcontent/rproxy");
+        
+        PassMappingLinkRewritingParserAaptor parserAdaptor = new PassMappingLinkRewritingParserAaptor();
         parserAdaptor.setReverseProxyRewritingContext(rewritingContext);
         
         StringReader reader = new StringReader(html);
         StringWriter writer = new StringWriter();
         parserAdaptor.rewrite(null, reader, writer);
         
+        log.info("source: \n" + html);
+        log.info("result: \n" + writer);
+        
         List<String> lines = (List<String>) IOUtils.readLines(new StringReader(writer.toString()));
         
         assertTrue("Wrong rewriting: " + lines.get(1), StringUtils.contains(lines.get(1), "href=\"mission.html\""));
         assertTrue("Wrong rewriting: " + lines.get(1), StringUtils.contains(lines.get(1), "href='about.html'"));
-        assertTrue("Wrong rewriting: " + lines.get(2), StringUtils.contains(lines.get(2), "href=\"/webcontent/rproxy/portals/docs/\""));
-        assertTrue("Wrong rewriting: " + lines.get(3), StringUtils.contains(lines.get(3), "href=\"/webcontent/rproxy/portals/projectinfo.html\""));
-        assertTrue("Wrong rewriting: " + lines.get(4), StringUtils.contains(lines.get(4), "href=\"/webcontent/rproxy/apache/events.html\""));
+        assertTrue("Wrong rewriting: " + lines.get(2), StringUtils.contains(lines.get(2), "href=\"/webcontent/rproxy/www_apache/docs/\""));
+        assertTrue("Wrong rewriting: " + lines.get(2), StringUtils.contains(lines.get(2), "href='/webcontent/rproxy/www_apache/documents/'"));
+        assertTrue("Wrong rewriting: " + lines.get(3), StringUtils.contains(lines.get(3), "href=\"/webcontent/rproxy/portals_apache/projectinfo.html\""));
+        assertTrue("Wrong rewriting: " + lines.get(4), StringUtils.contains(lines.get(4), "href=\"/webcontent/rproxy/www_apache/events.html\""));
+        assertTrue("Wrong rewriting: " + lines.get(4), StringUtils.contains(lines.get(4), "href='/webcontent/rproxy/www_apache/apachecon.html'"));
+        assertTrue("Wrong rewriting: " + lines.get(5), StringUtils.contains(lines.get(5), "href=\"/webcontent/rproxy/localhost/manager/list\""));
+        assertTrue("Wrong rewriting: " + lines.get(5), StringUtils.contains(lines.get(5), "href='/webcontent/rproxy/localhost/manager/start'"));
     }
     
 }

Copied: portals/applications/webcontent/trunk/webcontent-jar/src/test/resources/log4j.properties (from r820182, portals/applications/webcontent/trunk/webcontent-jar/src/test/java/log4j.properties)
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/test/resources/log4j.properties?p2=portals/applications/webcontent/trunk/webcontent-jar/src/test/resources/log4j.properties&p1=portals/applications/webcontent/trunk/webcontent-jar/src/test/java/log4j.properties&r1=820182&r2=820733&rev=820733&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/test/java/log4j.properties (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/test/resources/log4j.properties Thu Oct  1 17:56:43 2009
@@ -12,7 +12,6 @@
 # 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.
-
 # ------------------------------------------------------------------------
 #
 # Logging Configuration
@@ -21,16 +20,15 @@
 #
 # ------------------------------------------------------------------------
 
-log4j.rootLogger = ERROR, errorlogging 
+log4j.rootLogger = INFO, console
 
-log4j.appender.errorlogging = org.apache.log4j.FileAppender
-log4j.appender.errorlogging.file = ${basedir}/target/surefire-reports/tests-error.log
-log4j.appender.errorlogging.layout = org.apache.log4j.PatternLayout
-log4j.appender.errorlogging.layout.conversionPattern = %d [%t] %-5p %c - %m%n
-log4j.appender.errorlogging.append = false
+log4j.category.org.apache.jetspeed = INFO, console
+log4j.additivity.org.apache.jetspeed = false
 
-log4j.appender.infologging = org.apache.log4j.FileAppender
-log4j.appender.infologging.file = ${basedir}/target/surefire-reports/tests-info.log
-log4j.appender.infologging.layout = org.apache.log4j.PatternLayout
-log4j.appender.infologging.layout.conversionPattern = %d [%t] %-5p %c - %m%n
-log4j.appender.infologging.append = false
+#
+# Console
+#
+log4j.appender.console = org.apache.log4j.ConsoleAppender
+log4j.appender.console.layout = org.apache.log4j.PatternLayout
+# Pattern to output the caller's file name and line number.
+log4j.appender.console.layout.ConversionPattern = %d [%t] %-5p %c{1}:%L - %m%n

Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/test/resources/log4j.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/test/resources/log4j.properties
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy.properties
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy.properties?rev=820733&r1=820732&r2=820733&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy.properties (original)
+++ portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy.properties Thu Oct  1 17:56:43 2009
@@ -75,18 +75,15 @@
 
 # ... Sets detail attributes for each path item.
 
-proxy.reverse.pass.apache.local = /apache/
-proxy.reverse.pass.apache.remote = http://www.apache.org/
-
-proxy.reverse.pass.portals.local = /portals/
-proxy.reverse.pass.portals.remote = http://portals.apache.org/
-proxy.reverse.pass.portals.rewriter.basic = org.apache.portals.applications.webcontent.rewriter.WebContentRewriter
-proxy.reverse.pass.portals.rewriter.parserAdaptor = html
+proxy.reverse.pass.apache.local = /*_apache/
+proxy.reverse.pass.apache.remote = http://$1.apache.org/
+proxy.reverse.pass.apache.rewriter.basic = org.apache.portals.applications.webcontent.rewriter.WebContentRewriter
+proxy.reverse.pass.apache.rewriter.parserAdaptor = html
 # ... SimpleLinkRewritingParserAaptor rewrites links only based on its remote base URLs,
 # ... while PassMappingLinkRewritingParserAaptor rewrites links based on all reverse proxy pass mappings.
 #proxy.reverse.pass.portals.rewriter.parserAdaptor.html = org.apache.portals.applications.webcontent.proxy.impl.SimpleLinkRewritingParserAaptor
-proxy.reverse.pass.portals.rewriter.parserAdaptor.html = org.apache.portals.applications.webcontent.proxy.impl.PassMappingLinkRewritingParserAaptor
-proxy.reverse.pass.portals.rewriter.parserAdaptor.html.mimeType = text/html
+proxy.reverse.pass.apache.rewriter.parserAdaptor.html = org.apache.portals.applications.webcontent.proxy.impl.PassMappingLinkRewritingParserAaptor
+proxy.reverse.pass.apache.rewriter.parserAdaptor.html.mimeType = text/html
 
 proxy.reverse.pass.localhost.local = /localhost/
 proxy.reverse.pass.localhost.remote = http://localhost:8080/

Modified: portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/portlet.xml
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/portlet.xml?rev=820733&r1=820732&r2=820733&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/portlet.xml (original)
+++ portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/portlet.xml Thu Oct  1 17:56:43 2009
@@ -139,7 +139,7 @@
       </preference>
       <preference>
         <name>PROXYLOCALPATH</name>
-        <value>${contextPath}/rproxy/portals/</value>
+        <value>${contextPath}/rproxy/portals_apache/</value>
       </preference>
       <preference>
         <name>AUTORESIZE</name>