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 2014/07/13 00:43:54 UTC

svn commit: r1610080 [1/2] - in /portals/applications/webcontent/trunk: ./ reverse-proxy/ reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/ reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/cha...

Author: woonsan
Date: Sat Jul 12 22:43:53 2014
New Revision: 1610080

URL: http://svn.apache.org/r1610080
Log:
APA-63: splits reverse proxy service components into chains.

Added:
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/ProxyMapping.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/RequestContext.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/ReverseProxyException.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/ReverseProxyNotFoundException.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/ReverseProxyService.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/URICleaner.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/AbstractProxyCommand.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/CleanupCommand.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ContinueProcessingChain.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ExecuteHttpClientCommand.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/HandleNotModifiedCommand.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/HandleRedirectionCommand.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/InitHttpClientCommand.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/InitHttpRequestCommand.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/InitializationCommand.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ProxyContext.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ResolveContentRewriterCommand.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ResolveLocalPathCommand.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ResolveProxyMappingCommand.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ResolveRemoteURICommand.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/SerializeHttpEntityContentCommand.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/SerializeHttpEntityHeadersCommand.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/DefaultReverseProxyService.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/HttpEntitySource.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/HttpServletResponseSink.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/LocationProxyMapping.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/ProxyHttpClient.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/ServletRequestContext.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/SimpleProxyMapping.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/servlet/
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/servlet/DefaultReverseProxyServlet.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/servlet/SimpleReverseProxyServlet.java
    portals/applications/webcontent/trunk/reverse-proxy/src/test/resources/web.xml
Modified:
    portals/applications/webcontent/trunk/pom.xml
    portals/applications/webcontent/trunk/reverse-proxy/pom.xml
    portals/applications/webcontent/trunk/reverse-proxy/src/test/resources/log4j.xml
    portals/applications/webcontent/trunk/war/pom.xml

Modified: portals/applications/webcontent/trunk/pom.xml
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/pom.xml?rev=1610080&r1=1610079&r2=1610080&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/pom.xml (original)
+++ portals/applications/webcontent/trunk/pom.xml Sat Jul 12 22:43:53 2014
@@ -57,6 +57,9 @@
     <oro.version>2.0.8</oro.version>
     <velocity.version>1.6.3</velocity.version>
     <velocity-tools.version>1.3</velocity-tools.version>
+
+    <maven-jetty-plugin.version>6.1.10</maven-jetty-plugin.version>
+
   </properties>
 
   <dependencyManagement>

Modified: portals/applications/webcontent/trunk/reverse-proxy/pom.xml
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/pom.xml?rev=1610080&r1=1610079&r2=1610080&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/pom.xml (original)
+++ portals/applications/webcontent/trunk/reverse-proxy/pom.xml Sat Jul 12 22:43:53 2014
@@ -125,4 +125,77 @@
 
   </dependencies>
 
