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/05 19:50:07 UTC

svn commit: r821934 [1/2] - in /portals/applications/webcontent/trunk: webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/ webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/ webcontent-jar/src...

Author: woonsan
Date: Mon Oct  5 17:50:07 2009
New Revision: 821934

URL: http://svn.apache.org/viewvc?rev=821934&view=rev
Log:
APA-17: Improves reverse proxy component.
- Proper 404 handling
- Omitting Content-Length when rewriting happens
- Request headers are configurable for each proxy target host.
- Enhances the default text line based parser adaptor classes hierarchy
- Rewriters, ParserAdaptors are properties-settable for sophisticated uses.
- Optimizing proxy path mapper selection.

Added:
    portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyException.java   (with props)
    portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyNotFoundException.java   (with props)
    portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/AbstractReverseProxyTextLinesParserAdaptor.java   (with props)
    portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultReverseProxyLinkRewritingParserAaptor.java   (contents, props changed)
      - copied, changed from r821705, 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/rewriter/AbstractTextLinesParserAdaptor.java   (with props)
Removed:
    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/SimpleLinkRewritingParserAaptor.java
Modified:
    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/HttpReverseProxyService.java
    portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/SSOSiteCredentialsProvider.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/RewritableHttpReverseProxyServiceImpl.java
    portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/MappingClasspathRewriterController.java
    portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/MappingRewriterController.java
    portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestProxyPathMappings.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

Added: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyException.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyException.java?rev=821934&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyException.java (added)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyException.java Mon Oct  5 17:50:07 2009
@@ -0,0 +1,75 @@
+/*
+ * 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;
+
+/**
+ * The <CODE>HttpReverseProxyException</CODE> class defines a general exception
+ * that an http reverse proxy component can throw when it is unable to perform its operation
+ * successfully.
+ * 
+ * @version $Id$
+ */
+public class HttpReverseProxyException extends Exception {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Constructs a new HttpReverseProxyException exception.
+     */
+    public HttpReverseProxyException() {
+        super();
+    }
+
+    /**
+     * Constructs a new HttpReverseProxyException exception with the given message.
+     *
+     * @param   message
+     *          the exception message
+     */
+    public HttpReverseProxyException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new HttpReverseProxyException exception with the nested exception.
+     *
+     * @param   nested
+     *          the nested exception
+     */
+    public HttpReverseProxyException(Throwable nested) {
+        super(nested);
+    }
+
+    /**
+     * Constructs a new HttpReverseProxyException exception when the container needs to do
+     * the following:
+     * <ul>
+     * <li>throw an exception 
+     * <li>include the "nested" exception
+     * <li>include a description message
+     * </ul>
+     *
+     * @param   msg
+     *          the exception message
+     * @param   nested
+     *          the nested exception
+     */
+    public HttpReverseProxyException(String msg, Throwable nested) {
+        super(msg, nested);
+    }
+    
+}

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

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

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

Added: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyNotFoundException.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyNotFoundException.java?rev=821934&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyNotFoundException.java (added)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyNotFoundException.java Mon Oct  5 17:50:07 2009
@@ -0,0 +1,75 @@
+/*
+ * 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;
+
+/**
+ * The <CODE>HttpReverseProxyNotFoundException</CODE> class defines a not-found-exception
+ * that an http reverse proxy component can throw when it is unable to find web resources
+ * successfully.
+ * 
+ * @version $Id$
+ */
+public class HttpReverseProxyNotFoundException extends HttpReverseProxyException {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Constructs a new HttpReverseProxyNotFoundException exception.
+     */
+    public HttpReverseProxyNotFoundException() {
+        super();
+    }
+
+    /**
+     * Constructs a new HttpReverseProxyNotFoundException exception with the given message.
+     *
+     * @param   message
+     *          the exception message
+     */
+    public HttpReverseProxyNotFoundException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new HttpReverseProxyNotFoundException exception with the nested exception.
+     *
+     * @param   nested
+     *          the nested exception
+     */
+    public HttpReverseProxyNotFoundException(Throwable nested) {
+        super(nested);
+    }
+
+    /**
+     * Constructs a new HttpReverseProxyNotFoundException exception when the container needs to do
+     * the following:
+     * <ul>
+     * <li>throw an exception 
+     * <li>include the "nested" exception
+     * <li>include a description message
+     * </ul>
+     *
+     * @param   msg
+     *          the exception message
+     * @param   nested
+     *          the nested exception
+     */
+    public HttpReverseProxyNotFoundException(String msg, Throwable nested) {
+        super(msg, nested);
+    }
+    
+}

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

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

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

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=821934&r1=821933&r2=821934&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 Mon Oct  5 17:50:07 2009
@@ -16,6 +16,8 @@
  */
 package org.apache.portals.applications.webcontent.proxy;
 
+import java.util.Map;
+
 
 /**
  * proxy path mapper interface for http reverse proxy service.
@@ -59,4 +61,10 @@
      */
     public String getLocalPath(String remoteURL);
     
+    /**
+     * Returns default request headers to the remote URL target.
+     * @return
+     */
+    public Map<String, String> getDefaultRequestHeaders();
+    
 }
\ 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=821934&r1=821933&r2=821934&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 Mon Oct  5 17:50:07 2009
@@ -16,8 +16,6 @@
  */
 package org.apache.portals.applications.webcontent.proxy;
 
-import java.util.List;
-
 import org.apache.portals.applications.webcontent.rewriter.RewriterController;
 import org.apache.portals.applications.webcontent.rewriter.rules.Ruleset;
 
@@ -54,9 +52,9 @@
     public Ruleset getRewriterRuleset(HttpReverseProxyPathMapper proxyPathMapper);
     
     /**
-     * Returns unmodifiable proxy path mappers.
+     * Returns the maximum matching path part count.
      * @return
      */
-    public List<HttpReverseProxyPathMapper> getProxyPathMappers();
+    public int getMaxMatchingPathPartCount();
     
 }
\ No newline at end of file

Modified: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyService.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyService.java?rev=821934&r1=821933&r2=821934&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyService.java (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyService.java Mon Oct  5 17:50:07 2009
@@ -34,6 +34,6 @@
     
     public void destroy();
     
-    public void invoke(HttpServletRequest request, HttpServletResponse response) throws IOException;
+    public void invoke(HttpServletRequest request, HttpServletResponse response) throws HttpReverseProxyException, IOException;
     
 }

