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/25 16:07:55 UTC

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

Author: woonsan
Date: Fri Sep 25 14:07:54 2009
New Revision: 818855

URL: http://svn.apache.org/viewvc?rev=818855&view=rev
Log:
APA-17: Adding configuration auto-refresh feature. Also, generalizing the way of sso auth info retrieval.

Added:
    portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/AuthScopeCredentials.java   (with props)
    portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultAuthScopeCredentialsImpl.java   (with props)
    portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestAuthScopeCredentials.java   (with props)
Modified:
    portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyConstants.java
    portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyServlet.java
    portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java
    portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy.properties
    portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/web.xml

Added: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/AuthScopeCredentials.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/AuthScopeCredentials.java?rev=818855&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/AuthScopeCredentials.java (added)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/AuthScopeCredentials.java Fri Sep 25 14:07:54 2009
@@ -0,0 +1,43 @@
+/*
+ * 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 org.apache.http.auth.AuthScope;
+
+/**
+ * Authentication Scope and Credentials holder interface to be used in reverse proxy component.
+ * 
+ * @version $Id$
+ */
+public interface AuthScopeCredentials
+{
+    
+    public String getSiteURL();
+    
+    public AuthScope getAuthScope();
+    
+    public String getUsername();
+    
+    public String getPassword();
+    
+    public boolean isFormAuthentication();
+    
+    public String getFormUserField();
+    
+    public String getFormPasswordField();
+    
+}

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

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

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

Modified: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyConstants.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyConstants.java?rev=818855&r1=818854&r2=818855&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyConstants.java (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyConstants.java Fri Sep 25 14:07:54 2009
@@ -21,8 +21,8 @@
     
     String HTTP_HEADER_LOCATION = "Location";
     
-    String REVERSE_PROXY_PATH_MAPPER_ATTRIBUTE = "org.apache.portals.applications.webcontent.proxy.reverseProxyPathMapper";
+    String PATH_MAPPER = "org.apache.portals.applications.webcontent.proxy.reverseProxyPathMapper";
     
-    String REVERSE_PROXY_AUTH_CREDS_MAP_ATTRIBUTE = "org.apache.portals.applications.webcontent.proxy.reverseProxyAuthCredsMap";
+    String USER_AUTH_SCOPE_CREDS = "org.apache.portals.applications.webcontent.proxy.reverseProxyUserAuthScopeCreds";
     
 }