+  <profiles>
+
+    <!--
+      You can run `mvn -Prun clean veryfy' for easier testing at http://localhost:8080/rproxy.
+      Also, you can run the following for remote debugging:
+
+      $ export MAVEN_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n"
+      $ mvn -Prun clean verify
+    -->
+
+    <profile>
+
+      <id>run</id>
+
+      <dependencies>
+
+        <dependency>
+          <groupId>org.slf4j</groupId>
+          <artifactId>slf4j-log4j12</artifactId>
+          <scope>runtime</scope>
+        </dependency>
+
+        <dependency>
+          <groupId>org.slf4j</groupId>
+          <artifactId>jcl-over-slf4j</artifactId>
+          <scope>runtime</scope>
+        </dependency>
+
+        <dependency>
+          <groupId>log4j</groupId>
+          <artifactId>log4j</artifactId>
+          <version>1.2.17</version>
+          <type>jar</type>
+        </dependency>
+
+      </dependencies>
+
+      <build>
+        <defaultGoal>initialize</defaultGoal>
+        <plugins>
+          <plugin>
+            <groupId>org.mortbay.jetty</groupId>
+            <artifactId>maven-jetty-plugin</artifactId>
+            <version>${maven-jetty-plugin.version}</version>
+            <executions>
+              <execution>
+                <id>cargo-run</id>
+                <phase>validate</phase>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+              </execution>
+            </executions>
+            <configuration>
+              <contextPath>/rproxy</contextPath>
+              <webAppSourceDirectory>${basedir}/src/test/resources</webAppSourceDirectory>
+              <webXml>${basedir}/target/test-classes/web.xml</webXml>
+              <classesDirectory>${basedir}/target/classes, ${basedir}/target/test-classes</classesDirectory>
+              <systemProperties>
+                <systemProperty>
+                  <name>log4j.configuration</name>
+                  <value>file://${basedir}/src/test/resources/log4j.xml</value>
+                </systemProperty>
+              </systemProperties>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+
+    </profile>
+
+  </profiles>
+
 </project>

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/ProxyMapping.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/ProxyMapping.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/ProxyMapping.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/ProxyMapping.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,31 @@
+/*
+ * 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.webcontent2.proxy2;
+
+
+public interface ProxyMapping
+{
+
+    public boolean matchesLocal(String localPath);
+
+    public String resolveRemoteFromLocal(String localPath);
+
+    public boolean matchesRemote(String remoteURI);
+
+    public String resolveLocalFromRemote(String remoteURI);
+
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/RequestContext.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/RequestContext.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/RequestContext.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/RequestContext.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,61 @@
+/*
+ * 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.webcontent2.proxy2;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+
+import org.apache.portals.applications.webcontent2.rewriter2.Sink;
+
+
+public interface RequestContext
+{
+
+    public String getServerName();
+
+    public int getServerPort();
+
+    public String getMethod();
+
+    public String getRequestBasePath();
+
+    public String getPathInfo();
+
+    public Object getAttribute(final String name);
+
+    public String getQueryString();
+
+    public Enumeration getHeaderNames();
+
+    public Enumeration getHeaders(String name);
+
+    public String getHeader(String name);
+
+    public InputStream getInputStream() throws IOException;
+
+    public void setStatus(int sc);
+
+    public void sendRedirect(String location) throws IOException;
+
+    public void setHeader(String name, String value);
+
+    public void setIntHeader(String name, int value);
+
+    public Sink getSink();
+
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/ReverseProxyException.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/ReverseProxyException.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/ReverseProxyException.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/ReverseProxyException.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,74 @@
+/*
+ * 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.webcontent2.proxy2;
+
+/**
+ * The <CODE>ReverseProxyException</CODE> class defines a general exception
+ * that an http reverse proxy component can throw when it is unable to perform its operation
+ * successfully.
+ */
+public class ReverseProxyException extends Exception 
+{
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Constructs a new HttpReverseProxyException exception.
+     */
+    public ReverseProxyException() {
+        super();
+    }
+
+    /**
+     * Constructs a new HttpReverseProxyException exception with the given message.
+     *
+     * @param   message
+     *          the exception message
+     */
+    public ReverseProxyException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new HttpReverseProxyException exception with the nested exception.
+     *
+     * @param   nested
+     *          the nested exception
+     */
+    public ReverseProxyException(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 ReverseProxyException(String msg, Throwable nested) {
+        super(msg, nested);
+    }
+    
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/ReverseProxyNotFoundException.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/ReverseProxyNotFoundException.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/ReverseProxyNotFoundException.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/ReverseProxyNotFoundException.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,73 @@
+/*
+ * 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.webcontent2.proxy2;
+
+/**
+ * The <CODE>ReverseProxyNotFoundException</CODE> class defines a not-found-exception
+ * that an http reverse proxy component can throw when it is unable to find web resources
+ * successfully.
+ */
+public class ReverseProxyNotFoundException extends ReverseProxyException {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Constructs a new HttpReverseProxyNotFoundException exception.
+     */
+    public ReverseProxyNotFoundException() {
+        super();
+    }
+
+    /**
+     * Constructs a new HttpReverseProxyNotFoundException exception with the given message.
+     *
+     * @param   message
+     *          the exception message
+     */
+    public ReverseProxyNotFoundException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new HttpReverseProxyNotFoundException exception with the nested exception.
+     *
+     * @param   nested
+     *          the nested exception
+     */
+    public ReverseProxyNotFoundException(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 ReverseProxyNotFoundException(String msg, Throwable nested) {
+        super(msg, nested);
+    }
+    
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/ReverseProxyService.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/ReverseProxyService.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/ReverseProxyService.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/ReverseProxyService.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,36 @@
+/*
+ * 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.webcontent2.proxy2;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Reverse Proxy Service interface
+ */
+public interface ReverseProxyService
+{
+
+    public void initialize();
+
+    public void invoke(HttpServletRequest request, HttpServletResponse response) throws ReverseProxyException, IOException;
+
+    public void destroy();
+
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/URICleaner.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/URICleaner.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/URICleaner.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/URICleaner.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,35 @@
+/*
+ * 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.webcontent2.proxy2;
+
+/**
+ * URICleaner
+ * <P>
+ * Components implementing this interface can be used to clean the remote URI
+ * before invoking HTTP Methods by HttpReverseProxyService. 
+ * </P>
+ */
+public interface URICleaner
+{
+    /**
+     * Inspects the specified uri and returns a cleaned uri.
+     * For example, this should replace disallowed characters such as space by a valid one.
+     * @param uri
+     * @return
+     */
+    public String clean(String uri);
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/AbstractProxyCommand.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/AbstractProxyCommand.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/AbstractProxyCommand.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/AbstractProxyCommand.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,66 @@
+/*
+ * 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.webcontent2.proxy2.chain;
+
+import org.apache.commons.chain.Command;
+import org.apache.commons.chain.Context;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractProxyCommand implements Command
+{
+
+    private static Logger log = LoggerFactory.getLogger(AbstractProxyCommand.class);
+
+    private Boolean executionResult;
+
+    public final boolean execute(Context context)
+    {
+        boolean savedResult = false;
+
+        try
+        {
+            savedResult = executeInternal((ProxyContext) context);
+        }
+        catch (Exception e)
+        {
+            log.error("Failed to execute command processing " + ((ProxyContext) context).getLocalPath(), e);
+        }
+
+        if (executionResult != null)
+        {
+            return executionResult.booleanValue();
+        }
+        else
+        {
+            return savedResult;
+        }
+    }
+
+    protected abstract boolean executeInternal(final ProxyContext context) throws Exception;
+
+    public boolean isExecutionResult()
+    {
+        return executionResult;
+    }
+
+    public void setExecutionResult(boolean executionResult)
+    {
+        this.executionResult = executionResult;
+    }
+
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/CleanupCommand.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/CleanupCommand.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/CleanupCommand.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/CleanupCommand.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,29 @@
+/*
+ * 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.webcontent2.proxy2.chain;
+
+
+
+public class CleanupCommand extends AbstractProxyCommand
+{
+
+    @Override
+    protected boolean executeInternal(final ProxyContext context) throws Exception
+    {
+        return false;
+    }
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ContinueProcessingChain.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ContinueProcessingChain.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ContinueProcessingChain.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ContinueProcessingChain.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,62 @@
+/*
+ * 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.webcontent2.proxy2.chain;
+
+import java.util.Collection;
+
+import org.apache.commons.chain.Command;
+import org.apache.commons.chain.Context;
+import org.apache.commons.chain.impl.ChainBase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ContinueProcessingChain extends ChainBase
+{
+
+    private Logger log = LoggerFactory.getLogger(ContinueProcessingChain.class);
+
+    public ContinueProcessingChain() {
+        super();
+    }
+
+    public ContinueProcessingChain(Command command) {
+        super(command);
+    }
+
+    public ContinueProcessingChain(Command[] commands) {
+        super(commands);
+    }
+
+    public ContinueProcessingChain(Collection commands) {
+        super(commands);
+    }
+
+    @Override
+    public boolean execute(Context context) throws Exception {
+        try 
+        {
+            super.execute(context);
+        }
+        catch (Exception e)
+        {
+            log.error("Failed to execute chain.", e);
+        }
+
+        return false;
+    }
+
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ExecuteHttpClientCommand.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ExecuteHttpClientCommand.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ExecuteHttpClientCommand.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ExecuteHttpClientCommand.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,65 @@
+/*
+ * 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.webcontent2.proxy2.chain;
+
+import java.util.Enumeration;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.protocol.HTTP;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class ExecuteHttpClientCommand extends AbstractProxyCommand
+{
+
+    private static Logger log = LoggerFactory.getLogger(ExecuteHttpClientCommand.class);
+
+    @Override
+    protected boolean executeInternal(final ProxyContext context) throws Exception
+    {
+        HttpRequestBase httpRequest = context.getHttpRequest();
+
+        // pass most headers to remote URI...
+        for (Enumeration enumHeaderNames = context.getRequestContext().getHeaderNames(); enumHeaderNames.hasMoreElements(); )
+        {
+            String headerName = (String) enumHeaderNames.nextElement();
+
+            if (StringUtils.equalsIgnoreCase(headerName, HTTP.CONTENT_LEN))
+                continue;
+
+            if (StringUtils.equalsIgnoreCase(headerName, HTTP.TARGET_HOST))
+                continue;
+
+            for (Enumeration enumHeaderValues = context.getRequestContext().getHeaders(headerName); enumHeaderValues.hasMoreElements(); )
+            {
+                String headerValue = (String) enumHeaderValues.nextElement();
+                httpRequest.addHeader(headerName, headerValue);
+            }
+        }
+
+        HttpClient httpClient = context.getHttpClient();
+        HttpResponse httpResponse = httpClient.execute(httpRequest);
+        context.setHttpResponse(httpResponse);
+
+        return false;
+    }
+
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/HandleNotModifiedCommand.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/HandleNotModifiedCommand.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/HandleNotModifiedCommand.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/HandleNotModifiedCommand.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,54 @@
+/*
+ * 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.webcontent2.proxy2.chain;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.protocol.HTTP;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class HandleNotModifiedCommand extends AbstractProxyCommand
+{
+
+    private static Logger log = LoggerFactory.getLogger(HandleNotModifiedCommand.class);
+
+    @Override
+    protected boolean executeInternal(final ProxyContext context) throws Exception
+    {
+        HttpResponse httpResponse = context.getHttpResponse();
+
+        int statusCode = httpResponse.getStatusLine().getStatusCode();
+
+        if (statusCode == HttpServletResponse.SC_NOT_MODIFIED)
+        {
+            // 304 needs special handling. See:
+            // http://www.ics.uci.edu/pub/ietf/http/rfc1945.html#Code304
+            // We get a 304 whenever passed an 'If-Modified-Since'
+            // header and the data on disk has not changed; server
+            // responds w/ a 304 saying I'm not going to send the
+            // body because the file has not changed.
+            context.getRequestContext().setIntHeader(HTTP.CONTENT_LEN, 0);
+            context.getRequestContext().setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+        }
+
+        return false;
+    }
+
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/HandleRedirectionCommand.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/HandleRedirectionCommand.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/HandleRedirectionCommand.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/HandleRedirectionCommand.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,106 @@
+/*
+ * 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.webcontent2.proxy2.chain;
+
+import java.net.URI;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.http.Header;
+import org.apache.http.HttpResponse;
+import org.apache.portals.applications.webcontent2.proxy.HttpReverseProxyConstants;
+import org.apache.portals.applications.webcontent2.proxy.HttpReverseProxyException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class HandleRedirectionCommand extends AbstractProxyCommand
+{
+
+    private static Logger log = LoggerFactory.getLogger(HandleRedirectionCommand.class);
+
+    @Override
+    protected boolean executeInternal(final ProxyContext context) throws Exception
+    {
+        HttpResponse httpResponse = context.getHttpResponse();
+
+        int statusCode = httpResponse.getStatusLine().getStatusCode();
+
+        // Check if the proxy response is a redirect
+        if (statusCode >= HttpServletResponse.SC_MULTIPLE_CHOICES /* 300 */
+            && statusCode < HttpServletResponse.SC_NOT_MODIFIED /* 304 */)
+        {
+            String location = null;
+            Header locationHeader = httpResponse.getFirstHeader(HttpReverseProxyConstants.HTTP_HEADER_LOCATION);
+
+            if (locationHeader != null)
+            {
+                location = locationHeader.getValue();
+            }
+
+            if (location == null)
+            {
+                throw new HttpReverseProxyException("Recieved status code is " + statusCode + " but no " + HttpReverseProxyConstants.HTTP_HEADER_LOCATION + " header was found in the response");
+            }
+
+            // According to rfc2616, "Location" header value must be an absolute URI.
+            // However, in case it is not, prepend the host URI of the proxy target URL.
+            if (location.startsWith("/")) {
+                URI targetURI = new URI(context.getRemoteURI());
+                String scheme = targetURI.getScheme();
+                int port = targetURI.getPort();
+                StringBuilder uriBuilder = new StringBuilder(40).append(targetURI.getScheme()).append("://").append(targetURI.getHost());
+
+                if (port > 0 && ((port != 80 && "http".equals(scheme)) || (port != 443 && "https".equals(scheme)))) {
+                    uriBuilder.append(':').append(port);
+                }
+
+                uriBuilder.append(location);
+                location = uriBuilder.toString();
+            }
+
+            // Modify the redirect to go to this proxy servlet rather that the proxied host
+            String localPath = context.getResolvedMapping().resolveLocalFromRemote(location);
+
+            // TODO: if the current proxy path mapper cannot map the remote location to local path, then
+            //       try to find out a possible path mapper instead one more time ...
+
+            String redirectLocation = null;
+
+            if (localPath == null)
+            {
+                if (log.isWarnEnabled())
+                {
+                    log.warn("Cannot translate the redirect location to local path. {}", location);
+                }
+
+                redirectLocation = location;
+            }
+            else
+            {
+                redirectLocation = context.getRequestContext().getRequestBasePath() + localPath;
+            }
+
+            context.getRequestContext().sendRedirect(redirectLocation);
+
+            return true;
+        }
+
+        return false;
+    }
+
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/InitHttpClientCommand.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/InitHttpClientCommand.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/InitHttpClientCommand.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/InitHttpClientCommand.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,83 @@
+/*
+ * 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.webcontent2.proxy2.chain;
+
+import org.apache.http.client.params.ClientPNames;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.routing.HttpRoutePlanner;
+import org.apache.http.params.HttpParams;
+import org.apache.portals.applications.webcontent2.proxy2.impl.ProxyHttpClient;
+
+
+public class InitHttpClientCommand extends AbstractProxyCommand
+{
+
+    private ClientConnectionManager clientConnectionManager;
+
+    private HttpParams httpClientParams;
+
+    private HttpRoutePlanner httpRoutePlanner;
+
+    @Override
+    protected boolean executeInternal(final ProxyContext context) throws Exception
+    {
+        ProxyHttpClient httpClient = new ProxyHttpClient(clientConnectionManager, httpClientParams);
+
+        if (httpRoutePlanner != null)
+        {
+            httpClient.setRoutePlanner(httpRoutePlanner);
+        }
+
+        // redirection should be adjusted with local host header...
+        httpClient.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false);
+
+        context.setHttpClient(httpClient);
+
+        return false;
+    }
+
+    public ClientConnectionManager getClientConnectionManager()
+    {
+        return clientConnectionManager;
+    }
+
+    public void setClientConnectionManager(ClientConnectionManager clientConnectionManager)
+    {
+        this.clientConnectionManager = clientConnectionManager;
+    }
+
+    public HttpParams getHttpClientParams()
+    {
+        return httpClientParams;
+    }
+
+    public void setHttpClientParams(HttpParams httpClientParams)
+    {
+        this.httpClientParams = httpClientParams;
+    }
+
+    public HttpRoutePlanner getHttpRoutePlanner()
+    {
+        return httpRoutePlanner;
+    }
+
+    public void setHttpRoutePlanner(HttpRoutePlanner httpRoutePlanner)
+    {
+        this.httpRoutePlanner = httpRoutePlanner;
+    }
+
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/InitHttpRequestCommand.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/InitHttpRequestCommand.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/InitHttpRequestCommand.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/InitHttpRequestCommand.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,98 @@
+/*
+ * 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.webcontent2.proxy2.chain;
+
+import org.apache.commons.lang.math.NumberUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpHead;
+import org.apache.http.client.methods.HttpOptions;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.client.methods.HttpTrace;
+import org.apache.http.entity.InputStreamEntity;
+import org.apache.http.protocol.HTTP;
+import org.apache.portals.applications.webcontent2.proxy2.ReverseProxyException;
+
+
+public class InitHttpRequestCommand extends AbstractProxyCommand
+{
+
+    @Override
+    protected boolean executeInternal(final ProxyContext context) throws Exception
+    {
+        HttpRequestBase httpRequest = null;
+
+        String method = context.getRequestContext().getMethod();
+        String remoteURI = context.getRemoteURI();
+
+        if (HttpGet.METHOD_NAME.equals(method))
+        {
+            httpRequest = new HttpGet(remoteURI);
+        }
+        else if (HttpHead.METHOD_NAME.equals(method))
+        {
+            httpRequest = new HttpHead(remoteURI);
+        }
+        else if (HttpPost.METHOD_NAME.equals(method))
+        {
+            httpRequest = new HttpPost(remoteURI);
+            long contentLength = NumberUtils.toLong(context.getRequestContext().getHeader(HTTP.CONTENT_LEN));
+
+            if (contentLength > 0L)
+            {
+                HttpEntity entity = new InputStreamEntity(context.getRequestContext().getInputStream(), contentLength);
+                ((HttpPost) httpRequest).setEntity(entity);
+            }
+        }
+        else if (HttpPut.METHOD_NAME.equals(method))
+        {
+            httpRequest = new HttpPut(remoteURI);
+
+            long contentLength = NumberUtils.toLong(context.getRequestContext().getHeader(HTTP.CONTENT_LEN));
+
+            if (contentLength > 0L)
+            {
+                HttpEntity entity = new InputStreamEntity(context.getRequestContext().getInputStream(), contentLength);
+                ((HttpPut) httpRequest).setEntity(entity);
+            }
+        }
+        else if (HttpDelete.METHOD_NAME.equals(method))
+        {
+            httpRequest = new HttpDelete(remoteURI);
+        }
+        else if (HttpOptions.METHOD_NAME.equals(method))
+        {
+            httpRequest = new HttpOptions(remoteURI);
+        }
+        else if (HttpTrace.METHOD_NAME.equals(method))
+        {
+            httpRequest = new HttpHead(remoteURI);
+        }
+        else
+        {
+            throw new ReverseProxyException("Unsupported method: " + method);
+        }
+
+        context.setHttpRequest(httpRequest);
+
+        return false;
+    }
+
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/InitializationCommand.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/InitializationCommand.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/InitializationCommand.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/InitializationCommand.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,36 @@
+/*
+ * 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.webcontent2.proxy2.chain;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+
+public class InitializationCommand extends AbstractProxyCommand
+{
+
+    private static Logger log = LoggerFactory.getLogger(InitializationCommand.class);
+
+    @Override
+    protected boolean executeInternal(final ProxyContext context) throws Exception
+    {
+        log.debug("Reverse-proxying {}", context.getRequestContext().getPathInfo());
+
+        return false;
+    }
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ProxyContext.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ProxyContext.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ProxyContext.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ProxyContext.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,133 @@
+/*
+ * 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.webcontent2.proxy2.chain;
+
+import java.util.Map;
+
+import org.apache.commons.chain.impl.ContextBase;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.portals.applications.webcontent2.proxy2.ProxyMapping;
+import org.apache.portals.applications.webcontent2.proxy2.RequestContext;
+import org.apache.portals.applications.webcontent2.rewriter2.ContentRewriter;
+
+public class ProxyContext extends ContextBase
+{
+
+    private static final long serialVersionUID = 1L;
+
+    private RequestContext requestContext;
+    private ProxyMapping resolvedMapping;
+    private String localPath;
+    private String remoteURI;
+    private HttpClient httpClient;
+    private HttpRequestBase httpRequest;
+    private HttpResponse httpResponse;
+    private ContentRewriter contentRewriter;
+
+    public ProxyContext() 
+    {
+        super();
+    }
+
+    public ProxyContext(Map map) 
+    {
+        super(map);
+    }
+
+    public RequestContext getRequestContext()
+    {
+        return requestContext;
+    }
+
+    public void setRequestContext(RequestContext requestContext)
+    {
+        this.requestContext = requestContext;
+    }
+
+    public ProxyMapping getResolvedMapping()
+    {
+        return resolvedMapping;
+    }
+
+    public void setResolvedMapping(ProxyMapping resolvedMapping)
+    {
+        this.resolvedMapping = resolvedMapping;
+    }
+
+    public String getLocalPath()
+    {
+        return localPath;
+    }
+
+    public void setLocalPath(String localPath)
+    {
+        this.localPath = localPath;
+    }
+
+    public String getRemoteURI()
+    {
+        return remoteURI;
+    }
+
+    public void setRemoteURI(String remoteURI)
+    {
+        this.remoteURI = remoteURI;
+    }
+
+    public HttpClient getHttpClient()
+    {
+        return httpClient;
+    }
+
+    public void setHttpClient(HttpClient httpClient)
+    {
+        this.httpClient = httpClient;
+    }
+
+    public HttpRequestBase getHttpRequest()
+    {
+        return httpRequest;
+    }
+
+    public void setHttpRequest(HttpRequestBase httpRequest)
+    {
+        this.httpRequest = httpRequest;
+    }
+
+    public HttpResponse getHttpResponse()
+    {
+        return httpResponse;
+    }
+
+    public void setHttpResponse(HttpResponse httpResponse)
+    {
+        this.httpResponse = httpResponse;
+    }
+
+    public ContentRewriter getContentRewriter()
+    {
+        return contentRewriter;
+    }
+
+    public void setContentRewriter(ContentRewriter contentRewriter)
+    {
+        this.contentRewriter = contentRewriter;
+    }
+
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ResolveContentRewriterCommand.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ResolveContentRewriterCommand.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ResolveContentRewriterCommand.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ResolveContentRewriterCommand.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,33 @@
+/*
+ * 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.webcontent2.proxy2.chain;
+
+import org.apache.portals.applications.webcontent2.proxy2.ProxyMapping;
+
+public class ResolveContentRewriterCommand extends AbstractProxyCommand
+{
+
+    @Override
+    protected boolean executeInternal(final ProxyContext context) throws Exception
+    {
+        ProxyMapping resolvedMapping = context.getResolvedMapping();
+        // TODO:
+
+        return false;
+    }
+
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ResolveLocalPathCommand.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ResolveLocalPathCommand.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ResolveLocalPathCommand.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ResolveLocalPathCommand.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,45 @@
+/*
+ * 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.webcontent2.proxy2.chain;
+
+
+
+public class ResolveLocalPathCommand extends AbstractProxyCommand
+{
+
+    @Override
+    protected boolean executeInternal(final ProxyContext context) throws Exception
+    {
+        String localPath = getInvokedPathInfo(context);
+        context.setLocalPath(localPath);
+
+        return false;
+    }
+
+    private String getInvokedPathInfo(final ProxyContext context)
+    {
+        String pathInfo = (String) context.getRequestContext().getAttribute("javax.servlet.include.path_info");
+
+        if (pathInfo != null)
+        {
+            return pathInfo;
+        }
+
+        return context.getRequestContext().getPathInfo();
+    }
+
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ResolveProxyMappingCommand.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ResolveProxyMappingCommand.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ResolveProxyMappingCommand.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ResolveProxyMappingCommand.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,61 @@
+/*
+ * 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.webcontent2.proxy2.chain;
+
+import org.apache.portals.applications.webcontent2.proxy2.ProxyMapping;
+import org.apache.portals.applications.webcontent2.proxy2.ReverseProxyNotFoundException;
+
+public class ResolveProxyMappingCommand extends AbstractProxyCommand
+{
+
+    private ProxyMapping [] proxyMappings;
+
+    @Override
+    protected boolean executeInternal(final ProxyContext context) throws Exception
+    {
+        final String localPath = context.getLocalPath();
+
+        ProxyMapping resolvedMapping = null;
+
+        if (proxyMappings != null)
+        {
+            for (ProxyMapping proxyMapping : proxyMappings)
+            {
+                if (proxyMapping.matchesLocal(localPath))
+                {
+                    resolvedMapping = proxyMapping;
+                    break;
+                }
+            }
+        }
+
+        if (resolvedMapping == null)
+        {
+            throw new ReverseProxyNotFoundException("Proxy configuration is not defined for " + localPath);
+        }
+
+        context.setResolvedMapping(resolvedMapping);
+
+        return false;
+    }
+
+    public void setProxyMappings(ProxyMapping[] proxyMappings)
+    {
+        this.proxyMappings = proxyMappings;
+    }
+
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ResolveRemoteURICommand.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ResolveRemoteURICommand.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ResolveRemoteURICommand.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/ResolveRemoteURICommand.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,68 @@
+/*
+ * 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.webcontent2.proxy2.chain;
+
+import org.apache.portals.applications.webcontent2.proxy2.ReverseProxyNotFoundException;
+import org.apache.portals.applications.webcontent2.proxy2.URICleaner;
+
+
+public class ResolveRemoteURICommand extends AbstractProxyCommand
+{
+
+    private URICleaner uriCleaner;
+
+    @Override
+    protected boolean executeInternal(final ProxyContext context) throws Exception
+    {
+        String localPath = context.getLocalPath();
+        String remoteURI = context.getResolvedMapping().resolveRemoteFromLocal(localPath);
+
+        if (remoteURI == null)
+        {
+            throw new ReverseProxyNotFoundException("Cannot translate the location path info into remote URI. " + remoteURI);
+        }
+
+        String queryString = context.getRequestContext().getQueryString();
+
+        if (queryString != null)
+        {
+            remoteURI = new StringBuilder(remoteURI.length() + 1 + queryString.length()).append(remoteURI).append('?').append(queryString).toString();
+        }
+
+        // Before invoking HTTP Methods, let's clean the remote target URI
+        // in order to avoid invalid URI exception (e.g. space in the URI)
+        if (uriCleaner != null)
+        {
+            remoteURI = uriCleaner.clean(remoteURI);
+        }
+
+        context.setRemoteURI(remoteURI);
+
+        return false;
+    }
+
+    public URICleaner getUriCleaner()
+    {
+        return uriCleaner;
+    }
+
+    public void setUriCleaner(URICleaner uriCleaner)
+    {
+        this.uriCleaner = uriCleaner;
+    }
+
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/SerializeHttpEntityContentCommand.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/SerializeHttpEntityContentCommand.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/SerializeHttpEntityContentCommand.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/SerializeHttpEntityContentCommand.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,82 @@
+/*
+ * 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.webcontent2.proxy2.chain;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.portals.applications.webcontent2.proxy2.impl.HttpEntitySource;
+import org.apache.portals.applications.webcontent2.rewriter2.ContentRewriter;
+import org.apache.portals.applications.webcontent2.rewriter2.Sink;
+import org.apache.portals.applications.webcontent2.rewriter2.Source;
+
+
+public class SerializeHttpEntityContentCommand extends AbstractProxyCommand
+{
+
+    @Override
+    protected boolean executeInternal(final ProxyContext context) throws Exception
+    {
+        HttpEntity httpEntity = null;
+
+        InputStream in = null;
+        OutputStream out = null;
+
+        try
+        {
+            HttpResponse httpResponse = context.getHttpResponse();
+            httpEntity = httpResponse.getEntity();
+
+            if (httpEntity != null)
+            {
+                Source source = new HttpEntitySource(httpEntity);
+                in = source.getInputStream();
+                Sink sink = context.getRequestContext().getSink();
+
+                ContentRewriter contentRewriter = context.getContentRewriter();
+
+                // According to javadoc of httpclient, getResponseBodyAsStream() can return null
+                // if the response has no body.
+                if (in != null)
+                {
+                    out = sink.getOutputStream();
+                    // TODO: do differently when contentRewriter is set.
+                    IOUtils.copy(in, out);
+                    out.flush();
+                }
+            }
+        }
+        finally
+        {
+            if (in != null)
+            {
+                IOUtils.closeQuietly(in);
+            }
+
+            if (out != null)
+            {
+                IOUtils.closeQuietly(out);
+            }
+        }
+
+        return false;
+    }
+
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/SerializeHttpEntityHeadersCommand.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/SerializeHttpEntityHeadersCommand.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/SerializeHttpEntityHeadersCommand.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/chain/SerializeHttpEntityHeadersCommand.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,107 @@
+/*
+ * 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.webcontent2.proxy2.chain;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.protocol.HTTP;
+
+
+public class SerializeHttpEntityHeadersCommand extends AbstractProxyCommand
+{
+
+    private String hostHeaderValue;
+
+    @Override
+    protected boolean executeInternal(final ProxyContext context) throws Exception
+    {
+        HttpResponse httpResponse = context.getHttpResponse();
+
+        int statusCode = httpResponse.getStatusLine().getStatusCode();
+
+        // Check if the proxy response is a redirect
+        if (statusCode >= HttpServletResponse.SC_MULTIPLE_CHOICES /* 300 */
+            && statusCode <= HttpServletResponse.SC_NOT_MODIFIED /* 304 */)
+        {
+            return false;
+        }
+
+        // Pass the response code back to the client
+        context.getRequestContext().setStatus(statusCode);
+
+        HttpEntity httpEntity = httpResponse.getEntity();
+
+        if (httpEntity != null)
+        {
+            // Pass response headers back to the client
+            Header [] headerArrayResponse = httpResponse.getAllHeaders();
+
+            for (Header header : headerArrayResponse)
+            {
+                String headerName = header.getName();
+
+                if (context.getContentRewriter() != null && StringUtils.equalsIgnoreCase(headerName, HTTP.CONTENT_LEN))
+                    continue;
+
+                if (StringUtils.startsWithIgnoreCase(headerName, "Set-Cookie"))
+                    continue;
+
+                String headerValue = header.getValue();
+
+                if (StringUtils.equalsIgnoreCase(headerName, HTTP.TARGET_HOST))
+                {
+                    String host = hostHeaderValue;
+
+                    if (host == null)
+                    {
+                        if (context.getRequestContext().getServerPort() == 80)
+                        {
+                            host = context.getRequestContext().getServerName();
+                        }
+                        else
+                        {
+                            host = context.getRequestContext().getServerName() + ":" + context.getRequestContext().getServerPort();
+                        }
+                    }
+
+                    context.getRequestContext().setHeader(headerName, host);
+                }
+                else
+                {
+                    context.getRequestContext().setHeader(headerName, headerValue);
+                }
+            }
+        }
+
+        return false;
+    }
+
+    public String getHostHeaderValue()
+    {
+        return hostHeaderValue;
+    }
+
+    public void setHostHeaderValue(String hostHeaderValue)
+    {
+        this.hostHeaderValue = hostHeaderValue;
+    }
+
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/DefaultReverseProxyService.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/DefaultReverseProxyService.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/DefaultReverseProxyService.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/DefaultReverseProxyService.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,48 @@
+package org.apache.portals.applications.webcontent2.proxy2.impl;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.chain.Command;
+import org.apache.portals.applications.webcontent2.proxy2.ReverseProxyException;
+import org.apache.portals.applications.webcontent2.proxy2.ReverseProxyService;
+import org.apache.portals.applications.webcontent2.proxy2.chain.ProxyContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DefaultReverseProxyService implements ReverseProxyService
+{
+
+    private static Logger log = LoggerFactory.getLogger(DefaultReverseProxyService.class);
+
+    private final Command proxyServiceCommand;
+
+    public DefaultReverseProxyService(final Command proxyServiceCommand)
+    {
+        this.proxyServiceCommand = proxyServiceCommand;
+    }
+
+    public void initialize()
+    {
+    }
+
+    public void invoke(HttpServletRequest request, HttpServletResponse response) throws ReverseProxyException, IOException
+    {
+        try
+        {
+            ProxyContext context = new ProxyContext();
+            context.setRequestContext(new ServletRequestContext(request, response));
+            proxyServiceCommand.execute(context);
+        }
+        catch (Exception e)
+        {
+            log.error("Failed to execute proxy service.", e);
+        }
+    }
+
+    public void destroy()
+    {
+    }
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/HttpEntitySource.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/HttpEntitySource.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/HttpEntitySource.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/HttpEntitySource.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,63 @@
+/*
+ * 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.webcontent2.proxy2.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.util.EntityUtils;
+import org.apache.portals.applications.webcontent2.rewriter2.Source;
+
+public class HttpEntitySource implements Source
+{
+
+    private final HttpEntity entity;
+    private final String characterEncoding;
+
+    public HttpEntitySource(final HttpEntity entity)
+    {
+        this(entity, null);
+    }
+
+    public HttpEntitySource(final HttpEntity entity, final String characterEncoding)
+    {
+        this.entity = entity;
+        this.characterEncoding = characterEncoding;
+    }
+
+    public InputStream getInputStream() throws IOException
+    {
+        return entity.getContent();
+    }
+
+    public Reader getReader() throws IOException
+    {
+        String charset = (characterEncoding != null ? characterEncoding : EntityUtils.getContentCharSet(entity));
+
+        if (charset != null)
+        {
+            return new InputStreamReader(getInputStream(), charset);
+        }
+        else
+        {
+            return new InputStreamReader(getInputStream());
+        }
+    }
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/HttpServletResponseSink.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/HttpServletResponseSink.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/HttpServletResponseSink.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/HttpServletResponseSink.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,46 @@
+/*
+ * 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.webcontent2.proxy2.impl;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.portals.applications.webcontent2.rewriter2.Sink;
+
+public class HttpServletResponseSink implements Sink
+{
+
+    private final HttpServletResponse response;
+
+    public HttpServletResponseSink(final HttpServletResponse response)
+    {
+        this.response = response;
+    }
+
+    public OutputStream getOutputStream() throws IOException
+    {
+        return response.getOutputStream();
+    }
+
+    public Writer getWriter() throws IOException
+    {
+        return response.getWriter();
+    }
+}

Added: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/LocationProxyMapping.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/LocationProxyMapping.java?rev=1610080&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/LocationProxyMapping.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy2/impl/LocationProxyMapping.java Sat Jul 12 22:43:53 2014
@@ -0,0 +1,64 @@
+/*
+ * 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.webcontent2.proxy2.impl;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.portals.applications.webcontent2.proxy2.ProxyMapping;
+
+public class LocationProxyMapping implements ProxyMapping
+{
+
+    private final String localBasePath;
+    private final String remoteBaseURL;
+
+    public LocationProxyMapping(final String localBasePath, final String remoteBaseURL)
+    {
+        this.localBasePath = localBasePath;
+        this.remoteBaseURL = remoteBaseURL;
+    }
+
+    public boolean matchesLocal(String localURI)
+    {
+        if (localURI != null)
+        {
+            return localURI.startsWith(localBasePath);
+        }
+
+        return false;
+    }
+
+    public String resolveRemoteFromLocal(String localPath)
+    {
+        return new StringBuilder(80).append(remoteBaseURL).append(StringUtils.substringAfter(localPath, localBasePath)).toString();
+    }
+
+    public boolean matchesRemote(String remoteURI)
+    {
+        if (remoteURI != null)
+        {
+            return remoteURI.startsWith(remoteBaseURL);
+        }
+
+        return false;
+    }
+
+    public String resolveLocalFromRemote(String remoteURI)
+    {
+        return new StringBuilder(80).append(localBasePath).append(StringUtils.substringAfter(remoteURI, remoteBaseURL)).toString();
+    }
+
+}