Modified: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/SSOSiteCredentialsProvider.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/SSOSiteCredentialsProvider.java?rev=821934&r1=821933&r2=821934&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/SSOSiteCredentialsProvider.java (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/SSOSiteCredentialsProvider.java Mon Oct  5 17:50:07 2009
@@ -16,7 +16,6 @@
  */
 package org.apache.portals.applications.webcontent.proxy;
 
-import java.net.URI;
 import java.util.List;
 
 import javax.servlet.http.HttpServletRequest;

Added: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/AbstractReverseProxyTextLinesParserAdaptor.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/AbstractReverseProxyTextLinesParserAdaptor.java?rev=821934&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/AbstractReverseProxyTextLinesParserAdaptor.java (added)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/AbstractReverseProxyTextLinesParserAdaptor.java Mon Oct  5 17:50:07 2009
@@ -0,0 +1,78 @@
+/*
+ * 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.impl;
+
+import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapper;
+import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapperProvider;
+import org.apache.portals.applications.webcontent.proxy.ReverseProxyRewritingContext;
+import org.apache.portals.applications.webcontent.proxy.ReverseProxyRewritingContextAware;
+import org.apache.portals.applications.webcontent.rewriter.AbstractTextLinesParserAdaptor;
+
+
+/**
+ * AbstractReverseProxyTextLinesParserAdaptor
+ * 
+ * @version $Id$
+ */
+public abstract class AbstractReverseProxyTextLinesParserAdaptor extends AbstractTextLinesParserAdaptor implements ReverseProxyRewritingContextAware
+{
+    
+    private ReverseProxyRewritingContext reverseProxyRewritingContext;
+    private String rewritingContextPath;
+    private HttpReverseProxyPathMapperProvider proxyPathMapperProvider;
+    private int maxMatchingPathPartCount;
+    private HttpReverseProxyPathMapper proxyPathMapper;
+
+    public void setReverseProxyRewritingContext(ReverseProxyRewritingContext reverseProxyRewritingContext)
+    {
+        this.reverseProxyRewritingContext = reverseProxyRewritingContext;
+        
+        if (this.reverseProxyRewritingContext != null)
+        {
+            rewritingContextPath = reverseProxyRewritingContext.getRewritingContextPath();
+            proxyPathMapperProvider = this.reverseProxyRewritingContext.getHttpReverseProxyPathMapperProvider();
+            maxMatchingPathPartCount = proxyPathMapperProvider.getMaxMatchingPathPartCount();
+            proxyPathMapper = this.reverseProxyRewritingContext.getHttpReverseProxyPathMapper();
+        }
+    }
+    
+    protected ReverseProxyRewritingContext getReverseProxyRewritingContext()
+    {
+        return reverseProxyRewritingContext;
+    }
+    
+    protected String getRewritingContextPath()
+    {
+        return rewritingContextPath;
+    }
+
+    protected HttpReverseProxyPathMapperProvider getHttpReverseProxyPathMapperProvider()
+    {
+        return proxyPathMapperProvider;
+    }
+    
+    protected int getMaxMatchingPathPartCount()
+    {
+        return maxMatchingPathPartCount;
+    }
+    
+    protected HttpReverseProxyPathMapper getHttpReverseProxyPathMapper()
+    {
+        return proxyPathMapper;
+    }
+    
+}

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

Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/AbstractReverseProxyTextLinesParserAdaptor.java
------------------------------------------------------------------------------
    svn:keywords = Id

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

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=821934&r1=821933&r2=821934&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 Mon Oct  5 17:50:07 2009
@@ -16,6 +16,8 @@
  */
 package org.apache.portals.applications.webcontent.proxy.impl;
 
+import java.util.Map;
+
 import org.apache.commons.lang.StringUtils;
 import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapper;
 
@@ -29,14 +31,16 @@
     private String name;
     private String localBasePath;
     private String remoteBaseURL;
+    private Map<String, String> defaultRequestHeaders;
     
     private int hash;
     
-    public DefaultHttpReverseProxyPathMapperImpl(String name, String localBasePath, String remoteBaseURL)
+    public DefaultHttpReverseProxyPathMapperImpl(String name, String localBasePath, String remoteBaseURL, Map<String, String> defaultRequestHeaders)
     {
         this.name = name;
         this.localBasePath = localBasePath;
         this.remoteBaseURL = remoteBaseURL;
+        this.defaultRequestHeaders = defaultRequestHeaders;
         hash = new StringBuilder(40).append(name).append(':').append(localBasePath).append(':').append(remoteBaseURL).toString().hashCode();
     }
     
@@ -75,6 +79,11 @@
         return null;
     }
     