Added: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultAuthScopeCredentialsImpl.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultAuthScopeCredentialsImpl.java?rev=818855&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultAuthScopeCredentialsImpl.java (added)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultAuthScopeCredentialsImpl.java Fri Sep 25 14:07:54 2009
@@ -0,0 +1,174 @@
+/*
+ * 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.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URLDecoder;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.http.auth.AuthScope;
+import org.apache.portals.applications.webcontent.proxy.AuthScopeCredentials;
+
+/**
+ * Authentication Scope and Credentials holder class to be used in reverse proxy component.
+ * 
+ * @version $Id$
+ */
+public class DefaultAuthScopeCredentialsImpl implements AuthScopeCredentials, Serializable
+{
+    private static final long serialVersionUID = 1L;
+    
+    private URI authCredsInURI;
+    private String siteURL;
+    private transient AuthScope authScope;
+    private String username;
+    private String password;
+    private String formUserField;
+    private String formPasswordField;
+    
+    public DefaultAuthScopeCredentialsImpl(URI authCredsInURI) throws URISyntaxException
+    {
+        this.authCredsInURI = authCredsInURI;
+        
+        String rawUserInfo = this.authCredsInURI.getRawUserInfo();
+        
+        if (rawUserInfo == null)
+        {
+            throw new URISyntaxException(authCredsInURI.toString(), "Userinfo is not defined in the uri.");
+        }
+        
+        String [] usernameAndPassword = StringUtils.split(rawUserInfo, ":");
+        
+        if (usernameAndPassword.length != 2)
+        {
+            throw new URISyntaxException(authCredsInURI.toString(), "Userinfo is not well-formed in the uri.");
+        }
+        
+        username = usernameAndPassword[0];
+        password = usernameAndPassword[1];
+        
+        int offset = username.indexOf('=');
+        
+        try
+        {
+            if (offset == -1)
+            {
+                username = URLDecoder.decode(username, "UTF-8");
+                password = URLDecoder.decode(password, "UTF-8");
+            }
+            else
+            {
+                formUserField = URLDecoder.decode(username.substring(0, offset), "UTF-8");
+                username = URLDecoder.decode(username.substring(offset + 1), "UTF-8");
+                
+                offset = password.indexOf('=');
+                
+                formPasswordField = URLDecoder.decode(password.substring(0, offset), "UTF-8");
+                password = URLDecoder.decode(password.substring(offset + 1), "UTF-8");
+            }
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            throw new URISyntaxException(authCredsInURI.toString(), "Userinfo is not correctly encoded.");
+        }
+    }
+    
+    public String getSiteURL()
+    {
+        if (siteURL == null && authCredsInURI != null)
+        {
+            String scheme = authCredsInURI.getScheme();
+            String host = authCredsInURI.getHost();
+            int port = authCredsInURI.getPort();
+            String path = authCredsInURI.getPath();
+            String query = authCredsInURI.getQuery();
+            
+            StringBuilder sb = new StringBuilder(100);
+            sb.append(scheme).append("://");
+            sb.append(host);
+            
+            if (port != -1)
+            {
+                sb.append(':').append(port);
+            }
+            
+            if (path != null)
+            {
+                sb.append(path);
+            }
+            
+            if (query != null)
+            {
+                sb.append('?').append(query);
+            }
+            
+            siteURL = sb.toString();
+        }
+        
+        return siteURL;
+    }
+    
+    public AuthScope getAuthScope()
+    {
+        if (authScope == null && authCredsInURI != null)
+        {
+            String host = authCredsInURI.getHost();
+            int port = authCredsInURI.getPort();
+            String realm = authCredsInURI.getFragment();
+            
+            if (StringUtils.isBlank(realm))
+            {
+                authScope = new AuthScope(host, port);
+            }
+            else
+            {
+                authScope = new AuthScope(host, port, realm);
+            }
+        }
+        
+        return authScope;
+    }
+    
+    public String getUsername()
+    {
+        return username;
+    }
+    
+    public String getPassword()
+    {
+        return password;
+    }
+    
+    public boolean isFormAuthentication()
+    {
+        return (formUserField != null && formPasswordField != null);
+    }
+    
+    public String getFormPasswordField()
+    {
+        return formPasswordField;
+    }
+    
+    public String getFormUserField()
+    {
+        return formUserField;
+    }
+    
+}

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

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

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

