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/09/17 12:22:07 UTC
svn commit: r816126 [1/2] - in /portals/applications/webcontent/trunk:
webcontent-jar/
webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/portlet/
webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/
webco...
Author: woonsan
Date: Thu Sep 17 10:22:06 2009
New Revision: 816126
URL: http://svn.apache.org/viewvc?rev=816126&view=rev
Log:
APA-16: Adding out-of-box reverse proxy service component.
Also, some improvements as follows:
- Makes it fully configurable on http client, connection manager, proxy path url mappings and rewriter configurations.
- Enhances performance by following the performance guidelines of httpclient.
- Uses Portlet 2.0 head contribution feature to add auto-resizing javascript just once.
- Adds out-of-box reverse proxy servlet with example configurations for www.apache.org and portals.apache.org
- Improves redirection url location handling.
Added:
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapper.java (with props)
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapperProvider.java (with props)
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyService.java (with props)
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpProxyPathMapperImpl.java (with props)
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyPathMapperProviderImpl.java (with props)
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyServlet.java (with props)
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java (with props)
portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy-urlmappings.properties (with props)
Modified:
portals/applications/webcontent/trunk/webcontent-jar/pom.xml
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/portlet/IFrameGenericPortlet.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/main/java/org/apache/portals/applications/webcontent/rewriter/RewriterController.java
portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/portlet.xml
portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/web.xml
portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/javascript/iframe_autoresize.js
Modified: portals/applications/webcontent/trunk/webcontent-jar/pom.xml
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/pom.xml?rev=816126&r1=816125&r2=816126&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/pom.xml (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/pom.xml Thu Sep 17 10:22:06 2009
@@ -38,7 +38,10 @@
<nekohtml.version>0.9.5</nekohtml.version>
<castor.version>1.1.1-xml</castor.version>
<commons-lang.version>2.4</commons-lang.version>
+ <commons-io.version>1.4</commons-io.version>
<commons-httpclient.version>3.0.1</commons-httpclient.version>
+ <commons-fileupload.version>1.2</commons-fileupload.version>
+ <commons-beanutils.version>1.7.0</commons-beanutils.version>
</properties>
<!-- Dependencies -->
@@ -103,6 +106,11 @@
<version>${commons-lang.version}</version>
</dependency>
<dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>${commons-io.version}</version>
+ </dependency>
+ <dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>${commons-httpclient.version}</version>
@@ -118,6 +126,16 @@
</exclusions>
</dependency>
<dependency>
+ <groupId>commons-fileupload</groupId>
+ <artifactId>commons-fileupload</artifactId>
+ <version>${commons-fileupload.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-beanutils</groupId>
+ <artifactId>commons-beanutils</artifactId>
+ <version>${commons-beanutils.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
Modified: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/portlet/IFrameGenericPortlet.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/portlet/IFrameGenericPortlet.java?rev=816126&r1=816125&r2=816126&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/portlet/IFrameGenericPortlet.java (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/portlet/IFrameGenericPortlet.java Thu Sep 17 10:22:06 2009
@@ -22,6 +22,7 @@
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
+import javax.portlet.MimeResponse;
import javax.portlet.PortletConfig;
import javax.portlet.PortletException;
import javax.portlet.PortletPreferences;
@@ -32,6 +33,7 @@
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.portals.bridges.velocity.GenericVelocityPortlet;
+import org.w3c.dom.Element;
/**
* IFrameGenericPortlet
@@ -42,10 +44,13 @@
public class IFrameGenericPortlet extends GenericVelocityPortlet
{
- private Map attributes = new HashMap();
+ public static final String IFRAME_AUTORESIZE_SCRIPT_ID = "org.apache.portals.applications.webcontent.portlet.iframe.autoresize";
- private Map maxAttributes = new HashMap();
+ private Map<String, String> attributes = new HashMap<String, String>();
+ private Map<String, String> maxAttributes = new HashMap<String, String>();
+
+ @Override
public void init(PortletConfig config) throws PortletException
{
super.init(config);
@@ -83,12 +88,12 @@
return this.getMappedAttributePreference(prefs, "MAX-" + attribute, maxAttributes);
}
- private String getMappedAttributePreference(PortletPreferences prefs, String attribute, Map map)
+ private String getMappedAttributePreference(PortletPreferences prefs, String attribute, Map<String, String> map)
{
- return prefs.getValue(attribute, (String) map.get(attribute));
+ return prefs.getValue(attribute, map.get(attribute));
}
- private void appendAttribute(PortletPreferences prefs, StringBuffer content, String attribute, Map map)
+ private void appendAttribute(PortletPreferences prefs, StringBuffer content, String attribute, Map<String, String> map)
{
String value;
@@ -110,7 +115,31 @@
{
appendAttribute(prefs, content, attribute, maxAttributes);
}
-
+
+ @Override
+ protected void doHeaders(RenderRequest request, RenderResponse response)
+ {
+ PortletPreferences prefs = request.getPreferences();
+ String autoResize = getAttributePreference(prefs, "AUTORESIZE");
+ String autoResizeScript = getAttributePreference(prefs, "AUTORESIZESCRIPT");
+
+ if (BooleanUtils.toBoolean(autoResize))
+ {
+ if (StringUtils.isBlank(autoResizeScript))
+ {
+ autoResizeScript = request.getContextPath() + "/javascript/iframe_autoresize.js";
+ }
+
+ Element headElem = response.createElement("script");
+ headElem.setAttribute("id", IFRAME_AUTORESIZE_SCRIPT_ID);
+ headElem.setAttribute("language", "JavaScript");
+ headElem.setAttribute("type", "text/javascript");
+ headElem.setAttribute("src", autoResizeScript);
+ response.addProperty(MimeResponse.MARKUP_HEAD_ELEMENT, headElem);
+ }
+ }
+
+ @Override
public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException
{
String viewPage = (String)request.getAttribute(PARAM_VIEW_PAGE);
@@ -124,6 +153,7 @@
}
}
+ @Override
public void doEdit(RenderRequest request, RenderResponse response) throws PortletException, IOException
{
response.setContentType("text/html");
@@ -179,19 +209,6 @@
// end fix JS2-349
content.append("</TD></TR></TBODY></TABLE>");
- String autoResize = getAttributePreference(prefs, "AUTORESIZE");
- String autoResizeScript = getAttributePreference(prefs, "AUTORESIZESCRIPT");
-
- if (StringUtils.isBlank(autoResizeScript))
- {
- autoResizeScript = request.getContextPath() + "/javascript/iframe_autoresize.js";
- }
-
- if (BooleanUtils.toBoolean(autoResize))
- {
- content.append("<SCRIPT LANGUAGE=\"JavaScript\" SRC=\"").append(autoResizeScript).append("\"></SCRIPT>\n");
- }
-
// set required content type and write HTML IFRAME content
response.setContentType("text/html");
response.getWriter().print(content.toString());
@@ -208,13 +225,20 @@
String proxyRemoteURL = getAttributePreference(prefs, "PROXYREMOTEURL");
String proxyLocalPath = getAttributePreference(prefs, "PROXYLOCALPATH");
- if (source == null)
+ if (source == null)
{
source = "";
}
else if (StringUtils.isNotEmpty(proxyRemoteURL) && StringUtils.isNotEmpty(proxyLocalPath) && source.startsWith(proxyRemoteURL))
{
- source = proxyLocalPath + source.substring(proxyRemoteURL.length());
+ if (proxyLocalPath.startsWith("/"))
+ {
+ source = proxyLocalPath + source.substring(proxyRemoteURL.length());
+ }
+ else
+ {
+ source = request.getContextPath() + "/" + proxyLocalPath + source.substring(proxyRemoteURL.length());
+ }
}
return source;
@@ -223,6 +247,7 @@
/**
* Save the prefs
*/
+ @Override
public void processAction(ActionRequest request, ActionResponse actionResponse) throws PortletException,
IOException
{
Added: 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=816126&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapper.java (added)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapper.java Thu Sep 17 10:22:06 2009
@@ -0,0 +1,55 @@
+/*
+ * 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;
+
+/**
+ * proxy path mapper interface for http reverse proxy service.
+ *
+ * @version $Id$
+ */
+public interface HttpReverseProxyPathMapper
+{
+
+ /**
+ * Returns the local base path to be mapped to remote base url.
+ * @return
+ */
+ public String getLocalBasePath();
+
+ /**
+ * Returns the remote base url mapped by the local path.
+ * @return
+ */
+ public String getRemoteBaseURL();
+
+ /**
+ * Generates a remote url mapped by the path.
+ * <P>It returns a translated remote URL or null if the translation fails.</P>
+ * @param localPath
+ * @return
+ */
+ public String getRemoteURL(String localPath);
+
+ /**
+ * Generates a local url mapped by the remote url.
+ * <P>It returns a translated local path or null if the translation fails.</P>
+ * @param remoteURL
+ * @return
+ */
+ public String getLocalPath(String remoteURL);
+
+}
\ No newline at end of file
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapper.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapper.java
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapper.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: 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=816126&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapperProvider.java (added)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapperProvider.java Thu Sep 17 10:22:06 2009
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.portals.applications.webcontent.proxy;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.portals.applications.webcontent.rewriter.Rewriter;
+import org.apache.portals.applications.webcontent.rewriter.RewriterController;
+
+/**
+ * proxy path mapper provider interface for http reverse proxy service.
+ *
+ * @version $Id$
+ */
+public interface HttpReverseProxyPathMapperProvider
+{
+
+ /**
+ * Finds a reverse proxy path mapper based on the request
+ * @return
+ */
+ public HttpReverseProxyPathMapper findMapper(HttpServletRequest request);
+
+ /**
+ * Finds a reverse proxy path mapper based on the remoteURL
+ * @return
+ */
+ public HttpReverseProxyPathMapper findMapperByRemoteURL(String remoteURL);
+
+ /**
+ * Finds a reverse proxy rewriter controller based on the request
+ * @return
+ */
+ public RewriterController findRewriterController(HttpServletRequest request);
+
+ /**
+ * Finds a reverse proxy rewriter based on the request
+ * @return
+ */
+ public Rewriter findRewriter(HttpServletRequest request);
+
+}
\ No newline at end of file
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapperProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapperProvider.java
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyPathMapperProvider.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: 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=816126&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyService.java (added)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyService.java Thu Sep 17 10:22:06 2009
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.portals.applications.webcontent.proxy;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+
+/**
+ * HTTP Reverse Proxy Service interface
+ *
+ * @version $Id$
+ */
+public interface HttpReverseProxyService
+{
+
+ public void initialize();
+
+ public void destroy();
+
+ public void invoke(HttpServletRequest request, HttpServletResponse response) throws IOException;
+
+}
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyService.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyService.java
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyService.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpProxyPathMapperImpl.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpProxyPathMapperImpl.java?rev=816126&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpProxyPathMapperImpl.java (added)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpProxyPathMapperImpl.java Thu Sep 17 10:22:06 2009
@@ -0,0 +1,67 @@
+/*
+ * 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;
+
+/**
+ * Default implementation of <CODE>HttpProxyPathMapper</CODE> interface.
+ *
+ * @version $Id$
+ */
+public class DefaultHttpProxyPathMapperImpl implements HttpReverseProxyPathMapper
+{
+ private String localBasePath;
+ private String remoteBaseURL;
+
+ public DefaultHttpProxyPathMapperImpl(String localBasePath, String remoteBaseURL)
+ {
+ this.localBasePath = localBasePath;
+ this.remoteBaseURL = remoteBaseURL;
+ }
+
+ public String getLocalBasePath()
+ {
+ return localBasePath;
+ }
+
+ public String getRemoteBaseURL()
+ {
+ return remoteBaseURL;
+ }
+
+ public String getRemoteURL(String localPath)
+ {
+ if (localPath.startsWith(localBasePath))
+ {
+ return remoteBaseURL + localPath.substring(localBasePath.length());
+ }
+
+ return null;
+ }
+
+ public String getLocalPath(String remoteURL)
+ {
+ if (remoteURL.startsWith(remoteBaseURL))
+ {
+ return localBasePath + remoteURL.substring(remoteBaseURL.length());
+ }
+
+ return null;
+ }
+
+}
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpProxyPathMapperImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpProxyPathMapperImpl.java
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpProxyPathMapperImpl.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: 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=816126&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyPathMapperProviderImpl.java (added)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyPathMapperProviderImpl.java Thu Sep 17 10:22:06 2009
@@ -0,0 +1,122 @@
+/*
+ * 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 java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.collections.KeyValue;
+import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapper;
+import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapperProvider;
+import org.apache.portals.applications.webcontent.rewriter.Rewriter;
+import org.apache.portals.applications.webcontent.rewriter.RewriterController;
+
+/**
+ * Default <CODE>HttpReverseProxyPathMapperProvider</CODE> implementation
+ *
+ * @version $Id$
+ */
+public class DefaultHttpReverseProxyPathMapperProviderImpl implements HttpReverseProxyPathMapperProvider
+{
+
+ /**
+ * Proxy path mappers
+ */
+ private List<HttpReverseProxyPathMapper> proxyPathMappers;
+
+ /**
+ * rewriter controller mappers
+ */
+ private List<KeyValue> rewriterControllerPairs;
+
+ /**
+ * rewriters
+ */
+ private List<KeyValue> rewriterPairs;
+
+ public DefaultHttpReverseProxyPathMapperProviderImpl(List<HttpReverseProxyPathMapper> proxyPathMappers,
+ List<KeyValue> rewriterControllerPairs,
+ List<KeyValue> rewriterPairs)
+ {
+ this.proxyPathMappers = proxyPathMappers;
+ this.rewriterControllerPairs = rewriterControllerPairs;
+ this.rewriterPairs = rewriterPairs;
+ }
+
+ public HttpReverseProxyPathMapper findMapper(HttpServletRequest request)
+ {
+ String pathInfo = request.getPathInfo();
+
+ for (HttpReverseProxyPathMapper proxyPathMapper : proxyPathMappers)
+ {
+ if (pathInfo.startsWith(proxyPathMapper.getLocalBasePath()))
+ {
+ return proxyPathMapper;
+ }
+ }
+
+ return null;
+ }
+
+ public HttpReverseProxyPathMapper findMapperByRemoteURL(String remoteURL)
+ {
+ if (remoteURL != null)
+ {
+ for (HttpReverseProxyPathMapper proxyPathMapper : proxyPathMappers)
+ {
+ if (remoteURL.startsWith(proxyPathMapper.getRemoteBaseURL()))
+ {
+ return proxyPathMapper;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public RewriterController findRewriterController(HttpServletRequest request)
+ {
+ String pathInfo = request.getPathInfo();
+
+ for (KeyValue pair : rewriterControllerPairs)
+ {
+ if (pathInfo.startsWith((String) pair.getKey()))
+ {
+ return (RewriterController) pair.getValue();
+ }
+ }
+
+ return null;
+ }
+
+ public Rewriter findRewriter(HttpServletRequest request)
+ {
+ String pathInfo = request.getPathInfo();
+
+ for (KeyValue pair : rewriterPairs)
+ {
+ if (pathInfo.startsWith((String) pair.getKey()))
+ {
+ return (Rewriter) pair.getValue();
+ }
+ }
+
+ return null;
+ }
+
+}
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyPathMapperProviderImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyPathMapperProviderImpl.java
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyPathMapperProviderImpl.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: 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=816126&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyServlet.java (added)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyServlet.java Thu Sep 17 10:22:06 2009
@@ -0,0 +1,297 @@
+/*
+ * 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 java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.collections.KeyValue;
+import org.apache.commons.collections.keyvalue.DefaultKeyValue;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.BooleanUtils;
+import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapper;
+import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapperProvider;
+import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyService;
+import org.apache.portals.applications.webcontent.rewriter.MappingRewriterController;
+import org.apache.portals.applications.webcontent.rewriter.Rewriter;
+import org.apache.portals.applications.webcontent.rewriter.RewriterController;
+import org.apache.portals.applications.webcontent.rewriter.WebContentRewriter;
+import org.apache.portals.applications.webcontent.rewriter.html.neko.NekoParserAdaptor;
+import org.apache.portals.applications.webcontent.rewriter.xml.SaxParserAdaptor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Default reverse proxy servlet implementation as an example.
+ *
+ * @version $Id$
+ */
+public class DefaultHttpReverseProxyServlet extends HttpServlet
+{
+ private static final long serialVersionUID = 1L;
+
+ private static Logger log = LoggerFactory.getLogger(DefaultHttpReverseProxyServlet.class);
+
+ protected HttpReverseProxyPathMapperProvider proxyPathMapperProvider;
+ protected HttpReverseProxyService proxyService;
+
+ @Override
+ public void init(ServletConfig config) throws ServletException
+ {
+ List<HttpReverseProxyPathMapper> proxyPathMappers = new ArrayList<HttpReverseProxyPathMapper>();
+ List<KeyValue> rewriterControllerPairs = new ArrayList<KeyValue>();
+ List<KeyValue> rewriterPairs = new ArrayList<KeyValue>();
+
+ String urlMappings = config.getInitParameter("reverseproxy.urlmappings");
+
+ if (urlMappings != null)
+ {
+ Pattern reverseProxyPathURLPattern = Pattern.compile("^ReverseProxyPathURL\\s+(\\S+)\\s+(\\S+)$", Pattern.CASE_INSENSITIVE);
+ Pattern reverseProxyRewriterPattern = Pattern.compile("^ReverseProxyRewriter\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)$", Pattern.CASE_INSENSITIVE);
+
+ List lines = readLines(config, urlMappings, null);
+
+ for (Iterator it = lines.iterator(); it.hasNext(); )
+ {
+ String line = ((String) it.next()).trim();
+
+ if ("".equals(line) || line.startsWith("#"))
+ {
+ continue;
+ }
+
+ Matcher reverseProxyPathURLMatcher = reverseProxyPathURLPattern.matcher(line);
+ Matcher reverseProxyRewriterMatcher = reverseProxyRewriterPattern.matcher(line);
+
+ if (reverseProxyPathURLMatcher.matches())
+ {
+ String localBasePath = reverseProxyPathURLMatcher.group(1);
+ String remoteBaseURL = reverseProxyPathURLMatcher.group(2);
+ HttpReverseProxyPathMapper proxyPathMapper = new DefaultHttpProxyPathMapperImpl(localBasePath, remoteBaseURL);
+ proxyPathMappers.add(proxyPathMapper);
+ }
+ else if (reverseProxyRewriterMatcher.matches())
+ {
+ String localBasePath = reverseProxyRewriterMatcher.group(1);
+ String rulesMapping = reverseProxyRewriterMatcher.group(2);
+ String rewriterRules = reverseProxyRewriterMatcher.group(3);
+
+ try
+ {
+ RewriterController rewriterController = createRewriterController(config, rulesMapping);
+ rewriterControllerPairs.add(new DefaultKeyValue(localBasePath, rewriterController));
+ Rewriter rewriter = createRewriter(config, rewriterController, rewriterRules);
+ rewriterPairs.add(new DefaultKeyValue(localBasePath, rewriter));
+ }
+ catch (Exception e)
+ {
+ throw new ServletException(e);
+ }
+ }
+ }
+ }
+
+ proxyPathMapperProvider = new DefaultHttpReverseProxyPathMapperProviderImpl(proxyPathMappers, rewriterControllerPairs, rewriterPairs);
+ proxyService = new RewritableHttpReverseProxyServiceImpl(proxyPathMapperProvider);
+
+ String param = config.getInitParameter("reverseproxy.fileuploaddir");
+
+ if (param != null)
+ {
+ param = param.trim();
+
+ if (param.startsWith("file:"))
+ {
+ ((RewritableHttpReverseProxyServiceImpl) proxyService).setFileUploadDir(new File(URI.create(param)));
+ }
+ else if (param.startsWith("/"))
+ {
+ ((RewritableHttpReverseProxyServiceImpl) proxyService).setFileUploadDir(new File(config.getServletContext().getRealPath(param)));
+ }
+ else
+ {
+ ((RewritableHttpReverseProxyServiceImpl) proxyService).setFileUploadDir(new File(param));
+ }
+ }
+
+ param = config.getInitParameter("reverseproxy.hostheadervalue");
+
+ if (param != null)
+ {
+ ((RewritableHttpReverseProxyServiceImpl) proxyService).setHostHeaderValue(param.trim());
+ }
+
+ param = config.getInitParameter("reverseproxy.localbaseurl");
+
+ if (param != null)
+ {
+ ((RewritableHttpReverseProxyServiceImpl) proxyService).setLocalBaseURL(param.trim());
+ }
+
+ param = config.getInitParameter("reverseproxy.maxfileuploadsize");
+
+ if (param != null)
+ {
+ ((RewritableHttpReverseProxyServiceImpl) proxyService).setMaxFileUploadSize(Integer.parseInt(param.trim()));
+ }
+
+ param = config.getInitParameter("reverseproxy.prependlocalbaseurl");
+
+ if (param != null)
+ {
+ ((RewritableHttpReverseProxyServiceImpl) proxyService).setPrependLocalBaseURL(BooleanUtils.toBoolean(param.trim()));
+ }
+
+ param = config.getInitParameter("reverseproxy.cookiepolicy");
+
+ if (param != null)
+ {
+ ((RewritableHttpReverseProxyServiceImpl) proxyService).setCookiePolicy(param.trim());
+ }
+
+ Properties connectionProperties = new Properties();
+
+ for (Enumeration enumParamNames = config.getInitParameterNames(); enumParamNames.hasMoreElements(); )
+ {
+ String paramName = (String) enumParamNames.nextElement();
+
+ if (paramName.startsWith("connection.property."))
+ {
+ String propName = paramName.substring("connection.property.".length());
+ String paramValue = config.getInitParameter(paramName);
+ connectionProperties.setProperty(propName, paramValue);
+ }
+ }
+
+ if (!connectionProperties.isEmpty())
+ {
+ ((RewritableHttpReverseProxyServiceImpl) proxyService).setConnectionProperties(connectionProperties);
+ }
+
+ proxyService.initialize();
+ }
+
+ public void destroy()
+ {
+ if (proxyService != null)
+ {
+ proxyService.destroy();
+ }
+
+ proxyService = null;
+ }
+
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ proxyService.invoke(request, response);
+ }
+
+ public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ doGet(request, response);
+ }
+
+ private List readLines(ServletConfig config, String resourceContextRelativePath, String encoding)
+ {
+ List lines = null;
+ InputStream input = null;
+
+ try
+ {
+ input = config.getServletContext().getResourceAsStream(resourceContextRelativePath);
+ lines = IOUtils.readLines(input, encoding);
+ }
+ catch (IOException e)
+ {
+ log.error("Failed to read resource: " + resourceContextRelativePath + ". " + e);
+ }
+ finally
+ {
+ if (input != null)
+ {
+ try
+ {
+ input.close();
+ }
+ catch (Exception ce)
+ {
+ }
+ }
+ }
+
+ return Collections.unmodifiableList(lines != null ? lines : Collections.emptyList());
+ }
+
+ private RewriterController createRewriterController(ServletConfig config, String rulesMappingResourcePath) throws Exception
+ {
+ RewriterController rwc = null;
+
+ Class [] rewriterClasses = new Class[] { WebContentRewriter.class, WebContentRewriter.class};
+ Class [] adaptorClasses = new Class[] { NekoParserAdaptor.class, SaxParserAdaptor.class};
+
+ rwc = new MappingRewriterController(config.getServletContext().getRealPath(rulesMappingResourcePath),
+ Arrays.asList(rewriterClasses),
+ Arrays.asList(adaptorClasses));
+
+ return rwc;
+ }
+
+ private Rewriter createRewriter(ServletConfig config, RewriterController rwc, String rewriterRulesResourcePath) throws Exception
+ {
+ Rewriter rewriter = null;
+ InputStream rewriterRulesInput = null;
+
+ try
+ {
+ rewriterRulesInput = config.getServletContext().getResourceAsStream(rewriterRulesResourcePath);
+ rewriter = rwc.createRewriter(rwc.loadRuleset(rewriterRulesInput));
+ }
+ finally
+ {
+ if (rewriterRulesInput != null)
+ {
+ try
+ {
+ rewriterRulesInput.close();
+ }
+ catch (Exception ce)
+ {
+ }
+ }
+ }
+
+ return rewriter;
+ }
+
+}
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyServlet.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyServlet.java
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyServlet.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java?rev=816126&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java (added)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java Thu Sep 17 10:22:06 2009
@@ -0,0 +1,620 @@
+/*
+ * 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 java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.fileupload.disk.DiskFileItem;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.HttpMethodBase;
+import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.cookie.CookiePolicy;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.multipart.ByteArrayPartSource;
+import org.apache.commons.httpclient.methods.multipart.FilePart;
+import org.apache.commons.httpclient.methods.multipart.FilePartSource;
+import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
+import org.apache.commons.httpclient.methods.multipart.Part;
+import org.apache.commons.httpclient.methods.multipart.PartSource;
+import org.apache.commons.httpclient.methods.multipart.StringPart;
+import org.apache.commons.io.IOUtils;
+import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapper;
+import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapperProvider;
+import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyService;
+import org.apache.portals.applications.webcontent.rewriter.ParserAdaptor;
+import org.apache.portals.applications.webcontent.rewriter.Rewriter;
+import org.apache.portals.applications.webcontent.rewriter.RewriterController;
+import org.apache.portals.applications.webcontent.rewriter.RewriterException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * HTTP Reverse Proxy Service Implementation
+ *
+ * @version $Id$
+ */
+public class RewritableHttpReverseProxyServiceImpl implements HttpReverseProxyService
+{
+
+ private static Logger log = LoggerFactory.getLogger(RewritableHttpReverseProxyServiceImpl.class);
+
+ public static final String REVERSE_PROXY_PATH_MAPPER_ATTRIBUTE = "org.apache.jetspeed.proxy.reverseProxyPathMapper";
+
+ public static final String REWRITER_CONTROLLER_ATTRIBUTE = "rewriterController";
+
+ private static final String LOCATION_HEADER = "Location";
+
+ private static final String CONTENT_TYPE_HEADER = "Content-Type";
+
+ private static final String CONTENT_LENGTH_HEADER = "Content-Length";
+
+ private static final String HOST_HEADER = "Host";
+
+ /**
+ * Proxy path mapper provider
+ */
+ private HttpReverseProxyPathMapperProvider proxyPathMapperProvider;
+
+ /**
+ * Forced host header value
+ */
+ private String hostHeaderValue;
+
+ /**
+ * forced local base url. e.g., "http://localhost:8080/jetspeed/webcontent".
+ */
+ private String localBaseURL;
+
+ /**
+ * flag to force to prefix localBaseURL when it redirects
+ */
+ private boolean prependLocalBaseURL;
+
+ /**
+ * Maximum file upload size
+ */
+ private int maxFileUploadSize;
+
+ /**
+ * File upload directory
+ */
+ private File fileUploadDir;
+
+ /**
+ * Cookie policy
+ */
+ private String cookiePolicy = CookiePolicy.IGNORE_COOKIES;
+
+ /**
+ * The shared http client for performance.
+ */
+ private HttpClient httpClient;
+
+ /**
+ * HTTP Connection Parameters
+ */
+ private Properties connectionProperties;
+
+ public RewritableHttpReverseProxyServiceImpl(HttpReverseProxyPathMapperProvider proxyPathMapperProvider)
+ {
+ this.proxyPathMapperProvider = proxyPathMapperProvider;
+ }
+
+ public void setHostHeaderValue(String hostHeaderValue)
+ {
+ this.hostHeaderValue = hostHeaderValue;
+ }
+
+ public void setLocalBaseURL(String localBaseURL)
+ {
+ this.localBaseURL = localBaseURL;
+ }
+
+ public void setPrependLocalBaseURL(boolean prependLocalBaseURL)
+ {
+ this.prependLocalBaseURL = prependLocalBaseURL;
+ }
+
+ public void setMaxFileUploadSize(int maxFileUploadSize)
+ {
+ this.maxFileUploadSize = maxFileUploadSize;
+ }
+
+ public void setFileUploadDir(File fileUploadDir)
+ {
+ this.fileUploadDir = fileUploadDir;
+ }
+
+ public void setCookiePolicy(String cookiePolicy)
+ {
+ this.cookiePolicy = cookiePolicy;
+ }
+
+ public void setConnectionProperties(Properties connectionProperties)
+ {
+ this.connectionProperties = connectionProperties;
+ }
+
+ public void initialize()
+ {
+ MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
+
+ if (connectionProperties != null)
+ {
+ for (Enumeration enumPropNames = connectionProperties.propertyNames(); enumPropNames.hasMoreElements(); )
+ {
+ String propName = (String) enumPropNames.nextElement();
+ String propValue = connectionProperties.getProperty(propName);
+
+ try
+ {
+ PropertyUtils.setProperty(connectionManager, propName, propValue);
+ }
+ catch (Exception e)
+ {
+ if (log.isDebugEnabled())
+ {
+ log.error("Cannot set property. " + propName + " = " + propValue, e);
+ }
+ else
+ {
+ log.error("Cannot set property. " + propName + " = " + propValue + ". {}", e);
+ }
+ }
+ }
+ }
+
+ httpClient = new HttpClient(connectionManager);
+ }
+
+ public void destroy()
+ {
+ if (httpClient != null)
+ {
+ ((MultiThreadedHttpConnectionManager) httpClient.getHttpConnectionManager()).shutdown();
+ }
+
+ httpClient = null;
+ }
+
+ public void invoke(HttpServletRequest request, HttpServletResponse response) throws IOException
+ {
+ // proxyPathMapper can be injected by using request attribute.
+ HttpReverseProxyPathMapper proxyPathMapper = (HttpReverseProxyPathMapper) request.getAttribute(REVERSE_PROXY_PATH_MAPPER_ATTRIBUTE);
+
+ String pathInfo = request.getPathInfo();
+
+ if (proxyPathMapper == null)
+ {
+ proxyPathMapper = proxyPathMapperProvider.findMapper(request);
+ }
+
+ if (proxyPathMapper == null)
+ {
+ throw new IOException("Proxy configuration is not defined for " + pathInfo);
+ }
+
+ if (hostHeaderValue == null)
+ {
+ if (request.getServerPort() == 80)
+ {
+ hostHeaderValue = request.getServerName();
+ }
+ else
+ {
+ hostHeaderValue = request.getServerName() + ":" + request.getServerPort();
+ }
+ }
+
+ if (localBaseURL == null)
+ {
+ localBaseURL = request.getScheme() + "://" + hostHeaderValue + request.getServletPath();
+ }
+
+ String proxyTargetURL = proxyPathMapper.getRemoteURL(pathInfo);
+
+ if (proxyTargetURL == null)
+ {
+ throw new IllegalStateException("Cannot translate the location path info into remote URL. " + pathInfo);
+ }
+
+ String method = request.getMethod();
+ boolean isGetMethod = "GET".equals(method);
+ boolean isPostMethod = "POST".equals(method);
+ boolean isPostMultipartMethod = isPostMethod && ServletFileUpload.isMultipartContent(request);
+
+ HttpMethodBase httpMethodForProxyRequest = null;
+
+ if (isGetMethod)
+ {
+ httpMethodForProxyRequest = new GetMethod(proxyTargetURL);
+ }
+ else if (isPostMethod)
+ {
+ httpMethodForProxyRequest = new PostMethod(proxyTargetURL);
+
+ if (isPostMultipartMethod)
+ {
+ postMultipartParams((PostMethod) httpMethodForProxyRequest, request);
+ }
+ else
+ {
+ postFormParams((PostMethod) httpMethodForProxyRequest, request);
+ }
+ }
+ else
+ {
+ throw new IOException("Unsupported method: " + method);
+ }
+
+ if (cookiePolicy != null)
+ {
+ httpMethodForProxyRequest.getParams().setCookiePolicy(cookiePolicy);
+ }
+
+ // redirection should be adjusted with local host header...
+ httpMethodForProxyRequest.setFollowRedirects(false);
+
+ String queryString = request.getQueryString();
+
+ if (queryString != null)
+ {
+ httpMethodForProxyRequest.setQueryString(queryString);
+ }
+
+ setProxyRequestHeaders(httpMethodForProxyRequest, request);
+
+ if (isPostMultipartMethod)
+ {
+ postMultipartParams((PostMethod) httpMethodForProxyRequest, request);
+ }
+ else if (isPostMethod)
+ {
+ postFormParams((PostMethod) httpMethodForProxyRequest, request);
+ }
+
+ try
+ {
+ int proxyResponseCode = httpClient.executeMethod(httpMethodForProxyRequest);
+
+ // Check if the proxy response is a redirect
+ if (proxyResponseCode >= HttpServletResponse.SC_MULTIPLE_CHOICES /* 300 */
+ && proxyResponseCode < HttpServletResponse.SC_NOT_MODIFIED /* 304 */)
+ {
+ String location = httpMethodForProxyRequest.getResponseHeader(LOCATION_HEADER).getValue();
+
+ if (location == null)
+ {
+ throw new IOException("Recieved status code: " + proxyResponseCode + " but no " + LOCATION_HEADER + " header was found in the response");
+ }
+
+ // Modify the redirect to go to this proxy servlet rather that the proxied host
+ // FYI, according to rfc2616, "Location" header value must be an absolute URI.
+ String localPath = proxyPathMapper.getLocalPath(location);
+
+ // 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...
+ if (localPath == null)
+ {
+ HttpReverseProxyPathMapper proxyPathMapperByLocation = proxyPathMapperProvider.findMapperByRemoteURL(location);
+
+ if (proxyPathMapperByLocation != null)
+ {
+ localPath = proxyPathMapperByLocation.getLocalPath(location);
+ }
+ }
+
+ String redirectLocation = null;
+
+ if (localPath == null)
+ {
+ if (log.isWarnEnabled())
+ {
+ log.warn("Cannot translate the redirect location to local path. {}", location);
+ }
+
+ redirectLocation = location;
+ }
+ else
+ {
+ if (prependLocalBaseURL) {
+ redirectLocation = localBaseURL + localPath;
+ } else {
+ redirectLocation = request.getContextPath() + request.getServletPath() + localPath;
+ }
+ }
+
+ response.sendRedirect(redirectLocation);
+
+ return;
+ }
+ else if (proxyResponseCode == 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.
+ response.setIntHeader(CONTENT_LENGTH_HEADER, 0);
+ response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+
+ return;
+ }
+
+ // Pass the response code back to the client
+ response.setStatus(proxyResponseCode);
+
+ String responseContentType = null;
+
+ // Pass response headers back to the client
+ Header[] headerArrayResponse = httpMethodForProxyRequest.getResponseHeaders();
+
+ for (Header header : headerArrayResponse)
+ {
+ response.setHeader(header.getName(), header.getValue());
+
+ if (responseContentType == null && header.getName().equalsIgnoreCase(CONTENT_TYPE_HEADER))
+ {
+ responseContentType = header.getValue();
+ }
+ }
+
+ // Send the content to the client
+ sendContentToClient(request, response, httpMethodForProxyRequest, responseContentType);
+ }
+ finally
+ {
+ // be sure the connection is released back to the connection manager...
+ httpMethodForProxyRequest.releaseConnection();
+ }
+ }
+
+ private void sendContentToClient(HttpServletRequest request, HttpServletResponse response, HttpMethodBase httpMethodForProxyRequest, String responseContentType) throws IOException
+ {
+ InputStream in = null;
+ Reader reader = null;
+ OutputStream out = null;
+ Writer writer = null;
+
+ try
+ {
+ in = httpMethodForProxyRequest.getResponseBodyAsStream();
+
+ // According to javadoc of httpclient, getResponseBodyAsStream() can return null
+ // if the response has no body.
+ if (in != null)
+ {
+ out = response.getOutputStream();
+
+ RewriterController rewriterController = proxyPathMapperProvider.findRewriterController(request);
+ Rewriter rewriter = proxyPathMapperProvider.findRewriter(request);
+
+ if (rewriterController == null || rewriter == null)
+ {
+ IOUtils.copy(in, out);
+ out.flush();
+ }
+ else
+ {
+ String mimeTypeForParserAdaptor = "text/html";
+
+ if (responseContentType != null)
+ {
+ int offset = responseContentType.indexOf(';');
+
+ if (offset > 0)
+ {
+ mimeTypeForParserAdaptor = mimeTypeForParserAdaptor.substring(0, offset).trim();
+ }
+ else
+ {
+ mimeTypeForParserAdaptor = responseContentType;
+ }
+ }
+
+ ParserAdaptor parserAdaptor = rewriterController.createParserAdaptor(mimeTypeForParserAdaptor);
+ String responseCharSet = httpMethodForProxyRequest.getResponseCharSet();
+
+ if (responseCharSet != null)
+ {
+ reader = new InputStreamReader(in, responseCharSet);
+ writer = new OutputStreamWriter(out, responseCharSet);
+ }
+ else
+ {
+ reader = new InputStreamReader(in);
+ writer = new OutputStreamWriter(out);
+ }
+
+ rewriter.rewrite(parserAdaptor, reader, writer);
+ writer.flush();
+ }
+ }
+ }
+ catch (RewriterException e)
+ {
+ throw new IOException(e.getLocalizedMessage());
+ }
+ finally
+ {
+ if (reader != null)
+ {
+ try { reader.close(); } catch (Exception ce) { }
+ }
+ if (in != null)
+ {
+ try { in.close(); } catch (Exception ce) { }
+ }
+ if (writer != null)
+ {
+ try { writer.close(); } catch (Exception ce) { }
+ }
+ if (out != null)
+ {
+ try { out.close(); } catch (Exception ce) { }
+ }
+ }
+ }
+
+ private void setProxyRequestHeaders(HttpMethod httpMethodForProxyRequest, HttpServletRequest request)
+ {
+ // Get an Enumeration of all of the header names sent by the client
+ for (Enumeration enumHeaderNames = request.getHeaderNames(); enumHeaderNames.hasMoreElements(); )
+ {
+ String headerName = (String) enumHeaderNames.nextElement();
+
+ if (headerName.equalsIgnoreCase(CONTENT_LENGTH_HEADER))
+ continue;
+
+ // As per the Java Servlet API 2.5 documentation:
+ // Some headers, such as Accept-Language can be sent by clients
+ // as several headers each with a different value rather than
+ // sending the header as a comma separated list.
+ // Thus, we get an Enumeration of the header values sent by the client
+
+ for (Enumeration enumHeaderValues = request.getHeaders(headerName); enumHeaderValues.hasMoreElements(); )
+ {
+ String headerValue = (String) enumHeaderValues.nextElement();
+
+ // In case the proxy host is running multiple virtual servers,
+ // rewrite the Host header to ensure that we get content from
+ // the correct virtual server
+ if (headerName.equalsIgnoreCase(HOST_HEADER))
+ {
+ headerValue = hostHeaderValue;
+ }
+
+ Header header = new Header(headerName, headerValue);
+
+ // Set the same header on the proxy request
+ httpMethodForProxyRequest.setRequestHeader(header);
+ }
+ }
+ }
+
+ private void postFormParams(PostMethod httpMethodForProxyRequest, HttpServletRequest request)
+ {
+ Map<String, String[]> paramsMap = (Map<String, String[]>) request.getParameterMap();
+ List<NameValuePair> paramNameValuePairs = new ArrayList<NameValuePair>();
+
+ for (String paramName : paramsMap.keySet())
+ {
+ String [] paramValues = paramsMap.get(paramName);
+
+ for (String paramValue : paramValues)
+ {
+ NameValuePair nameValuePair = new NameValuePair(paramName, paramValue);
+ paramNameValuePairs.add(nameValuePair);
+ }
+ }
+
+ httpMethodForProxyRequest.setRequestBody(paramNameValuePairs.toArray(new NameValuePair[] {}));
+ }
+
+ private void postMultipartParams(PostMethod httpMethodForProxyRequest, HttpServletRequest request) throws IOException
+ {
+ DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
+
+ if (maxFileUploadSize > 0)
+ {
+ fileItemFactory.setSizeThreshold(maxFileUploadSize);
+ }
+
+ if (fileUploadDir != null)
+ {
+ fileItemFactory.setRepository(fileUploadDir);
+ }
+
+ ServletFileUpload fileUpload = new ServletFileUpload(fileItemFactory);
+
+ try
+ {
+ List<FileItem> fileItems = (List<FileItem>) fileUpload.parseRequest(request);
+ Part [] parts = new Part[fileItems.size()];
+ int i = 0;
+
+ for (FileItem fileItem : fileItems)
+ {
+ if (fileItem.isFormField())
+ {
+ parts[i] = (new StringPart(fileItem.getFieldName(), fileItem.getString()));
+ }
+ else
+ {
+ PartSource partSource = null;
+
+ if (fileItem.isInMemory())
+ {
+ partSource = new ByteArrayPartSource(fileItem.getName(), fileItem.get());
+ }
+ else
+ {
+ partSource = new FilePartSource(fileItem.getFieldName(), ((DiskFileItem) fileItem).getStoreLocation());
+ }
+
+ parts[i] = (new FilePart(fileItem.getFieldName(), partSource));
+ }
+
+ i++;
+ }
+
+ MultipartRequestEntity multipartRequestEntity = new MultipartRequestEntity(parts, httpMethodForProxyRequest.getParams());
+ httpMethodForProxyRequest.setRequestEntity(multipartRequestEntity);
+
+ // The current content-type header (received from the client) IS of
+ // type "multipart/form-data", but the content-type header also
+ // contains the chunk boundary string of the chunks. Currently, this
+ // header is using the boundary of the client request, since we
+ // blindly copied all headers from the client request to the proxy
+ // request. However, we are creating a new request with a new chunk
+ // boundary string, so it is necessary that we re-set the
+ // content-type string to reflect the new chunk boundary string
+ httpMethodForProxyRequest.setRequestHeader(CONTENT_TYPE_HEADER, multipartRequestEntity.getContentType());
+ }
+ catch (FileUploadException fileUploadException)
+ {
+ throw new IOException(fileUploadException.getLocalizedMessage());
+ }
+ }
+
+}
+
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/MappingRewriterController.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/MappingRewriterController.java?rev=816126&r1=816125&r2=816126&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/MappingRewriterController.java (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/MappingRewriterController.java Thu Sep 17 10:22:06 2009
@@ -18,6 +18,7 @@
import java.io.File;
import java.io.FileReader;
+import java.io.InputStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collections;
@@ -28,13 +29,13 @@
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.apache.portals.applications.webcontent.rewriter.html.SwingParserAdaptor;
import org.apache.portals.applications.webcontent.rewriter.rules.Ruleset;
import org.apache.portals.applications.webcontent.rewriter.xml.SaxParserAdaptor;
import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.xml.Unmarshaller;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
@@ -247,5 +248,32 @@
return ruleset;
}
+
+ public Ruleset loadRuleset( InputStream input )
+ {
+ Ruleset ruleset = null;
+ try
+ {
+ DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = dbfactory.newDocumentBuilder();
+
+ InputSource source = new InputSource(input);
+
+ Document doc = builder.parse(source);
+
+ Unmarshaller unmarshaller = new Unmarshaller(this.mapper);
+
+ ruleset = (Ruleset) unmarshaller.unmarshal(doc);
+ ruleset.sync();
+ rulesets.put(ruleset.getId(), ruleset);
+
+ }
+ catch (Throwable t)
+ {
+ log.error("ForwardService: Could not unmarshal: " + input, t);
+ }
+
+ return ruleset;
+ }
}
\ No newline at end of file
Modified: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/RewriterController.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/RewriterController.java?rev=816126&r1=816125&r2=816126&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/RewriterController.java (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/rewriter/RewriterController.java Thu Sep 17 10:22:06 2009
@@ -16,6 +16,7 @@
*/
package org.apache.portals.applications.webcontent.rewriter;
+import java.io.InputStream;
import java.io.Reader;
import org.apache.portals.applications.webcontent.rewriter.rules.Ruleset;
@@ -66,7 +67,7 @@
throws RewriterException;
/**
- * Loads a XML-based Rewriter Ruleset given a stream to the XML configuration.
+ * Loads a XML-based Rewriter Ruleset given a reader to the XML configuration.
*
* @param reader The stream to the XML configuration.
* @return A Ruleset configuration tree.
@@ -81,4 +82,12 @@
*/
Ruleset lookupRuleset(String id);
+ /**
+ * Loads a XML-based Rewriter Ruleset given a stream to the XML configuration.
+ *
+ * @param reader The stream to the XML configuration.
+ * @return A Ruleset configuration tree.
+ */
+ Ruleset loadRuleset(InputStream input);
+
}
Added: portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy-urlmappings.properties
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy-urlmappings.properties?rev=816126&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy-urlmappings.properties (added)
+++ portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy-urlmappings.properties Thu Sep 17 10:22:06 2009
@@ -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.
+# ------------------------------------------------------------------------
+#
+# Reverse Proxy URL Mappings Configuration
+#
+# $Id$
+#
+# ------------------------------------------------------------------------
+
+# Note: Specify the local path info prefix and remote base url after "ReverseProxyPathURL".
+# Also, you can specify rewriting rules by putting rules mapping configuration and rules configuration
+# for the specific local path after "ReverseProxyRewriter".
+
+ReverseProxyPathURL /apache/ http://www.apache.org/
+#ReverseProxyRewriter /apache/ /WEB-INF/conf/rproxy-rewriter-rules-mapping.xml /WEB-INF/conf/rproxy-rewriter-rules-mapping.xml
+
+ReverseProxyPathURL /portals/ http://portals.apache.org/
+#ReverseProxyRewriter /portals/ /WEB-INF/conf/rproxy-rewriter-rules-mapping.xml /WEB-INF/conf/rproxy-rewriter-rules-mapping.xml
Propchange: portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy-urlmappings.properties
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy-urlmappings.properties
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy-urlmappings.properties
------------------------------------------------------------------------------
svn:mime-type = text/plain