+    public Map<String, String> getDefaultRequestHeaders()
+    {
+        return defaultRequestHeaders;
+    }
+    
     @Override
     public int hashCode()
     {
@@ -99,4 +108,5 @@
         
         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=821934&r1=821933&r2=821934&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 Mon Oct  5 17:50:07 2009
@@ -24,6 +24,7 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.apache.commons.collections.map.LRUMap;
 import org.apache.commons.lang.StringUtils;
 import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapper;
 import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapperProvider;
@@ -42,18 +43,34 @@
     
     private static String [] GLOB_EXPR_SEARCHES = { "*", ".", "/", "?", "+" };
     
-    private static String [] GLOB_EXPR_REPLACES = { "(.+)", "\\.", "\\/", "\\?", "\\+" };
+    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 String [] GROUP_REF_REPLACES = { "([^\\/]+)", "([^\\/]+)", "([^\\/]+)", "([^\\/]+)", "([^\\/]+)", 
+                                                    "([^\\/]+)", "([^\\/]+)", "([^\\/]+)", "([^\\/]+)" };
     
     private static Logger log = LoggerFactory.getLogger(DefaultHttpReverseProxyPathMapperProviderImpl.class);
     
     /**
-     * Proxy path mappers
+     * Maximum matching path part count
      */
-    private List<HttpReverseProxyPathMapper> proxyPathMappers;
+    private int maxMatchingPathPartCount = 2;
+    
+    /**
+     * Static proxy path mappers
+     */
+    private Map<String, HttpReverseProxyPathMapper> staticProxyPathMappersMap;
+    
+    /**
+     * Dynamic proxy path mappers
+     */
+    private Map dynamicProxyPathMappersMap;
+    
+    /**
+     * Maximum size of dynamic proxy path map
+     */
+    private int dynamicProxyPathMapperCacheCount;
     
     /**
      * Proxy path Glob mappers
@@ -78,37 +95,93 @@
                                                          Map<HttpReverseProxyPathMapper, RewriterController> rewriterControllerMap,
                                                          Map<HttpReverseProxyPathMapper, Ruleset> rewriterRulesetMap)
     {
+        this(proxyPathMappers, 1000, rewriterControllerMap, rewriterRulesetMap);
+    }
+    
+    public DefaultHttpReverseProxyPathMapperProviderImpl(List<HttpReverseProxyPathMapper> proxyPathMappers, 
+                                                         int dynamicProxyPathMapperCacheCount,
+                                                         Map<HttpReverseProxyPathMapper, RewriterController> rewriterControllerMap,
+                                                         Map<HttpReverseProxyPathMapper, Ruleset> rewriterRulesetMap)
+    {
+        this.dynamicProxyPathMapperCacheCount = dynamicProxyPathMapperCacheCount;
         this.rewriterControllerMap = rewriterControllerMap;
         this.rewriterRulesetMap = rewriterRulesetMap;
         
-        this.proxyPathMappers = Collections.synchronizedList(new ArrayList<HttpReverseProxyPathMapper>());
+        this.staticProxyPathMappersMap = new HashMap<String, HttpReverseProxyPathMapper>();
+        this.dynamicProxyPathMappersMap = Collections.synchronizedMap(new LRUMap(this.dynamicProxyPathMapperCacheCount));
         this.proxyPathGlobMappers = new ArrayList<HttpReverseProxyPathMapper>();
         
+        this.localBasePathGlobPatternMap = Collections.synchronizedMap(new HashMap<HttpReverseProxyPathMapper, Pattern>());
+        this.remoteBaseURLGlobPatternMap = Collections.synchronizedMap(new HashMap<HttpReverseProxyPathMapper, Pattern>());
+        
         for (HttpReverseProxyPathMapper proxyPathMapper : proxyPathMappers)
         {
+            String localBasePath = proxyPathMapper.getLocalBasePath();
+            String remoteBaseURL = proxyPathMapper.getRemoteBaseURL();
+            
             if (!StringUtils.contains(proxyPathMapper.getLocalBasePath(), '*'))
             {
-                this.proxyPathMappers.add(proxyPathMapper);
+                staticProxyPathMappersMap.put(StringUtils.removeEnd(localBasePath, "/"), proxyPathMapper);
+                staticProxyPathMappersMap.put(StringUtils.removeEnd(remoteBaseURL, "/"), proxyPathMapper);
             }
             else
             {
                 this.proxyPathGlobMappers.add(proxyPathMapper);
+                
+                try
+                {
+                    String expr = StringUtils.replaceEach(proxyPathMapper.getLocalBasePath(), GLOB_EXPR_SEARCHES, GLOB_EXPR_REPLACES);
+                    localBasePathGlobPatternMap.put(proxyPathMapper, Pattern.compile(expr));
+                    expr = StringUtils.replaceEach(proxyPathMapper.getRemoteBaseURL(), GLOB_EXPR_SEARCHES, GLOB_EXPR_REPLACES);
+                    expr = StringUtils.replaceEach(expr, GROUP_REF_SEARCHES, GROUP_REF_REPLACES);
+                    remoteBaseURLGlobPatternMap.put(proxyPathMapper, Pattern.compile(expr));
+                }
+                catch (Exception e)
+                {
+                    if (log.isDebugEnabled())
+                    {
+                        log.error("Failed to create regular expression pattern for " + proxyPathMapper.getLocalBasePath(), e);
+                    }
+                    else
+                    {
+                        log.error("Failed to create regular expression pattern for {}. {}", proxyPathMapper.getLocalBasePath(), e);
+                    }
+                }
             }
         }
-        
-        this.localBasePathGlobPatternMap = Collections.synchronizedMap(new HashMap<HttpReverseProxyPathMapper, Pattern>());
-        this.remoteBaseURLGlobPatternMap = Collections.synchronizedMap(new HashMap<HttpReverseProxyPathMapper, Pattern>());
+    }
+    
+    public void setMaxMatchingPathPartCount(int maxMatchingPathPartCount)
+    {
+        this.maxMatchingPathPartCount = maxMatchingPathPartCount;
+    }
+    
+    public int getMaxMatchingPathPartCount()
+    {
+        return maxMatchingPathPartCount;
     }
     
     public HttpReverseProxyPathMapper findMapper(String pathInfo)
     {
-        int mapperCount = proxyPathMappers.size();
+        String [] pathParts = StringUtils.split(pathInfo, "/", maxMatchingPathPartCount + 1);
+        int pathPartCount = (pathParts != null ? pathParts.length : 0);
         
-        for (int i = 0; i < mapperCount; i++)
+        if (pathPartCount == 0)
         {
-            HttpReverseProxyPathMapper proxyPathMapper = proxyPathMappers.get(i);
+            return null;
+        }
+        
+        for (int i = Math.min(pathPartCount, maxMatchingPathPartCount); i > 0; i--)
+        {
+            String localBasePathKey = "/" + StringUtils.join(pathParts, "/", 0, i);
+            HttpReverseProxyPathMapper proxyPathMapper = staticProxyPathMappersMap.get(localBasePathKey);
             
-            if (StringUtils.startsWith(pathInfo, proxyPathMapper.getLocalBasePath()))
+            if (proxyPathMapper == null)
+            {
+                proxyPathMapper = (HttpReverseProxyPathMapper) dynamicProxyPathMappersMap.get(localBasePathKey);
+            }
+            
+            if (proxyPathMapper != null)
             {
                 return proxyPathMapper;
             }
@@ -122,74 +195,52 @@
                 
                 if (pattern == null)
                 {
-                    try
+                    continue;
+                }
+                
+                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++)
                     {
-                        pattern = Pattern.compile(StringUtils.replaceEach(proxyPathMapper.getLocalBasePath(), GLOB_EXPR_SEARCHES, GLOB_EXPR_REPLACES));
+                        replaces[i] = matcher.group(i + 1);
+                        searches[i] = "$" + (i + 1);
                     }
-                    catch (Exception e)
+                    
+                    //HttpReverseProxyPathMapper cloned = (HttpReverseProxyPathMapper) proxyPathMapper.clone();
+                    String localBasePath = matcher.group(0);
+                    String remoteBaseURL = StringUtils.replaceEach(proxyPathMapper.getRemoteBaseURL(), searches, replaces);
+                    HttpReverseProxyPathMapper derivedMapper = 
+                        new DefaultHttpReverseProxyPathMapperImpl(proxyPathMapper.getName() + ":" + localBasePath,
+                                                                  localBasePath,
+                                                                  remoteBaseURL,
+                                                                  proxyPathMapper.getDefaultRequestHeaders());
+                    
+                    RewriterController rewriterController = rewriterControllerMap.get(proxyPathMapper);
+                    Ruleset rewriterRules = rewriterRulesetMap.get(proxyPathMapper);
+                    
+                    if (rewriterController != null)
                     {
-                        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);
-                        }
+                        rewriterControllerMap.put(derivedMapper, rewriterController);
                     }
                     
-                    if (pattern != null)
+                    if (rewriterRules != null)
                     {
-                        localBasePathGlobPatternMap.put(proxyPathMapper, pattern);
+                        rewriterRulesetMap.put(derivedMapper, rewriterRules);
                     }
-                }
-                
-                if (pattern != null)
-                {
-                    Matcher matcher = pattern.matcher(pathInfo);
                     
-                    if (matcher.lookingAt())
+                    synchronized (dynamicProxyPathMappersMap)
                     {
-                        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);
-                        HttpReverseProxyPathMapper derivedMapper = 
-                            new DefaultHttpReverseProxyPathMapperImpl(proxyPathMapper.getName() + ":" + localBasePath,
-                                                                      localBasePath,
-                                                                      StringUtils.replaceEach(proxyPathMapper.getRemoteBaseURL(), searches, replaces));
-                        
-                        RewriterController rewriterController = rewriterControllerMap.get(proxyPathMapper);
-                        Ruleset rewriterRules = rewriterRulesetMap.get(proxyPathMapper);
-                        
-                        if (rewriterController != null)
-                        {
-                            rewriterControllerMap.put(derivedMapper, rewriterController);
-                        }
-                        
-                        if (rewriterRules != null)
-                        {
-                            rewriterRulesetMap.put(derivedMapper, rewriterRules);
-                        }
-                        
-                        synchronized (proxyPathMappers)
-                        {
-                            if (!proxyPathMappers.contains(derivedMapper))
-                            {
-                                proxyPathMappers.add(derivedMapper);
-                            }
-                        }
-                        
-                        return derivedMapper;
+                        dynamicProxyPathMappersMap.put(StringUtils.removeEnd(localBasePath, "/"), derivedMapper);
+                        dynamicProxyPathMappersMap.put(StringUtils.removeEnd(remoteBaseURL, "/"), derivedMapper);
                     }
+                    
+                    return derivedMapper;
                 }
             }
         }
@@ -199,18 +250,27 @@
     
     public HttpReverseProxyPathMapper findMapperByRemoteURL(String remoteURL)
     {
-        if (remoteURL == null)
+        String [] pathParts = StringUtils.split(remoteURL, "/", maxMatchingPathPartCount + 2);
+        int pathPartCount = (pathParts != null ? pathParts.length : 0);
+        
+        if (pathPartCount < 2)
         {
             return null;
         }
-        
-        int mapperCount = proxyPathMappers.size();
-        
-        for (int i = 0; i < mapperCount; i++)
+
+        String scheme = pathParts[0];
+
+        for (int i = Math.min(pathPartCount, maxMatchingPathPartCount + 1); i > 1; i--)
         {
-            HttpReverseProxyPathMapper proxyPathMapper = proxyPathMappers.get(i);
+            String remoteBaseURLKey = scheme + "//" + StringUtils.join(pathParts, "/", 1, i);
+            HttpReverseProxyPathMapper proxyPathMapper = (HttpReverseProxyPathMapper) staticProxyPathMappersMap.get(remoteBaseURLKey);
             
-            if (StringUtils.startsWith(remoteURL, proxyPathMapper.getRemoteBaseURL()))
+            if (proxyPathMapper == null)
+            {
+                proxyPathMapper = (HttpReverseProxyPathMapper) dynamicProxyPathMappersMap.get(remoteBaseURLKey);
+            }
+            
+            if (proxyPathMapper != null)
             {
                 return proxyPathMapper;
             }
@@ -224,83 +284,58 @@
                 
                 if (pattern == null)
                 {
-                    try
+                    continue;
+                }
+                
+                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);
+                    }
+                    
+                    String remoteBaseURL = matcher.group(0);
+                    String localBasePath = proxyPathMapper.getLocalBasePath();
+                    
+                    for (int i = 1; StringUtils.contains(localBasePath, '*'); i++)
                     {
-                        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);
+                        localBasePath = StringUtils.replaceOnce(localBasePath, "*", "$" + i);
                     }
-                    catch (Exception e)
+                    
+                    localBasePath = StringUtils.replaceEach(localBasePath, searches, replaces);
+                    HttpReverseProxyPathMapper derivedMapper = 
+                        new DefaultHttpReverseProxyPathMapperImpl(proxyPathMapper.getName() + ":" + localBasePath,
+                                                                  localBasePath,
+                                                                  remoteBaseURL,
+                                                                  proxyPathMapper.getDefaultRequestHeaders());
+                    
+                    RewriterController rewriterController = rewriterControllerMap.get(proxyPathMapper);
+                    Ruleset rewriterRules = rewriterRulesetMap.get(proxyPathMapper);
+                    
+                    if (rewriterController != null)
                     {
-                        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);
-                        }
+                        rewriterControllerMap.put(derivedMapper, rewriterController);
                     }
                     
-                    if (pattern != null)
+                    if (rewriterRules != null)
                     {
-                        remoteBaseURLGlobPatternMap.put(proxyPathMapper, pattern);
+                        rewriterRulesetMap.put(derivedMapper, rewriterRules);
                     }
-                }
-                
-                if (pattern != null)
-                {
-                    Matcher matcher = pattern.matcher(remoteURL);
                     
-                    if (matcher.lookingAt())
+                    synchronized (dynamicProxyPathMappersMap)
                     {
-                        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);
-                        }
-                        
-                        String remoteBaseURL = matcher.group(0);
-                        String localBasePath = proxyPathMapper.getLocalBasePath();
-                        
-                        for (int i = 1; StringUtils.contains(localBasePath, '*'); i++)
-                        {
-                            localBasePath = StringUtils.replaceOnce(localBasePath, "*", "$" + i);
-                        }
-                        
-                        localBasePath = StringUtils.replaceEach(localBasePath, searches, replaces);
-                        HttpReverseProxyPathMapper derivedMapper = 
-                            new DefaultHttpReverseProxyPathMapperImpl(proxyPathMapper.getName() + ":" + localBasePath,
-                                                                      localBasePath,
-                                                                      remoteBaseURL);
-                        
-                        RewriterController rewriterController = rewriterControllerMap.get(proxyPathMapper);
-                        Ruleset rewriterRules = rewriterRulesetMap.get(proxyPathMapper);
-                        
-                        if (rewriterController != null)
-                        {
-                            rewriterControllerMap.put(derivedMapper, rewriterController);
-                        }
-                        
-                        if (rewriterRules != null)
-                        {
-                            rewriterRulesetMap.put(derivedMapper, rewriterRules);
-                        }
-                        
-                        synchronized (proxyPathMappers)
-                        {
-                            if (!proxyPathMappers.contains(derivedMapper))
-                            {
-                                proxyPathMappers.add(derivedMapper);
-                            }
-                        }
-                        
-                        return derivedMapper;
+                        dynamicProxyPathMappersMap.put(StringUtils.removeEnd(localBasePath, "/"), derivedMapper);
+                        dynamicProxyPathMappersMap.put(StringUtils.removeEnd(remoteBaseURL, "/"), derivedMapper);
                     }
+                    
+                    return derivedMapper;
                 }
             }
         }
@@ -318,9 +353,4 @@
         return rewriterRulesetMap.get(proxyPathMapper);
     }
     
-    public List<HttpReverseProxyPathMapper> getProxyPathMappers()
-    {
-        return Collections.unmodifiableList(proxyPathMappers);
-    }
-    
 }

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=821934&r1=821933&r2=821934&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 Mon Oct  5 17:50:07 2009
@@ -59,6 +59,8 @@
 import org.apache.http.conn.routing.RouteInfo;
 import org.apache.http.params.BasicHttpParams;
 import org.apache.http.params.HttpParams;
+import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyException;
+import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyNotFoundException;
 import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapper;
 import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapperProvider;
 import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyService;
@@ -166,12 +168,26 @@
             if (StringUtils.isBlank(localBasePath) || StringUtils.isBlank(remoteBaseURL))
             {
                 log.error("Wrong configuration for pass mapping of " + pathName + ". local={}, remove={}.", localBasePath, remoteBaseURL);
+                continue;
             }
             
             try
             {
+                Map<String, String> defaultRequestHeaders = null;
+                Configuration defaultRequestHeadersConf = pathPassConf.subset("request.header");
+                if (!defaultRequestHeadersConf.isEmpty())
+                {
+                    defaultRequestHeaders = new HashMap<String, String>();
+                    
+                    for (Iterator it = defaultRequestHeadersConf.getKeys(); it.hasNext(); )
+                    {
+                        String key = (String) it.next();
+                        defaultRequestHeaders.put(key, defaultRequestHeadersConf.getString(key));
+                    }
+                }
+                
                 HttpReverseProxyPathMapper proxyPathMapper = 
-                    new DefaultHttpReverseProxyPathMapperImpl(pathName, localBasePath, remoteBaseURL);
+                    new DefaultHttpReverseProxyPathMapperImpl(pathName, localBasePath, remoteBaseURL, defaultRequestHeaders);
                 proxyPathMappers.add(proxyPathMapper);
                 
                 Configuration rewritersConf = pathPassConf.subset("rewriter");
@@ -207,8 +223,30 @@
             }
         }
         
-        HttpReverseProxyPathMapperProvider proxyPathMapperProvider = 
-            new DefaultHttpReverseProxyPathMapperProviderImpl(proxyPathMappers, rewriterControllerMap, rewriterRulesetMap);
+        int dynamicProxyPathMapperCacheCount = 1000;
+        try 
+        {
+            dynamicProxyPathMapperCacheCount = passConf.getInt("dynamicProxyPathMapperCacheCount", dynamicProxyPathMapperCacheCount);
+        }
+        catch (Exception ignore)
+        {
+        }
+        
+        int maxMatchingPathPartCount = 2;
+        try 
+        {
+            maxMatchingPathPartCount = passConf.getInt("maxMatchingPathPartCount", maxMatchingPathPartCount);
+        }
+        catch (Exception ignore)
+        {
+        }
+        
+        DefaultHttpReverseProxyPathMapperProviderImpl proxyPathMapperProvider = 
+            new DefaultHttpReverseProxyPathMapperProviderImpl(proxyPathMappers, dynamicProxyPathMapperCacheCount, 
+                                                              rewriterControllerMap, rewriterRulesetMap);
+        
+        proxyPathMapperProvider.setMaxMatchingPathPartCount(maxMatchingPathPartCount);
+        
         HttpReverseProxyService tempProxyService = new RewritableHttpReverseProxyServiceImpl(proxyPathMapperProvider);
         
         Configuration serverConf = configuration.subset("proxy.server");
@@ -319,6 +357,14 @@
             {
                 proxyService.invoke(request, response);
             }
+            catch (HttpReverseProxyNotFoundException e)
+            {
+                response.sendError(404, e.getLocalizedMessage());
+            }
+            catch (HttpReverseProxyException e)
+            {
+                throw new ServletException(e);
+            }
             finally
             {
                 try
@@ -339,6 +385,9 @@
         Class basicRewriterClass = null;
         Class ruleBasedRewriterClass = null;
         Map<String, Class> adaptorMimeTypeClassMap = new HashMap<String, Class>();
+        Map<String, Object> basicRewriterProps = null;
+        Map<String, Object> rulesetRewriterProps = null;
+        Map<String, Map<String, Object>> parserAdaptorMimeTypeMap = null;
         
         try
         {
@@ -349,22 +398,43 @@
                 ruleMappingsFilePath = getServletContext().getRealPath(ruleMappings);
             }
             
-            String basicRewriter = rewriterConf.getString("basic");
+            Configuration basicRewriterConf = rewriterConf.subset("basic");
+            String basicRewriter = basicRewriterConf.getString("");
             
             if (!StringUtils.isBlank(basicRewriter))
             {
                 basicRewriterClass = Thread.currentThread().getContextClassLoader().loadClass(basicRewriter);
+                Configuration propsConf = basicRewriterConf.subset("property");
+                if (!propsConf.isEmpty())
+                {
+                    basicRewriterProps = new HashMap<String, Object>();
+                    for (Iterator it = propsConf.getKeys(); it.hasNext(); )
+                    {
+                        String propName = (String) it.next();
+                        basicRewriterProps.put(propName, propsConf.getString(propName));
+                    }
+                }
             }
             
-            String ruleBasedRewriter = rewriterConf.getString("rulebased");
+            Configuration ruleBasedRewriterConf = rewriterConf.subset("rulebased");
+            String ruleBasedRewriter = ruleBasedRewriterConf.getString("");
             
             if (!StringUtils.isBlank(ruleBasedRewriter))
             {
                 ruleBasedRewriterClass = Thread.currentThread().getContextClassLoader().loadClass(ruleBasedRewriter);
+                Configuration propsConf = ruleBasedRewriterConf.subset("property");
+                if (!propsConf.isEmpty())
+                {
+                    rulesetRewriterProps = new HashMap<String, Object>();
+                    for (Iterator it = propsConf.getKeys(); it.hasNext(); )
+                    {
+                        String propName = (String) it.next();
+                        rulesetRewriterProps.put(propName, propsConf.getString(propName));
+                    }
+                }
             }
             
             Configuration parserAdaptorsConf = rewriterConf.subset("parserAdaptor");
-            
             String [] parserAdaptorNames = parserAdaptorsConf.getStringArray("");
             
             if (!ArrayUtils.isEmpty(parserAdaptorNames))
@@ -378,14 +448,35 @@
                     if (!StringUtils.isBlank(parserAdaptor))
                     {
                         Class parserAdaptorClass = Thread.currentThread().getContextClassLoader().loadClass(parserAdaptor);
+                        Configuration propsConf = parserAdaptorConf.subset("property");
+                        if (!propsConf.isEmpty())
+                        {
+                            Map<String, Object> parserAdaptorProps = new HashMap<String, Object>();
+                            for (Iterator it = propsConf.getKeys(); it.hasNext(); )
+                            {
+                                String propName = (String) it.next();
+                                parserAdaptorProps.put(propName, propsConf.getString(propName));
+                            }
+                            if (parserAdaptorMimeTypeMap == null)
+                            {
+                                parserAdaptorMimeTypeMap = new HashMap<String, Map<String, Object>>();
+                            }
+                            parserAdaptorMimeTypeMap.put(mimeType, parserAdaptorProps);
+                        }
                         adaptorMimeTypeClassMap.put(mimeType, parserAdaptorClass);
                     }
                 }
             }
             
-            return new MappingRewriterController(ruleMappingsFilePath, 
-                                                 basicRewriterClass, ruleBasedRewriterClass, 
-                                                 adaptorMimeTypeClassMap);
+            MappingRewriterController rewriterController = new MappingRewriterController(ruleMappingsFilePath, 
+                                                                                         basicRewriterClass, ruleBasedRewriterClass, 
+                                                                                         adaptorMimeTypeClassMap);
+            
+            rewriterController.setBasicRewriterProps(basicRewriterProps);
+            rewriterController.setRulesetRewriterProps(basicRewriterProps);
+            rewriterController.setParserAdaptorMimeTypePropsMap(parserAdaptorMimeTypeMap);
+            
+            return rewriterController;
         }
         catch (Exception e)
         {

Copied: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultReverseProxyLinkRewritingParserAaptor.java (from r821705, 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/DefaultReverseProxyLinkRewritingParserAaptor.java?p2=portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultReverseProxyLinkRewritingParserAaptor.java&p1=portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/PassMappingLinkRewritingParserAaptor.java&r1=821705&r2=821934&rev=821934&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/DefaultReverseProxyLinkRewritingParserAaptor.java Mon Oct  5 17:50:07 2009
@@ -16,32 +16,16 @@
  */
 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.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
-import java.util.List;
+import java.util.Map;
 import java.util.Set;
 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;
 import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapper;
-import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapperProvider;
-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;
 import org.apache.portals.applications.webcontent.util.CharArraySegment;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * A simple reverse proxy link rewriting parser adaptor implementation.
@@ -51,39 +35,39 @@
  * 
  * @version $Id$
  */
-public class PassMappingLinkRewritingParserAaptor implements ParserAdaptor, ReverseProxyRewritingContextAware
+public class DefaultReverseProxyLinkRewritingParserAaptor extends AbstractReverseProxyTextLinesParserAdaptor
 {
     
     protected static final Pattern LINK_ABS_PATH_PATTERN = 
         Pattern.compile("(\\s|^)(href|src|action)\\s*=\\s*(['\"])((\\/)[^'\"]*)['\"]", Pattern.CASE_INSENSITIVE);
     
     protected static final Pattern LINK_HTTP_ABS_URL_PATTERN = 
-        Pattern.compile("(\\s|^)(href|src|action)\\s*=\\s*['\"](https?:\\/\\/[^\\/'\"]+)[^'\"]*['\"]", Pattern.CASE_INSENSITIVE);
+        Pattern.compile("(\\s|^)(href|src|action)\\s*=\\s*['\"](https?:\\/\\/[^'\"]+)['\"]", Pattern.CASE_INSENSITIVE);
     
     protected static final Pattern HTTP_DOMAIN_ADDRESS_ONLY_PATTERN = 
         Pattern.compile("^https?:\\/\\/[^\\/]+$", Pattern.CASE_INSENSITIVE);
     
-    private static Logger log = LoggerFactory.getLogger(PassMappingLinkRewritingParserAaptor.class);
-    
     protected boolean lookUpAllMappings;
     
-    protected ReverseProxyRewritingContext reverseProxyRewritingContext;
+    protected String localPathMatchingReplaces;
     
     protected String [] linkRemoteBaseURLSearches = { "/", "." };
     protected String [] linkRemoteBaseURLReplaces = { "\\/", "\\." };
     
-    private List<HttpReverseProxyPathMapper> proxyPathMappers;
-    private List<KeyValue> remoteURLPatternReplacesPairs;
-    private KeyValue myURLPatternReplacesPair;
+    private Pattern defaultRemoteURLPattern;
+    private String defaultRemoteURLReplaces;
     
     private Set<String> blacklist;
     
-    public PassMappingLinkRewritingParserAaptor()
+    private Map<HttpReverseProxyPathMapper, Pattern> remoteURLMatchingPatternMap;
+    private Map<HttpReverseProxyPathMapper, String> localPathMatchingReplacesMap;
+    
+    public DefaultReverseProxyLinkRewritingParserAaptor()
     {
         this(true, null);
     }
     
-    public PassMappingLinkRewritingParserAaptor(boolean lookUpAllMappings, Set<String> blacklist)
+    public DefaultReverseProxyLinkRewritingParserAaptor(boolean lookUpAllMappings, Set<String> blacklist)
     {
         setLookUpAllMappings(lookUpAllMappings);
         setBlacklist(blacklist);
@@ -99,151 +83,110 @@
         this.blacklist = blacklist;
     }
     
-    public void setReverseProxyRewritingContext(ReverseProxyRewritingContext reverseProxyRewritingContext)
+    @Override
+    protected String rewriteLine(String line) throws Exception
     {
-        this.reverseProxyRewritingContext = reverseProxyRewritingContext;
-    }
-    
-    public void rewrite(Rewriter rewriter, Reader reader, Writer writer) throws RewriterException
-    {
-        HttpReverseProxyPathMapperProvider proxyPathMapperProvider = reverseProxyRewritingContext.getHttpReverseProxyPathMapperProvider();
-        String myLocalPathMatchingReplaces = createLocalPathMatchingReplaces(reverseProxyRewritingContext.getHttpReverseProxyPathMapper());
-        
-        if (lookUpAllMappings && blacklist == null)
+        if (defaultRemoteURLPattern == null)
         {
-            blacklist = new HashSet<String>();
+            defaultRemoteURLPattern = createRemoteURLMatchingPattern(getHttpReverseProxyPathMapper());
+            defaultRemoteURLReplaces = createLocalPathMatchingReplaces(getHttpReverseProxyPathMapper());
         }
         
-        PrintWriter out = new PrintWriter(new BufferedWriter(writer));
+        // first, replace slash leading relative paths by slash leading reverse proxying relative paths.
+        Matcher linkBasePathMatcher = LINK_ABS_PATH_PATTERN.matcher(line);
+        line = linkBasePathMatcher.replaceAll("$1$2=$3" + defaultRemoteURLReplaces + "$4$3");
         
-        for (LineIterator lineIt = IOUtils.lineIterator(reader); lineIt.hasNext(); )
+        // if there's any https? absolute url link, try to find the proxy path mapper again...
+        if (lookUpAllMappings)
         {
-            String line = lineIt.nextLine();
-            String tempLine = line;
+            CharSequence segment = new CharArraySegment(line);
             
-            if (!StringUtils.isBlank(line))
+            for (Matcher absURLMatcher = LINK_HTTP_ABS_URL_PATTERN.matcher(segment); absURLMatcher.find(); )
             {
-                try
+                HttpReverseProxyPathMapper proxyMapper = null;
+                String absURL = absURLMatcher.group(3);
+                int maxMatchingPathPartCount = getMaxMatchingPathPartCount();
+                String [] pathParts = StringUtils.split(absURL, "/", maxMatchingPathPartCount + 2);
+                int pathPartCount = (pathParts != null ? pathParts.length : 0);
+                
+                if (pathPartCount < 2)
                 {
-                    // first, replace slash leading relative paths by slash leading reverse proxying relative paths. 
-                    Matcher linkBasePathMatcher = LINK_ABS_PATH_PATTERN.matcher(tempLine);
-                    tempLine = linkBasePathMatcher.replaceAll("$1$2=$3" + myLocalPathMatchingReplaces + "$4$3");
+                    continue;
+                }
+                
+                String scheme = pathParts[0];
+                
+                for (int i = Math.min(pathPartCount, maxMatchingPathPartCount + 1); i > 1; i--)
+                {
+                    String remoteBaseURLKey = scheme + "//" + StringUtils.join(pathParts, "/", 1, i);
+                    
+                    if (blacklist != null && blacklist.contains(remoteBaseURLKey))
+                    {
+                        continue;
+                    }
+
+                    proxyMapper = getHttpReverseProxyPathMapperProvider().findMapperByRemoteURL(remoteBaseURLKey + "/");
                     
-                    // second, replace absolute urls by slash leading relative paths.
-                    if (lookUpAllMappings)
+                    if (proxyMapper == null)
                     {
-                        for (KeyValue pair : getRemoteURLPatternReplacesPairs())
+                        if (blacklist == null)
                         {
-                            Matcher matcher = ((Pattern) pair.getKey()).matcher(tempLine);
-                            tempLine = replaceRemoteLinkValues(matcher, "$1$2=$3" + ((String) pair.getValue()) + "$6$3", tempLine);
+                            blacklist = new HashSet<String>();
                         }
                         
-                        // if there's any https? absolute url link, try to find the proxy path mapper again...
+                        blacklist.add(remoteBaseURLKey);
+                    }
+                    else
+                    {
+                        if (remoteURLMatchingPatternMap == null)
+                        {
+                            remoteURLMatchingPatternMap = new HashMap<HttpReverseProxyPathMapper, Pattern>();
+                            localPathMatchingReplacesMap = new HashMap<HttpReverseProxyPathMapper, String>();
+                        }
                         
-                        CharSequence segment = new CharArraySegment(tempLine);
+                        Pattern pattern = remoteURLMatchingPatternMap.get(proxyMapper);
+                        if (pattern == null)
+                        {
+                            pattern = createRemoteURLMatchingPattern(proxyMapper);
+                            remoteURLMatchingPatternMap.put(proxyMapper, pattern);
+                        }
                         
-                        for (Matcher absURLMatcher = LINK_HTTP_ABS_URL_PATTERN.matcher(segment); absURLMatcher.find(); )
+                        String localPathMatchingReplaces = localPathMatchingReplacesMap.get(proxyMapper);
+                        if (localPathMatchingReplaces == null)
                         {
-                            String domainURL = absURLMatcher.group(3);
-                            
-                            if (blacklist.contains(domainURL))
-                            {
-                                continue;
-                            }
-                            
-                            HttpReverseProxyPathMapper proxyMapper = proxyPathMapperProvider.findMapperByRemoteURL(domainURL + "/");
-                            
-                            if (proxyMapper == null)
-                            {
-                                blacklist.add(domainURL);
-                            }
-                            else
-                            {
-                                if (!proxyPathMappers.contains(proxyMapper))
-                                {
-                                    KeyValue pair = new DefaultKeyValue(createRemoteURLMatchingPattern(proxyMapper),
-                                                                        createLocalPathMatchingReplaces(proxyMapper));
-                                    
-                                    Matcher matcher = ((Pattern) pair.getKey()).matcher(tempLine);
-                                    tempLine = replaceRemoteLinkValues(matcher, "$1$2=$3" + ((String) pair.getValue()) + "$6$3", tempLine);
-                                    
-                                    remoteURLPatternReplacesPairs.add(pair);
-                                    proxyPathMappers.add(proxyMapper);
-                                }
-                            }
-                            
-                            segment = segment.subSequence(absURLMatcher.end(), segment.length());
-                            absURLMatcher.reset(segment);
+                            localPathMatchingReplaces = createLocalPathMatchingReplaces(proxyMapper);
+                            localPathMatchingReplacesMap.put(proxyMapper, localPathMatchingReplaces);
                         }
+                        
+                        Matcher matcher = pattern.matcher(line);
+                        line = replaceRemoteLinkValues(matcher, "$1$2=$3" + localPathMatchingReplaces + "$6$3", line);
+                        
+                        break;
                     }
-                    else
-                    {
-                        KeyValue pair = getMyURLPatternReplacesPair();
-                        Matcher matcher = ((Pattern) pair.getKey()).matcher(tempLine);
-                        tempLine = matcher.replaceAll("$1$2=$3" + ((String) pair.getValue()) + "$6$3");
-                    }
-                    
-                    line = tempLine;
-                }
-                catch (Exception e)
-                {
-                    log.warn("Error during {}: {}", "replacement", e);
                 }
+                
+                segment = segment.subSequence(absURLMatcher.end(), segment.length());
+                absURLMatcher.reset(segment);
             }
-            
-            out.println(line);
+        }
+        else
+        {
+            Matcher matcher = defaultRemoteURLPattern.matcher(line);
+            line = matcher.replaceAll("$1$2=$3" + defaultRemoteURLReplaces + "$6$3");
         }
         
-        out.flush();
+        return line;
     }
     
     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;
+        String remoteBaseURLPattern = StringUtils.replaceEach(StringUtils.removeEnd(proxyMapper.getRemoteBaseURL(), "/"), linkRemoteBaseURLSearches, linkRemoteBaseURLReplaces);
+        return Pattern.compile("(\\s|^)(href|src|action)\\s*=\\s*(['\"])((" + remoteBaseURLPattern + ")([^'\"]*))['\"]", Pattern.CASE_INSENSITIVE);
     }
     
     protected String createLocalPathMatchingReplaces(HttpReverseProxyPathMapper proxyMapper)
     {
-        return reverseProxyRewritingContext.getRewritingContextPath() + StringUtils.removeEnd(proxyMapper.getLocalBasePath(), "/");
-    }
-    
-    protected List<KeyValue> getRemoteURLPatternReplacesPairs()
-    {
-        if (remoteURLPatternReplacesPairs == null)
-        {
-            HttpReverseProxyPathMapperProvider mapperProvider = reverseProxyRewritingContext.getHttpReverseProxyPathMapperProvider();
-            proxyPathMappers = new ArrayList<HttpReverseProxyPathMapper>(mapperProvider.getProxyPathMappers());
-            int proxyMappersCount = proxyPathMappers.size();
-            remoteURLPatternReplacesPairs = new ArrayList<KeyValue>();
-            
-            for (HttpReverseProxyPathMapper proxyMapper : proxyPathMappers)
-            {
-                remoteURLPatternReplacesPairs.add(new DefaultKeyValue(createRemoteURLMatchingPattern(proxyMapper),
-                                                                      createLocalPathMatchingReplaces(proxyMapper)));
-            }
-        }
-        
-        return remoteURLPatternReplacesPairs;
-    }
-    
-    protected KeyValue getMyURLPatternReplacesPair()
-    {
-        if (myURLPatternReplacesPair == null)
-        {
-            HttpReverseProxyPathMapper proxyMapper = reverseProxyRewritingContext.getHttpReverseProxyPathMapper();
-            myURLPatternReplacesPair = new DefaultKeyValue(createRemoteURLMatchingPattern(proxyMapper), createLocalPathMatchingReplaces(proxyMapper));
-        }
-        
-        return myURLPatternReplacesPair;
+        return getRewritingContextPath() + StringUtils.removeEnd(proxyMapper.getLocalBasePath(), "/");
     }
     
     protected String replaceRemoteLinkValues(Matcher matcher, String replacement, String text)
@@ -282,9 +225,4 @@
         return text;
     }
     
-    public void parse(Rewriter rewriter, Reader reader) throws RewriterException
-    {
-        throw new UnsupportedOperationException();
-    }
-    
 }

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

Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultReverseProxyLinkRewritingParserAaptor.java
------------------------------------------------------------------------------
    svn:keywords = Id

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