Modified: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyServlet.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyServlet.java?rev=818855&r1=818854&r2=818855&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyServlet.java (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyServlet.java Fri Sep 25 14:07:54 2009
@@ -16,6 +16,7 @@
  */
 package org.apache.portals.applications.webcontent.proxy.impl;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.InetAddress;
@@ -36,9 +37,11 @@
 import org.apache.commons.collections.keyvalue.DefaultKeyValue;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.PropertiesConfiguration;
+import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang.ArrayUtils;
 import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.math.NumberUtils;
 import org.apache.http.HttpHost;
 import org.apache.http.client.params.ClientParamBean;
 import org.apache.http.conn.params.ConnManagerParamBean;
@@ -67,15 +70,65 @@
     
     private static Logger log = LoggerFactory.getLogger(DefaultHttpReverseProxyServlet.class);
     
-    protected HttpReverseProxyPathMapperProvider proxyPathMapperProvider;
     protected HttpReverseProxyService proxyService;
     
-    private Configuration configuration;
+    private PropertiesConfiguration configuration;
+    
+    private long configurationRefreshDelay;
+    
+    private FileChangedReloadingStrategy configReloadingStrategy;
     
     @Override
     public void init(ServletConfig config) throws ServletException
     {
-        loadConfiguration(config);
+        super.init(config);
+        
+        configurationRefreshDelay = NumberUtils.toLong(getServletConfig().getInitParameter("reverseproxy.configuration.refresh.delay"), 0L);
+        
+        if (configurationRefreshDelay > 0L)
+        {
+            configReloadingStrategy = new FileChangedReloadingStrategy()
+            {
+                @Override
+                public void reloadingPerformed()
+                {
+                    super.reloadingPerformed();
+                    
+                    try
+                    {
+                        if (proxyService != null)
+                        {
+                            recreateHttpReverseProxyService();
+                        }
+                    }
+                    catch (Exception e)
+                    {
+                        if (log.isDebugEnabled())
+                        {
+                            log.error("Failed to recreate reverse proxy service.", e);
+                        }
+                        else
+                        {
+                            log.error("Failed to recreate reverse proxy service. {}", e.toString());
+                        }
+                    }
+                }
+            };
+            
+            configReloadingStrategy.setRefreshDelay(Math.max(configurationRefreshDelay, 2000));
+        }
+        
+        loadConfiguration();
+        
+        recreateHttpReverseProxyService();
+    }
+    
+    private void recreateHttpReverseProxyService() throws ServletException
+    {
+        if (log.isDebugEnabled())
+        {
+            log.debug("DefaultHttpReverseProxyServlet is to initialize reverse proxy service component...");
+        }
         
         List<HttpReverseProxyPathMapper> proxyPathMappers = new ArrayList<HttpReverseProxyPathMapper>();
         
@@ -102,12 +155,12 @@
                 
                 if (ArrayUtils.getLength(rewriterRuleConfs) == 2)
                 {
-                    RewriterController rewriterController = createRewriterController(config, rewriterRuleConfs[0], rewriterClassNames, adaptorClassNames);
+                    RewriterController rewriterController = createRewriterController(rewriterRuleConfs[0], rewriterClassNames, adaptorClassNames);
                     
                     if (rewriterController != null)
                     {
                         rewriterControllerPairs.add(new DefaultKeyValue(localBasePath, rewriterController));
-                        Rewriter rewriter = createRewriter(config, rewriterController, rewriterRuleConfs[1]);
+                        Rewriter rewriter = createRewriter(rewriterController, rewriterRuleConfs[1]);
                         rewriterPairs.add(new DefaultKeyValue(localBasePath, rewriter));
                     }
                 }
@@ -118,19 +171,19 @@
             throw new ServletException("Failed to initialize url mappings. " + e);
         }
         
-        proxyPathMapperProvider = new DefaultHttpReverseProxyPathMapperProviderImpl(proxyPathMappers, rewriterControllerPairs, rewriterPairs);
-        proxyService = new RewritableHttpReverseProxyServiceImpl(proxyPathMapperProvider);
+        HttpReverseProxyPathMapperProvider proxyPathMapperProvider = new DefaultHttpReverseProxyPathMapperProviderImpl(proxyPathMappers, rewriterControllerPairs, rewriterPairs);
+        HttpReverseProxyService tempProxyService = new RewritableHttpReverseProxyServiceImpl(proxyPathMapperProvider);
         
         Configuration serverConf = configuration.subset("proxy.server");
         
         if (!StringUtils.isBlank(serverConf.getString("hostname")))
         {
-            ((RewritableHttpReverseProxyServiceImpl) proxyService).setHostHeaderValue(serverConf.getString("hostname"));
+            ((RewritableHttpReverseProxyServiceImpl) tempProxyService).setHostHeaderValue(serverConf.getString("hostname"));
         }
         
         if (!StringUtils.isBlank(serverConf.getString("baseurl")))
         {
-            ((RewritableHttpReverseProxyServiceImpl) proxyService).setLocalBaseURL(serverConf.getString("baseurl"));
+            ((RewritableHttpReverseProxyServiceImpl) tempProxyService).setLocalBaseURL(serverConf.getString("baseurl"));
         }
         
         Configuration clientParamsConf = configuration.subset("proxy.http.client.param");
@@ -139,7 +192,7 @@
         {
             HttpParams clientParams = new BasicHttpParams();
             setBeanPropertiesByConfiguration(new ClientParamBean(clientParams), clientParamsConf);
-            ((RewritableHttpReverseProxyServiceImpl) proxyService).setClientParams(clientParams);
+            ((RewritableHttpReverseProxyServiceImpl) tempProxyService).setClientParams(clientParams);
         }
         
         Configuration connManagerParamsConf = configuration.subset("proxy.http.connManager.param");
@@ -184,10 +237,41 @@
                 connManagerParamBean.setConnectionsPerRoute(connPerRouteBean);
             }
             
-            ((RewritableHttpReverseProxyServiceImpl) proxyService).setConnectionManagerParams(connManagerParams);
+            ((RewritableHttpReverseProxyServiceImpl) tempProxyService).setConnectionManagerParams(connManagerParams);
         }
         
-        proxyService.initialize();
+        Configuration ssoUserConf = configuration.subset("proxy.sso.user");
+        
+        try
+        {
+            ((RewritableHttpReverseProxyServiceImpl) tempProxyService).setUserAuthScopeCredentialsPropertyPath(ssoUserConf.getString("userAuthScopeCredentialsPropertyPath"));
+        }
+        catch (Exception e)
+        {
+        }
+        
+        try
+        {
+            ((RewritableHttpReverseProxyServiceImpl) tempProxyService).setKeepAuthScopeCredentialsInSession(ssoUserConf.getBoolean("keepAuthScopeCredentialsInSession", true));
+        }
+        catch (Exception e)
+        {
+        }
+        
+        tempProxyService.initialize();
+        
+        HttpReverseProxyService oldProxyService = proxyService;
+        proxyService = tempProxyService;
+        
+        if (log.isInfoEnabled())
+        {
+            log.info("DefaultHttpReverseProxyServlet has (re)initialized reverse proxy service component...");
+        }
+        
+        if (oldProxyService != null)
+        {
+            oldProxyService.destroy();
+        }
     }
     
     public void destroy()
@@ -203,6 +287,15 @@
     public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
     {
         proxyService.invoke(request, response);
+        
+        try
+        {
+            // dummy read for refreshing... 
+            configuration.getString("proxy.reverse.pass");
+        }
+        catch (Exception e)
+        {
+        }
     }
     
     public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
@@ -210,19 +303,19 @@
         doGet(request, response);
     }
     
-    private RewriterController createRewriterController(ServletConfig config, String rulesMappingResourcePath, String [] rewriterClassNames, String [] adaptorClassNames) throws Exception
+    private RewriterController createRewriterController(String rulesMappingResourcePath, String [] rewriterClassNames, String [] adaptorClassNames) throws Exception
     {
-        return new MappingRewriterController(config.getServletContext().getRealPath(rulesMappingResourcePath), buildClassList(rewriterClassNames), buildClassList(adaptorClassNames));
+        return new MappingRewriterController(getServletContext().getRealPath(rulesMappingResourcePath), buildClassList(rewriterClassNames), buildClassList(adaptorClassNames));
     }
     
-    private Rewriter createRewriter(ServletConfig config, RewriterController rwc, String rewriterRulesResourcePath) throws Exception
+    private Rewriter createRewriter(RewriterController rwc, String rewriterRulesResourcePath) throws Exception
     {
         Rewriter rewriter = null;
         InputStream rewriterRulesInput = null;
         
         try
         {
-            rewriterRulesInput = config.getServletContext().getResourceAsStream(rewriterRulesResourcePath);
+            rewriterRulesInput = getServletContext().getResourceAsStream(rewriterRulesResourcePath);
             rewriter = rwc.createRewriter(rwc.loadRuleset(rewriterRulesInput));
         }
         finally
@@ -286,7 +379,13 @@
             }
         }
         
-        secure = routeConf.getBoolean("secure", false);
+        try
+        {
+            secure = routeConf.getBoolean("secure", false);
+        }
+        catch (Exception e)
+        {
+        }
         
         try 
         {
@@ -339,7 +438,15 @@
         String scheme = null;
         
         hostname = hostConf.getString("hostname");
-        port = hostConf.getInt("port", 0);
+        
+        try
+        {
+            port = hostConf.getInt("port", 0);
+        }
+        catch (Exception e)
+        {
+        }
+        
         scheme = hostConf.getString("scheme");
         
         if (StringUtils.isBlank(hostname))
@@ -394,22 +501,40 @@
         return null;
     }
     
-    private void loadConfiguration(ServletConfig servletConfig) throws ServletException
+    private void loadConfiguration() throws ServletException
     {
-        String configResourcePath = servletConfig.getInitParameter("reverseproxy.configuration");
+        String configResourcePath = getServletConfig().getInitParameter("reverseproxy.configuration");
         
         if (configResourcePath == null)
         {
             configResourcePath = "/WEB-INF/conf/reverseproxy.properties";
         }
         
+        File configResourceFile = null;
+        
+        try
+        {
+            configResourceFile = new File(getServletContext().getRealPath(configResourcePath));
+        }
+        catch (Exception e)
+        {
+        }
+        
         InputStream configInput = null;
         
         try
         {
-            configInput = servletConfig.getServletContext().getResourceAsStream(configResourcePath);
-            configuration = new PropertiesConfiguration();
-            ((PropertiesConfiguration) configuration).load(configInput);
+            if (configResourceFile != null && configResourceFile.isFile() && configReloadingStrategy != null)
+            {
+                configuration = new PropertiesConfiguration(configResourceFile);
+                configuration.setReloadingStrategy(configReloadingStrategy);
+            }
+            else
+            {
+                configInput = getServletContext().getResourceAsStream(configResourcePath);
+                configuration = new PropertiesConfiguration();
+                ((PropertiesConfiguration) configuration).load(configInput);
+            }
         }
         catch (Exception e)
         {

Modified: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java?rev=818855&r1=818854&r2=818855&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java Fri Sep 25 14:07:54 2009
@@ -23,19 +23,23 @@
 import java.io.OutputStreamWriter;
 import java.io.Reader;
 import java.io.Writer;
+import java.net.URI;
+import java.util.ArrayList;
 import java.util.Enumeration;
-import java.util.Map;
+import java.util.List;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 
+import org.apache.commons.beanutils.PropertyUtils;
 import org.apache.commons.io.IOUtils;
+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.auth.AuthScope;
 import org.apache.http.auth.Credentials;
+import org.apache.http.auth.UsernamePasswordCredentials;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.client.methods.HttpPost;
 import org.apache.http.client.methods.HttpRequestBase;
@@ -52,6 +56,7 @@
 import org.apache.http.params.HttpParams;
 import org.apache.http.protocol.HTTP;
 import org.apache.http.util.EntityUtils;
+import org.apache.portals.applications.webcontent.proxy.AuthScopeCredentials;
 import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyConstants;
 import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapper;
 import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapperProvider;
@@ -103,6 +108,15 @@
      */
     private HttpParams clientParams;
     
+    /**
+     * Property Path to find User AuthScope-Credentials for SSO.
+     * <P>The property path value will be evaluated from {@link HttpServletRequest} object.
+     * The property path syntax conforms Apache Commons BeanUtils {@link PropertyUtils#getProperty(Object, String)}.</P>
+     */
+    private String userAuthScopeCredentialsPropertyPath;
+    
+    private boolean keepAuthScopeCredentialsInSession = true;
+    
     public RewritableHttpReverseProxyServiceImpl(HttpReverseProxyPathMapperProvider proxyPathMapperProvider)
     {
         this.proxyPathMapperProvider = proxyPathMapperProvider;
@@ -128,6 +142,16 @@
         this.connectionManagerParams = connectionManagerParams;
     }
     
+    public void setUserAuthScopeCredentialsPropertyPath(String userAuthScopeCredentialsPropertyPath)
+    {
+        this.userAuthScopeCredentialsPropertyPath = userAuthScopeCredentialsPropertyPath;
+    }
+    
+    public void setKeepAuthScopeCredentialsInSession(boolean keepAuthScopeCredentialsInSession)
+    {
+        this.keepAuthScopeCredentialsInSession = keepAuthScopeCredentialsInSession;
+    }
+    
     public void initialize()
     {
         if (clientParams == null)
@@ -158,7 +182,7 @@
     public void invoke(HttpServletRequest request, HttpServletResponse response) throws IOException
     {
         // proxyPathMapper can be injected by using request attribute.
-        HttpReverseProxyPathMapper proxyPathMapper = (HttpReverseProxyPathMapper) request.getAttribute(HttpReverseProxyConstants.REVERSE_PROXY_PATH_MAPPER_ATTRIBUTE);
+        HttpReverseProxyPathMapper proxyPathMapper = (HttpReverseProxyPathMapper) request.getAttribute(HttpReverseProxyConstants.PATH_MAPPER);
         
         String pathInfo = request.getPathInfo();
         
@@ -208,7 +232,7 @@
         // redirection should be adjusted with local host header...
         httpClient.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false);
         // set credentials for this user if available
-        retrieveCredentialsInfos(httpClient, request);
+        setUserCredentialsInfos(httpClient, request);
         
         String method = request.getMethod();
         boolean isGetMethod = "GET".equals(method);
@@ -486,25 +510,56 @@
         }
     }
     
-    private void retrieveCredentialsInfos(DefaultHttpClient httpClient, HttpServletRequest request)
+    private void setUserCredentialsInfos(DefaultHttpClient httpClient, HttpServletRequest request)
     {
-        Map<AuthScope, Credentials> authScopeCredentialsMap = (Map<AuthScope, Credentials>) request.getAttribute(HttpReverseProxyConstants.REVERSE_PROXY_AUTH_CREDS_MAP_ATTRIBUTE);
+        List<AuthScopeCredentials> userAuthScopeCredentials = (List<AuthScopeCredentials>) request.getAttribute(HttpReverseProxyConstants.USER_AUTH_SCOPE_CREDS);
         
-        if (authScopeCredentialsMap == null)
+        if (userAuthScopeCredentials == null)
         {
             HttpSession session = request.getSession(false);
             
             if (session != null)
             {
-                authScopeCredentialsMap = (Map<AuthScope, Credentials>) session.getAttribute(HttpReverseProxyConstants.REVERSE_PROXY_AUTH_CREDS_MAP_ATTRIBUTE);
+                userAuthScopeCredentials = (List<AuthScopeCredentials>) session.getAttribute(HttpReverseProxyConstants.USER_AUTH_SCOPE_CREDS);
+            }
+        }
+        
+        if (userAuthScopeCredentials == null && userAuthScopeCredentialsPropertyPath != null)
+        {
+            try
+            {
+                List<URI> authCredsURIs = (List<URI>) PropertyUtils.getProperty(request, StringUtils.removeStart(userAuthScopeCredentialsPropertyPath, "request."));
+                
+                if (authCredsURIs != null)
+                {
+                    userAuthScopeCredentials = new ArrayList<AuthScopeCredentials>();
+                    
+                    for (URI authCredsURI : authCredsURIs)
+                    {
+                        userAuthScopeCredentials.add(new DefaultAuthScopeCredentialsImpl(authCredsURI));
+                    }
+                    
+                    if (keepAuthScopeCredentialsInSession)
+                    {
+                        request.getSession().setAttribute(HttpReverseProxyConstants.USER_AUTH_SCOPE_CREDS, userAuthScopeCredentials);
+                    }
+                }
+            }
+            catch (Exception e)
+            {
+                if (log.isWarnEnabled())
+                {
+                    log.warn("Cannot access the authScopeCredentials list object by the path, {}. {}", userAuthScopeCredentialsPropertyPath, e);
+                }
             }
         }
         
-        if (authScopeCredentialsMap != null && !authScopeCredentialsMap.isEmpty())
+        if (userAuthScopeCredentials != null && !userAuthScopeCredentials.isEmpty())
         {
-            for (Map.Entry<AuthScope, Credentials> entry : authScopeCredentialsMap.entrySet())
+            for (AuthScopeCredentials authScopeCreds : userAuthScopeCredentials)
             {
-                httpClient.getCredentialsProvider().setCredentials(entry.getKey(), entry.getValue());
+                Credentials creds = new UsernamePasswordCredentials(authScopeCreds.getUsername(), authScopeCreds.getPassword());
+                httpClient.getCredentialsProvider().setCredentials(authScopeCreds.getAuthScope(), creds);
             }
         }
     }

Added: portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestAuthScopeCredentials.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestAuthScopeCredentials.java?rev=818855&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestAuthScopeCredentials.java (added)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestAuthScopeCredentials.java Fri Sep 25 14:07:54 2009
@@ -0,0 +1,156 @@
+/*
+ * 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.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.portals.applications.webcontent.proxy.impl.DefaultAuthScopeCredentialsImpl;
+
+/**
+ * Test case for AuthScopeCredentials with various URIs.
+ * 
+ * @version $Id$
+ */
+public class TestAuthScopeCredentials extends TestCase
+{
+    public void testAuthURIs() throws URISyntaxException
+    {
+        URI uri = URI.create("http://manager:mngpwd@www.localhost.com:8080/manager/list?a=1&b=2");
+        AuthScopeCredentials asc = new DefaultAuthScopeCredentialsImpl(uri);
+        assertEquals("http://www.localhost.com:8080/manager/list?a=1&b=2", asc.getSiteURL());
+        assertEquals("manager", asc.getUsername());
+        assertEquals("mngpwd", asc.getPassword());
+        assertEquals("www.localhost.com", asc.getAuthScope().getHost());
+        assertEquals(8080, asc.getAuthScope().getPort());
+        assertNull(asc.getAuthScope().getRealm());
+        assertFalse(asc.isFormAuthentication());
+        
+        uri = URI.create("http://formuser=manager:formpwd=mngpwd@www.localhost.com:8080/manager/list?a=1&b=2");
+        asc = new DefaultAuthScopeCredentialsImpl(uri);
+        assertEquals("http://www.localhost.com:8080/manager/list?a=1&b=2", asc.getSiteURL());
+        assertEquals("manager", asc.getUsername());
+        assertEquals("mngpwd", asc.getPassword());
+        assertEquals("www.localhost.com", asc.getAuthScope().getHost());
+        assertEquals(8080, asc.getAuthScope().getPort());
+        assertNull(asc.getAuthScope().getRealm());
+        assertTrue(asc.isFormAuthentication());
+        assertEquals("formuser", asc.getFormUserField());
+        assertEquals("formpwd", asc.getFormPasswordField());
+        
+        uri = URI.create("http://formuser=manager:formpwd=mng%3Dpwd@www.localhost.com:8080/manager/list?a=1&b=2");
+        asc = new DefaultAuthScopeCredentialsImpl(uri);
+        assertEquals("http://www.localhost.com:8080/manager/list?a=1&b=2", asc.getSiteURL());
+        assertEquals("manager", asc.getUsername());
+        assertEquals("mng=pwd", asc.getPassword());
+        assertEquals("www.localhost.com", asc.getAuthScope().getHost());
+        assertEquals(8080, asc.getAuthScope().getPort());
+        assertNull(asc.getAuthScope().getRealm());
+        assertTrue(asc.isFormAuthentication());
+        assertEquals("formuser", asc.getFormUserField());
+        assertEquals("formpwd", asc.getFormPasswordField());
+        
+        uri = URI.create("http://manager:mngpwd@www.localhost.com:8080/manager/list#Tomcat%20Manager%20Application");
+        asc = new DefaultAuthScopeCredentialsImpl(uri);
+        assertEquals("http://www.localhost.com:8080/manager/list", asc.getSiteURL());
+        assertEquals("manager", asc.getUsername());
+        assertEquals("mngpwd", asc.getPassword());
+        assertEquals("www.localhost.com", asc.getAuthScope().getHost());
+        assertEquals(8080, asc.getAuthScope().getPort());
+        assertEquals("Tomcat Manager Application", asc.getAuthScope().getRealm());
+        assertFalse(asc.isFormAuthentication());
+    }
+    
+    public void testUseAuthScopeCredsBeanPathRetrieval() throws URISyntaxException, IllegalAccessException, InvocationTargetException, NoSuchMethodException
+    {
+        Request request = new Request();
+        AppRequestContext arc = new AppRequestContext();
+        arc.getObjects().put("org.examples.provider", new UserAuthScopeCredentialsProvider());
+        request.setAttribute("org.examples.request.context", arc);
+        
+        final String propertyPath = "request.attribute(org.examples.request.context).objects(org.examples.provider).userAuthScopeCredentials";
+        
+        List<AuthScopeCredentials> authScopeCreds = (List<AuthScopeCredentials>) PropertyUtils.getProperty(request, StringUtils.removeStart(propertyPath, "request."));
+        assertNotNull(authScopeCreds);
+        assertTrue(authScopeCreds.size() == 2);
+        
+        AuthScopeCredentials asc = authScopeCreds.get(0);
+        assertEquals("manager", asc.getUsername());
+        assertEquals("manager", asc.getPassword());
+        assertEquals("www.localhost.com", asc.getAuthScope().getHost());
+        assertEquals(8080, asc.getAuthScope().getPort());
+        
+        asc = authScopeCreds.get(1);
+        assertEquals("devmgr", asc.getUsername());
+        assertEquals("devmgr", asc.getPassword());
+        assertEquals("www.localhost.com", asc.getAuthScope().getHost());
+        assertEquals(8080, asc.getAuthScope().getPort());
+    }
+    
+    public static class Request
+    {
+        private Map<String, Object> attrs = new HashMap<String, Object>();
+        
+        public void setAttribute(String attrName, Object attrValue)
+        {
+            attrs.put(attrName, attrValue);
+        }
+        
+        public Object getAttribute(String attrName)
+        {
+            return attrs.get(attrName);
+        }
+    }
+    
+    public static class AppRequestContext
+    {
+        private Map<String, Object> objects = new HashMap<String, Object>();
+        
+        public Map<String, Object> getObjects()
+        {
+            return objects;
+        }
+    }
+    
+    public static class UserAuthScopeCredentialsProvider
+    {
+        public List<AuthScopeCredentials> getUserAuthScopeCredentials()
+        {
+            List<AuthScopeCredentials> userAuthScopeCredentials = new ArrayList<AuthScopeCredentials>();
+            
+            try
+            {
+                userAuthScopeCredentials.add(new DefaultAuthScopeCredentialsImpl(URI.create("http://manager:manager@www.localhost.com:8080")));
+                userAuthScopeCredentials.add(new DefaultAuthScopeCredentialsImpl(URI.create("http://devmgr:devmgr@www.localhost.com:8080")));
+            }
+            catch (Exception e)
+            {
+            }
+            
+            return userAuthScopeCredentials;
+        }
+    }
+}

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

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

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

Modified: portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy.properties
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy.properties?rev=818855&r1=818854&r2=818855&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy.properties (original)
+++ portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy.properties Fri Sep 25 14:07:54 2009
@@ -42,6 +42,12 @@
 proxy.http.client.param.allowCircularRedirects = false
 
 
+# Reverse Proxy Single Sign On configurations
+# ... Sets property path from request object to retrieve user's authScopeCredential list object.
+# ... The property path should conform Apache Commons BeanUtils PropUtils.getProperty(Object, String).
+proxy.sso.user.userAuthScopeCredentialsPropertyPath = request.attribute(org.apache.jetspeed.request.RequestContext).objects(org.apache.portals.applications.webcontent.proxy.authCredsProvider).authCredsURIs
+proxy.sso.user.keepAuthScopeCredentialsInSession
+
 # Global HTTP ClientConnectionManager parameters
 # ... You can set various http client connection manager parameters with prefix, 'proxy.http.connManager.param.'.
 # ... Refer to the javadoc of org.apache.http.conn.params.ConnManagerParamBean.
@@ -64,6 +70,7 @@
 
 # ... 'somewhere' is just an example to show the full configurable items...
 proxy.http.route.somewhere.target.hostname = somewhere.localhost.com
+proxy.http.route.somewhere.target.port = 8080
 proxy.http.route.somewhere.maxConnections = 5
 proxy.http.route.somewhere.local = 111.111.111.111
 proxy.http.route.somewhere.secure = false
@@ -91,6 +98,6 @@
 # ... 'somewhere' is just an example to show the full configurable items...
 proxy.reverse.pass.somewhere.local = /somewhere/
 proxy.reverse.pass.somewhere.remote = http://somewhere.localhost.com/
-#proxy.reverse.pass.somewhere.rewriters = ${defaults.htmlRewriter}, ${defaults.xmlRewriter} 
-#proxy.reverse.pass.somewhere.adaptors = ${defaults.htmlAdaptor}, ${defaults.xmlAdaptor}
-#proxy.reverse.pass.somewhere.rules = ${defaults.ruleMappings}, ${defaults.rewriterRules}
+proxy.reverse.pass.somewhere.rewriters = ${defaults.htmlRewriter}, ${defaults.xmlRewriter} 
+proxy.reverse.pass.somewhere.adaptors = ${defaults.htmlAdaptor}, ${defaults.xmlAdaptor}
+proxy.reverse.pass.somewhere.rules = ${defaults.ruleMappings}, ${defaults.rewriterRules}

Modified: portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/web.xml?rev=818855&r1=818854&r2=818855&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/web.xml (original)
+++ portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/web.xml Fri Sep 25 14:07:54 2009
@@ -55,6 +55,10 @@
       <param-name>reverseproxy.configuration</param-name>
       <param-value>/WEB-INF/conf/reverseproxy.properties</param-value>
     </init-param>
+    <init-param>
+      <param-name>reverseproxy.configuration.refresh.delay</param-name>
+      <param-value>60000</param-value>
+    </init-param>
     <load-on-startup>11</load-on-startup>
   </servlet>